From 927d73b3a263fd5682fb8f402203766a9d850676 Mon Sep 17 00:00:00 2001 From: Shantanu Mane Date: Tue, 16 Jun 2026 23:28:31 +0530 Subject: [PATCH] feat(db): add webhook_registrations and webhook_deliveries tables - New migration 000002 for the webhook system (DEV-44) - webhook_deliveries is the outbox: status, attempts, next_attempt_at - Partial index on next_attempt_at WHERE status='pending' for the poll loop - ON DELETE CASCADE from deliveries to their registration - uuid_generate_v4 + IF NOT EXISTS to match existing schema conventions --- .../migrations/000002_webhooks.down.sql | 2 ++ .../migrations/000002_webhooks.up.sql | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 internal/database/migrations/000002_webhooks.down.sql create mode 100644 internal/database/migrations/000002_webhooks.up.sql diff --git a/internal/database/migrations/000002_webhooks.down.sql b/internal/database/migrations/000002_webhooks.down.sql new file mode 100644 index 0000000..8d6f7b6 --- /dev/null +++ b/internal/database/migrations/000002_webhooks.down.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS webhook_deliveries; +DROP TABLE IF EXISTS webhook_registrations; diff --git a/internal/database/migrations/000002_webhooks.up.sql b/internal/database/migrations/000002_webhooks.up.sql new file mode 100644 index 0000000..5f7ff72 --- /dev/null +++ b/internal/database/migrations/000002_webhooks.up.sql @@ -0,0 +1,24 @@ +CREATE TABLE IF NOT EXISTS webhook_registrations ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + url TEXT NOT NULL, + secret TEXT NOT NULL, -- encrypted at rest (ENCRYPTION_KEY) + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS webhook_deliveries ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + registration_id UUID NOT NULL REFERENCES webhook_registrations (id) ON DELETE CASCADE, + event TEXT NOT NULL, -- 'job.done' | 'job.failed' + asset_id UUID NOT NULL, + job_id BIGINT NOT NULL, + payload JSONB NOT NULL, + status TEXT NOT NULL DEFAULT 'pending', -- pending | delivered | failed + attempts INT NOT NULL DEFAULT 0, + next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(), + delivered_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS webhook_deliveries_pending_idx + ON webhook_deliveries (next_attempt_at) + WHERE status = 'pending';