Expand description
The subscriber: the loop that turns queued messages back into function calls.
One task per process, started by crate::run_with when the app subscribes
to anything. It does three things in a cycle:
- Wait — for a
NOTIFYfrom a publisher, or for[queues] poll_secs, whichever comes first. The notification is what makes delivery feel instant; the timeout is what makes it correct, since a notification can be missed and a retry has no publisher to announce it. - Claim — take a batch with
FOR UPDATE SKIP LOCKED, so several replicas share the work instead of each doing all of it. - Run — invoke each message’s function on a blocking worker, then mark the row done or schedule the retry.
§Why it drains rather than handling one batch per wake
A publisher that queues 500 messages fires notifications the listener will coalesce into far fewer wakeups — Postgres is allowed to, and does. A loop that handled one batch per notification would leave the rest sitting until the next poll. So a wake keeps claiming until a claim comes back empty.
§What a failure costs
Nothing that reaches the caller, because there is no caller: the request
that published this ended long ago. A handler that returns an error, panics,
or is missing entirely leaves a row with the reason on it and a retry
scheduled — and after [queues] max_attempts, a failed row somebody has
to come and look at. That is the design: the queue’s job is to make the
failure visible and re-runnable, not to make it somebody’s 500.
Structs§
- Subscriber
- Everything a subscriber needs to run a handler, cloned once at boot.
Functions§
- run
- Run until the process ends.