feat(v1.1.9): migrations 0034 + 0035 (queue_messages, queue_triggers)
- 0034_queue_messages.sql: per-app durable named queues. (app_id, queue_name) is the identity tuple; no queue registry table. Partial indexes on (claim_token IS NULL) for the dispatch hot path and (claim_token IS NOT NULL) for the visibility-timeout reclaim scan. The queue table IS the outbox for queue semantics — no double-buffering. - 0035_queue_triggers.sql: widens triggers.kind CHECK to admit 'queue'; widens outbox.source_kind CHECK to admit 'invoke' (for invoke_async). Adds queue_trigger_details(trigger_id PK, queue_name, visibility_timeout_secs, last_fired_at). Retry policy lives on the parent triggers row — same pattern as every other kind. One-consumer-per-queue is API-layer enforced via pg_advisory_xact_lock (partial unique index can't span parent.app_id). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
41
crates/manager-core/migrations/0035_queue_triggers.sql
Normal file
41
crates/manager-core/migrations/0035_queue_triggers.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
-- v1.1.9: queue:receive trigger kind + OutboxSourceKind::Invoke.
|
||||
--
|
||||
-- queue:receive is the new trigger kind that fires a script per claimed
|
||||
-- message. Layout E parent + per-kind detail (mirrors pubsub).
|
||||
--
|
||||
-- 'invoke' is added to outbox.source_kind for invoke_async() — a
|
||||
-- fire-and-forget function-composition call writes an outbox row that
|
||||
-- the dispatcher fires through the standard executor path.
|
||||
--
|
||||
-- Queue itself does NOT need an outbox.source_kind variant (the queue
|
||||
-- table IS the outbox for queue semantics — see 0034).
|
||||
|
||||
ALTER TABLE triggers DROP CONSTRAINT triggers_kind_check;
|
||||
ALTER TABLE triggers ADD CONSTRAINT triggers_kind_check
|
||||
CHECK (kind IN ('kv', 'dead_letter', 'docs', 'cron',
|
||||
'files', 'pubsub', 'email', 'queue'));
|
||||
|
||||
ALTER TABLE outbox DROP CONSTRAINT outbox_source_kind_check;
|
||||
ALTER TABLE outbox ADD CONSTRAINT outbox_source_kind_check
|
||||
CHECK (source_kind IN ('http', 'kv', 'dead_letter', 'docs',
|
||||
'cron', 'files', 'pubsub', 'email', 'invoke'));
|
||||
|
||||
-- Per-queue-trigger config. Retry policy lives on the parent triggers
|
||||
-- row (retry_max_attempts, retry_backoff, retry_base_ms) — same
|
||||
-- pattern as every other trigger kind. visibility_timeout_secs is
|
||||
-- queue-specific.
|
||||
--
|
||||
-- "Exactly one consumer per (app_id, queue_name)" is enforced at the
|
||||
-- API layer via a pg_advisory_xact_lock on hashtext(app_id || queue_name)
|
||||
-- + a SELECT-then-INSERT in one transaction (a partial unique index
|
||||
-- can't reference the parent's app_id column from the detail table).
|
||||
CREATE TABLE queue_trigger_details (
|
||||
trigger_id UUID PRIMARY KEY REFERENCES triggers(id) ON DELETE CASCADE,
|
||||
queue_name TEXT NOT NULL,
|
||||
visibility_timeout_secs INT NOT NULL DEFAULT 30,
|
||||
last_fired_at TIMESTAMPTZ NULL
|
||||
);
|
||||
|
||||
-- Help the dispatcher's "find all active queue consumers" query.
|
||||
CREATE INDEX idx_queue_trigger_details_queue_name
|
||||
ON queue_trigger_details (queue_name);
|
||||
Reference in New Issue
Block a user