You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
### Why?
The orchestrator's build poll loop needs to space `Status` calls out
without consuming `retry_count` / DLQ retry slots. `Delivery.Nack` does
schedule redelivery after a delay, but it overloads `retry_count` —
which the operator relies on to flag real failures. The fix is a
separate "postpone this work" primitive, distinct from "this delivery
failed, try again", so both signals stay meaningful.
### What?
Adds `Publisher.PublishAfter(ctx, topic, msg, delayMs)` to the queue
extension: a fresh message inserted into the topic, made visible to
subscribers only after `delayMs` from now. Distinct from
`Delivery.Nack(requeueAfterMillis)`:
- `Nack` is "this delivery failed, try again" — it bumps `retry_count`
and eventually trips DLQ.
- `PublishAfter` is "postpone this work" — `retry_count` resets to 0,
DLQ stays available for true failures.
SQL backing in `extension/queue/mysql`:
- New `visible_after BIGINT UNSIGNED NOT NULL DEFAULT 0` column on
`queue_messages`. Default 0 means immediately visible — back-compat
for any existing rows.
- `messageStore.InsertDelayed(ctx, topic, messages, visibleAfterMs)` is
the underlying primitive. `Insert` is now a thin wrapper that passes
`visibleAfterMs = 0`.
- `FetchByOffset` gains a `nowMs` parameter and an
`AND visible_after <= ?` predicate so subscribers skip rows whose
delivery is still deferred.
- `MoveToDLQ` writes `visible_after = 0` explicitly: any delay on the
original message has already been consumed by the time it failed.
The first consumer of `PublishAfter` is the orchestrator's poll-driven
`buildsignal` loop, which lands in the stacked PR on top of this one.
**`PublishAfter`** inserts a fresh message that becomes visible to subscribers only after `delayMs`. It is distinct from `Nack(requeueAfterMillis)` even though both can produce "next delivery happens at T+delay":
22
+
23
+
-`Nack` is "this delivery failed, try again" — it bumps `retry_count` and eventually trips DLQ.
24
+
-`PublishAfter` is "postpone this work" — `retry_count` resets to 0, DLQ stays available for true failures.
25
+
26
+
Use `PublishAfter` for self-driven poll loops (e.g. the orchestrator's `buildsignal` consumer re-publishing itself between `Status` calls). Use `Nack` for processing failures.
27
+
20
28
### Subscriber
21
29
Consumes messages from topics with per-subscription configuration.
|`queue_subscriber_heartbeats`| Active subscriber tracking |`(consumer_group, topic, subscriber_name)`|
114
114
115
+
`queue_messages` has a `visible_after BIGINT UNSIGNED NOT NULL DEFAULT 0` column that supports `Publisher.PublishAfter`: subscribers' `FetchByOffset` skips rows where `visible_after > now`. Default 0 means immediately visible, so existing rows continue to behave as before — the column is back-compatible.
116
+
115
117
See `schema/` for full SQL definitions. See the [RFC](../../doc/rfc/sql-queue-rfc.md#database-schema) for field-level documentation.
0 commit comments