feat(db): update_event_review mirrors reviewed_real + enforces 3-state exclusivity

This commit is contained in:
2026-08-25 00:34:25 +00:00
parent 23e4f585a8
commit f73c8eec91
2 changed files with 50 additions and 11 deletions
+25 -11
View File
@@ -685,17 +685,23 @@ class SeismoDb:
""" """
Sync derived index columns from a sidecar's `review` block. Sync derived index columns from a sidecar's `review` block.
Currently the only derived index is `events.false_trigger` — kept The derived indexes are `events.false_trigger` and
in sync so `/db/events?false_trigger=true` queries don't have to `events.reviewed_real` — kept in sync so `/db/events` queries don't
scan every sidecar JSON on disk. The sidecar JSON itself remains have to scan every sidecar JSON on disk. The sidecar JSON itself
the source of truth for the full review state. remains the source of truth for the full review state.
The two columns are mutually exclusive: setting either one true
forces the other's column to 0.
Returns True when the row exists, False otherwise. No-op fields Returns True when the row exists, False otherwise. No-op fields
(review without `false_trigger`) leave the column untouched. (review without `false_trigger` or `reviewed_real`) leave both
columns untouched.
""" """
if not isinstance(review, dict): if not isinstance(review, dict):
return False return False
if "false_trigger" not in review: has_ft = "false_trigger" in review
has_real = "reviewed_real" in review
if not has_ft and not has_real:
# Nothing derived to update; just confirm the row exists. # Nothing derived to update; just confirm the row exists.
with self._connect() as conn: with self._connect() as conn:
row = conn.execute( row = conn.execute(
@@ -703,12 +709,20 @@ class SeismoDb:
).fetchone() ).fetchone()
return row is not None return row is not None
flag = 1 if review.get("false_trigger") else 0 sets = {}
if has_ft:
sets["false_trigger"] = 1 if review.get("false_trigger") else 0
if has_real:
sets["reviewed_real"] = 1 if review.get("reviewed_real") else 0
# mutual exclusivity: a true in one forces the other column to 0
if sets.get("false_trigger") == 1:
sets["reviewed_real"] = 0
if sets.get("reviewed_real") == 1:
sets["false_trigger"] = 0
assign = ", ".join(f"{k}=?" for k in sets)
params = list(sets.values()) + [event_id]
with self._connect() as conn: with self._connect() as conn:
cur = conn.execute( cur = conn.execute(f"UPDATE events SET {assign} WHERE id=?", params)
"UPDATE events SET false_trigger=? WHERE id=?",
(flag, event_id),
)
return cur.rowcount > 0 return cur.rowcount > 0
# ── Monitor log ─────────────────────────────────────────────────────────── # ── Monitor log ───────────────────────────────────────────────────────────
@@ -0,0 +1,25 @@
from sfm.database import SeismoDb
from minimateplus.models import Event
def _ins(db, eid_key="01110000", serial="BE1"):
ev = Event(index=0); ev._waveform_key = bytes.fromhex(eid_key)
db.insert_events([ev], serial=serial)
return db.query_events(serial=serial)[0]["id"]
def test_confirm_real_sets_and_clears_ft(tmp_path):
db = SeismoDb(tmp_path/"s.db"); eid = _ins(db)
db.update_event_review(eid, {"false_trigger": True})
assert db.get_event(eid)["false_trigger"] == 1
db.update_event_review(eid, {"reviewed_real": True}) # confirming real clears FT
row = db.get_event(eid)
assert row["reviewed_real"] == 1 and row["false_trigger"] == 0
def test_flag_ft_clears_reviewed_real(tmp_path):
db = SeismoDb(tmp_path/"s.db"); eid = _ins(db)
db.update_event_review(eid, {"reviewed_real": True})
db.update_event_review(eid, {"false_trigger": True})
row = db.get_event(eid)
assert row["false_trigger"] == 1 and row["reviewed_real"] == 0