agent-orchestrator/backend/internal/storage/sqlite/migrations
Khushi Diwan 96d1649e46
fix(review): serialize concurrent triggers per worker to stop reviewer double-spawn (#246)
* fix(review): serialize concurrent triggers per worker to stop double-spawn

Engine.Trigger was a read-then-write (idempotency check -> reviewer spawn ->
InsertReviewRun) with no serialization and no backing constraint. Two near-
simultaneous triggers for the same worker at the same head SHA both passed the
GetReviewRunBySessionAndSHA check, both spawned a reviewer against the same
deterministic review-<id> handle, and both inserted a running run for one commit.

Add a per-worker keyed mutex (lockWorker) held across the whole Trigger body, so
the loser re-reads the freshly-recorded run and short-circuits to Created:false
instead of spawning. Back it with a partial unique index on
review_run(session_id, target_sha) (migration 0013) as a cross-restart safety
net; rows with an empty target_sha (head not yet observed) are excluded so they
are not blocked.

Adds a concurrency test asserting N simultaneous triggers spawn once and record
one run.

Closes #242

* fix(review): make migration 0013 dedup-safe and handle the unique conflict in Trigger

Pre-#242 daemons can already hold duplicate (session_id, target_sha)
review_run rows, on which CREATE UNIQUE INDEX fails and wedges startup.
Migration 0013 now collapses each duplicate group to a single survivor
(a completed pass over a still-running one, then newest by created_at)
before building the index.

Trigger now treats a unique-constraint hit as a fallback rather than an
error: InsertReviewRun maps it to the new domain.ErrDuplicateReviewRun
sentinel, and Trigger re-reads GetReviewRunBySessionAndSHA and returns
that run with Created:false instead of surfacing a raw error after the
reviewer may already have launched.
2026-06-17 00:43:10 +05:30
..
0001_init.sql refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
0002_remove_activity_source.sql refactor: remove activity source tracking (#62) (#66) 2026-06-01 09:26:18 +05:30
0003_add_session_display_name.sql feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
0004_scm_observer_schema.sql feat: add provider-neutral SCM observer (#76) 2026-06-04 22:26:07 +05:30
0005_pr_last_nudge_signature.sql feat(scm): wire observer messenger + RepoOriginURL + persist dedup (#108) (#114) 2026-06-05 23:20:02 +05:30
0006_pr_session_changed_cdc.sql feat: ao session claim-pr + spawn --claim-pr wiring (#101) 2026-06-06 00:01:03 +05:30
0007_allow_implemented_harnesses.sql feat(agents): agent platform — registry, activity hooks, harness allowlist (#119) 2026-06-07 00:52:40 +05:30
0008_add_project_config.sql feat(config): persist per-project agent config and resolve it at spawn (#154) 2026-06-08 21:35:29 +05:30
0009_workspace_projects.sql feat: add workspace project registration foundation (#165) 2026-06-10 16:10:14 +05:30
0010_add_first_signal_at.sql fix(codex): reliable activity signals — session-flag hooks, trust bypass, no_signal watchdog (#170) 2026-06-11 10:36:45 +05:30
0011_notifications.sql feat: add notifications v1 (#181) 2026-06-14 20:02:32 +05:30
0012_add_review_tables.sql feat(review): configurable AO code review backend (V1) (#192) (#197) 2026-06-15 01:17:17 +05:30
0013_review_run_unique_sha.sql fix(review): serialize concurrent triggers per worker to stop reviewer double-spawn (#246) 2026-06-17 00:43:10 +05:30