I would like to find out a good way to go about implementing a jobs queue using postgres and PDO (php).
Basically I have an events table where the app's events are logged and some form of scheduled processor (say proc) that will regularly take care of retrieving an event at a time and execute certain routines in response to it (and depending on the nature of the event it self).
Clearly, as soon as an instance of proc starts working on an event, I need to mark the row as ongoing, like that:
UPDATE events SET status = "ongoing" WHERE id = 3; -- >> QUERY 1 <<
Fine! proc can now do its business according to the type of event and its payload and no other thread will deal with the event of id = 3 as it is now ongoing.
When proc is done with event 3 it marks it as 'resolved' so that, again, no other thread will, in the future, take care of event 3. Here we go:
UPDATE events SET status = "resolved" WHERE id = 3; -- >> QUERY 2 <<
Now my concern is that this must be done inside a transaction, so I would have:
BEGIN;
-- QUERY 1
-- VARIOUS OTHER QUERIES TAKING A LOT OF TIME
-- QUERY 2
COMMIT;
As far as I know, when inside a transaction, the change operated by QUERY 1 is only visible to other threads when the whole transaction is committed. That implies that while proc (instance 1) is doing the time consuming work (the code between QUERY 1 and QUERY 2) some other instance of it might read the events table and think that no one is taking care of event 3 and move on doing stuff with it. Clearly that would mess up the whole thing and corrupt the state of the queue.
So my question is: how do I preserve the transactional style of proc and, at the same time, make the change of state of event 3 (from free to ongoing) immediately visible from outside the transaction?