Phase 2b — durable Postgres queue + worker (gated on DATABASE_URL)
Some checks failed
Docker Build / build-and-push-image (push) Has been cancelled
Some checks failed
Docker Build / build-and-push-image (push) Has been cancelled
Adds the async dispatch infrastructure : - Postgres pool + embedded migration (CREATE TABLE/INDEX IF NOT EXISTS gateway_jobs). Auto-applied at boot. lib/pq driver (matches webapp convention). - queue.go : Enqueue (idempotent on UNIQUE(bot_slug, update_id) — handles Telegram redelivery), Pop with FOR UPDATE SKIP LOCKED, MarkDone, MarkFailed with exponential backoff (30s → 2m → 10m → 1h → dead at 5). - worker.go : goroutine that drains the queue, dispatches via the same Handler interface as sync, schedules retries on failure, notifies the user once when a job goes to dead. - BotConfig gains `async: bool`. Registry refuses bots with async=true if DATABASE_URL is unset (queue=nil). - Server : when bot.Async, the webhook ack is immediate ; the update payload is enqueued for the worker. When DATABASE_URL is unset (current default), queue/worker stay disabled and only sync handlers (echo, http, auth) work — no breaking change to the running cluster. Refs ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 2.
This commit is contained in:
24
migrations/001_init.sql
Normal file
24
migrations/001_init.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Phase 2b — durable job queue for async handlers (shell, script, ollama).
|
||||
-- Voir ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 2.
|
||||
CREATE TABLE IF NOT EXISTS gateway_jobs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
bot_slug TEXT NOT NULL,
|
||||
handler_type TEXT NOT NULL,
|
||||
update_id BIGINT NOT NULL,
|
||||
payload JSONB NOT NULL,
|
||||
attempts INT NOT NULL DEFAULT 0,
|
||||
next_retry_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
last_error TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
-- idempotence : si Telegram redélivre (ack > 60s), on ignore le doublon.
|
||||
CONSTRAINT gateway_jobs_uniq_update UNIQUE (bot_slug, update_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS gateway_jobs_pickable
|
||||
ON gateway_jobs (next_retry_at)
|
||||
WHERE status = 'pending';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS gateway_jobs_status
|
||||
ON gateway_jobs (status);
|
||||
Reference in New Issue
Block a user