I'm looking for an atomic way to pick one ticket from a poll of tickets and give it to someone in PHP. So far I have thought of a few different solutions but I'm not sure how atomic they are (two people must NEVER have the same ticket).
All tickets are pre-generated in the range of 1-N (random numbers as tickets can't be used). The methods I think are viable are:
1) Use a file to store the tickets shuffled and pick the first one and rewrite the file (or pick the last one and only truncate without rewrite). Simplest example:
function NextTicket()
{
$fh = fopen('tickets.txt', 'rw+');
flock($fh, LOCK_EX)) //hopefully this should prevent parallel access
$all = explode("\n", stream_get_contents($arq));
$return = $all[0]; //ticket to be returned
unset($all[0]);
rewind($fh);
ftruncate($fh,0);
fwrite($fh, implode("\n", $all);
fclose($fh);
return $ticket;
}
2) Use a sqlite file to hold all tickets and extract a row at a time (supposes shuffled rows inserted).
function NextTicket()
{
$db = new SQLite3('tickets.sqlite');
$db->exec('BEGIN');
$res = $db->query('SELECT rowid,TI_NUMBER FROM tickets LIMIT 1');
$ticket = $res->fetchArray(SQLITE3_ASSOC);
$db->exec('DELETE FROM tickets WHERE rowid='.$ticket['rowid']);
$db->exec('COMMIT');
return $ticket['TI_NUMBER'];
}
3) Use sqlite as a counter with a single row instead of holding each ticket number in a row (I cannot use this method because the delivery should be random).
function NextTicket()
{
$db = new SQLite3('/tmp/tickets.sqlite');
$db->exec('BEGIN');
$res = $db->query('SELECT rowid,TI_NUMBER FROM tickets LIMIT 1');
$ticket = $res->fetchArray(SQLITE3_ASSOC);
$res = $db->query('UPDATE tickets SET TI_NUMBER=TI_NUMBER+1 WHERE rowid='.$ticket['rowid']);
$db->exec('COMMIT');
return $ticket['TI_NUMBER'];
}
4) Other approaches? Mysql 5.6 database is also available. Auto increment cannot be used as it's sequential and I need random row from the set. Maybe combining 1 and 3 to get a specific position from inside the shuffled file based in the auto increment.
Has anyone faced a similar issue? How was it solved?
Thanks in advance.
Aucun commentaire:
Enregistrer un commentaire