feat(backend): alerts come enriched and paged with an unseen count and a live alert frame
This commit is contained in:
1 parent
4469938f47
commit
2bb8ca45fb
7 files changed
+682
-65
No files matched your search
@@ -0,0 +1,86 @@
|
||||
"""watch names and webhooks
|
||||
|
||||
Revision ID: d8e3b5a1c7f4
|
||||
Revises: d8f4a1c6e2b7
|
||||
Create Date: 2026-10-19 03:00:00.000000
|
||||
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision: str = "d8e3b5a1c7f4"
|
||||
down_revision: str | None = "d8f4a1c6e2b7"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
_WEBHOOKS = """
|
||||
CREATE TABLE webhooks (
|
||||
id serial PRIMARY KEY,
|
||||
account_id integer NOT NULL,
|
||||
url text NOT NULL,
|
||||
secret text NOT NULL,
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
watch_ids integer[],
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
)
|
||||
"""
|
||||
|
||||
_DELIVERIES = """
|
||||
CREATE TABLE webhook_deliveries (
|
||||
id bigserial PRIMARY KEY,
|
||||
webhook_id integer NOT NULL REFERENCES webhooks (id) ON DELETE CASCADE,
|
||||
alert_id integer REFERENCES alerts (id) ON DELETE CASCADE,
|
||||
event text NOT NULL,
|
||||
status text NOT NULL DEFAULT 'pending',
|
||||
attempts integer NOT NULL DEFAULT 0,
|
||||
next_attempt_at timestamptz NOT NULL DEFAULT now(),
|
||||
response_code integer,
|
||||
last_error text,
|
||||
body text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
finished_at timestamptz
|
||||
)
|
||||
"""
|
||||
|
||||
_LEGACY_KEYWORD = """
|
||||
UPDATE watches
|
||||
SET params = (params - 'keyword') || jsonb_build_object('pattern', params->'keyword')
|
||||
WHERE kind = 'keyword' AND params ? 'keyword' AND NOT params ? 'pattern'
|
||||
"""
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("ALTER TABLE watches ADD COLUMN name text")
|
||||
op.execute(_LEGACY_KEYWORD)
|
||||
op.execute("ALTER TABLE alerts DROP CONSTRAINT alerts_watch_id_fkey")
|
||||
op.execute(
|
||||
"ALTER TABLE alerts ADD CONSTRAINT alerts_watch_id_fkey "
|
||||
"FOREIGN KEY (watch_id) REFERENCES watches (id) ON DELETE CASCADE"
|
||||
)
|
||||
op.execute("CREATE INDEX ix_alerts_account_id ON alerts (account_id, id DESC)")
|
||||
op.execute(_WEBHOOKS)
|
||||
op.execute("CREATE INDEX ix_webhooks_account ON webhooks (account_id)")
|
||||
op.execute(_DELIVERIES)
|
||||
op.execute(
|
||||
"CREATE INDEX ix_webhook_deliveries_due ON webhook_deliveries "
|
||||
"(next_attempt_at) WHERE status = 'pending'"
|
||||
)
|
||||
op.execute(
|
||||
"CREATE INDEX ix_webhook_deliveries_webhook ON webhook_deliveries "
|
||||
"(webhook_id, id DESC)"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.execute("DROP TABLE IF EXISTS webhook_deliveries")
|
||||
op.execute("DROP TABLE IF EXISTS webhooks")
|
||||
op.execute("DROP INDEX IF EXISTS ix_alerts_account_id")
|
||||
op.execute("ALTER TABLE alerts DROP CONSTRAINT alerts_watch_id_fkey")
|
||||
op.execute(
|
||||
"ALTER TABLE alerts ADD CONSTRAINT alerts_watch_id_fkey "
|
||||
"FOREIGN KEY (watch_id) REFERENCES watches (id)"
|
||||
)
|
||||
op.execute("ALTER TABLE watches DROP COLUMN name")
|
||||
Reference in new issue
Block a user