▲ | thewisenerd 5 days ago | ||||||||||||||||
t1: select for update where status=pending, set status=processing t2: update, set status=completed|error these are two independent, very short transactions? or am i misunderstanding something here? -- edit: i think i'm not seeing what the 'transaction at start of processor' logic is; i'm thinking more of a polling logic
this obviously has the drawback of knowing how long to sleep for; and tasks not getting "instantly" picked up, but eh, tradeoffs. | |||||||||||||||||
▲ | diarrhea 5 days ago | parent | next [-] | ||||||||||||||||
Your version makes sense. I understood the OP's approach as being different. Two (very, if indexed properly) short transactions at start and end are a good solution. One caveat is that the worker can die after t1, but before t2 - hence jobs need a timeout concept and should be idempotent for safe retrying. This gets you "at least once" processing. > this obviously has the drawback of knowing how long to sleep for; and tasks not getting "instantly" picked up, but eh, tradeoffs. Right. I've had success with exponential backoff sleep. In a busy system, means sleeps remain either 0 or very short. Another solution is Postgres LISTEN/NOTIFY: workers listen for events and PG wakes them up. On the happy path, this gets instant job pickup. This should be allowed to fail open and understood as a happy path optimization. As delivery can fail, this gets you "at most once" processing (which is why this approach by itself it not enough to drive a persistent job queue). A caveat with LISTEN/NOTIFY is that it doesn't scale due to locking [1]. [1]: https://www.recall.ai/blog/postgres-listen-notify-does-not-s... | |||||||||||||||||
| |||||||||||||||||
▲ | maxbond 5 days ago | parent | prev [-] | ||||||||||||||||
They're proposing doing it in one transaction as a heartbeat. > - If you find an unlocked task in 'executing', you know the processor died for sure. No heuristic needed | |||||||||||||||||
|