-- §11.6 D3: group-shared durable queues. -- -- The queue counterpart to the group_kv/docs/files shared stores (0053-0055). -- A group declares a `queue` shared collection (kind admitted in 0064); any -- subtree app enqueues into ONE group-owned store via -- `queue::shared_collection(name).enqueue(...)`. Consumption is by COMPETING -- CONSUMERS: a group `[[triggers.queue]] shared = true` template materializes a -- consumer copy per descendant app (like the M5 stateful templates), and all -- copies claim from this shared store with FOR UPDATE SKIP LOCKED — each message -- delivered at-most-once across the whole subtree, scaling horizontally. -- -- Identity tuple: (group_id, collection). Keyed by the OWNING GROUP, not an app -- (the shared rows belong to the group). CASCADE on group delete (data dies with -- its group; an app delete leaves it), matching the other group stores. Mirrors -- queue_messages (0034) column-for-column, swapping (app_id, queue_name) for -- (group_id, collection). CREATE TABLE group_queue_messages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE, collection TEXT NOT NULL, payload JSONB NOT NULL, enqueued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deliver_after TIMESTAMPTZ NULL, claim_token UUID NULL, claimed_at TIMESTAMPTZ NULL, attempt INT NOT NULL DEFAULT 0, max_attempts INT NOT NULL DEFAULT 3, enqueued_by_principal UUID NULL ); -- Dispatch hot path: scan for unclaimed messages in (group_id, collection) -- order by enqueued_at (the NOW() deliver_after filter is applied on the small -- partial result, as in 0034). CREATE INDEX idx_group_queue_messages_dispatch ON group_queue_messages (group_id, collection, enqueued_at) WHERE claim_token IS NULL; -- depth() / depth_pending() helpers. CREATE INDEX idx_group_queue_messages_group_collection ON group_queue_messages (group_id, collection); -- Reclaim-task scan: currently-leased messages past their visibility timeout. CREATE INDEX idx_group_queue_messages_claimed ON group_queue_messages (claimed_at) WHERE claim_token IS NOT NULL;