feat(db): add outbox, notifications and stage advance request tables.
Support transactional stage.ready_to_advance events with dedupe by stage instance and config revision. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
-- +goose Up
|
||||
-- Phase 4: Outbox 事件、站内通知与阶段推进待办去重
|
||||
|
||||
CREATE TABLE IF NOT EXISTS outbox_events (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
aggregate_type TEXT NOT NULL,
|
||||
aggregate_id TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
project_id BIGINT REFERENCES projects(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
published_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_outbox_unpublished ON outbox_events(created_at) WHERE published_at IS NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_outbox_project ON outbox_events(project_id, id DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
project_id BIGINT REFERENCES projects(id) ON DELETE CASCADE,
|
||||
event_id BIGINT REFERENCES outbox_events(id) ON DELETE SET NULL,
|
||||
type TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
body TEXT NOT NULL DEFAULT '',
|
||||
dedupe_key TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'unread',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
read_at TIMESTAMPTZ,
|
||||
acted_at TIMESTAMPTZ,
|
||||
CONSTRAINT chk_notification_status CHECK (status IN ('unread', 'read', 'acted', 'dismissed')),
|
||||
CONSTRAINT uq_notification_dedupe UNIQUE (user_id, dedupe_key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id, id DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_project ON notifications(project_id, id DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS stage_advance_requests (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
stage_instance_id BIGINT NOT NULL REFERENCES project_stage_instances(id) ON DELETE CASCADE,
|
||||
workflow_instance_id BIGINT NOT NULL REFERENCES project_workflow_instances(id) ON DELETE CASCADE,
|
||||
stage_key TEXT NOT NULL,
|
||||
readiness_revision INT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
requested_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
decided_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
decided_at TIMESTAMPTZ,
|
||||
reason TEXT NOT NULL DEFAULT '',
|
||||
CONSTRAINT chk_sar_status CHECK (status IN ('pending', 'confirmed', 'superseded', 'cancelled')),
|
||||
CONSTRAINT uq_sar_stage_revision UNIQUE (stage_instance_id, readiness_revision)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sar_instance ON stage_advance_requests(workflow_instance_id, status);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS stage_advance_requests;
|
||||
DROP TABLE IF EXISTS notifications;
|
||||
DROP TABLE IF EXISTS outbox_events;
|
||||
Reference in New Issue
Block a user