feat(db): add events.delivery_id + partial unique index (M-7)
This commit is contained in:
38
src/db.py
38
src/db.py
@@ -67,6 +67,17 @@ def init_db():
|
||||
# (CREATE TABLE IF NOT EXISTS won't add columns to an already-created table).
|
||||
_ensure_column(conn, "jobs", "transient_attempts", "INTEGER NOT NULL DEFAULT 0")
|
||||
_ensure_column(conn, "jobs", "available_at", "TEXT")
|
||||
# ORCH-5 (M-7): webhook delivery de-dup. Add events.delivery_id and a PARTIAL
|
||||
# unique index. Partial (WHERE delivery_id IS NOT NULL) so pre-existing rows
|
||||
# (which have NULL delivery_id) never collide with each other. Restart-safe:
|
||||
# _ensure_column is a no-op once the column exists, and CREATE INDEX IF NOT
|
||||
# EXISTS is a no-op once the index exists, so this is safe on the live prod DB.
|
||||
_ensure_column(conn, "events", "delivery_id", "TEXT")
|
||||
conn.execute(
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS idx_events_delivery "
|
||||
"ON events(delivery_id) WHERE delivery_id IS NOT NULL"
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
@@ -141,6 +152,33 @@ def get_next_work_item_id(repo: str, prefix: str = "ET") -> str:
|
||||
return f"{prefix}-{next_num:03d}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ORCH-5 (M-7): idempotent webhook event logging
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def insert_event_dedup(
|
||||
source: str, event_type: str, payload: str, delivery_id: str
|
||||
) -> bool:
|
||||
"""Idempotently log a webhook event keyed by delivery_id.
|
||||
|
||||
Returns True if a NEW row was inserted (caller should dispatch the event) and
|
||||
False if this delivery_id was already present (a duplicate delivery -> caller
|
||||
must skip dispatch/enqueue). Uses INSERT OR IGNORE against the partial UNIQUE
|
||||
index idx_events_delivery; rowcount==1 means the row was actually inserted.
|
||||
"""
|
||||
conn = get_db()
|
||||
try:
|
||||
cur = conn.execute(
|
||||
"INSERT OR IGNORE INTO events (source, event_type, payload, delivery_id) "
|
||||
"VALUES (?, ?, ?, ?)",
|
||||
(source, event_type, payload, delivery_id),
|
||||
)
|
||||
conn.commit()
|
||||
return cur.rowcount == 1
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ORCH-1 (F-2b): job queue helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user