Skip to content

db: make outbox inserts atomic - #435

Open
OllieinCanada wants to merge 1 commit into
sashiko-dev:mainfrom
OllieinCanada:agent/atomic-outbox-inserts
Open

db: make outbox inserts atomic#435
OllieinCanada wants to merge 1 commit into
sashiko-dev:mainfrom
OllieinCanada:agent/atomic-outbox-inserts

Conversation

@OllieinCanada

Copy link
Copy Markdown
Contributor

Summary

Make Sashiko's notification outboxes idempotent under concurrent review completion.

  • replace separate deduplication lookups and inserts with one conditional insert per outbox path
  • cover review email, Patchwork status update, and Patchwork failure notification queues
  • add deterministic tests that release 32 concurrent writers for each logical notification and verify exactly one row is stored

Root cause

Each outbox writer first queried for an existing row and then issued a separate insert. Two review tasks completing together could both observe that no row existed before either insert ran, allowing duplicate external notifications to be queued.

The code described these paths as duplicate-safe, but the invariant was not enforced atomically at the persistence boundary.

Design

Each writer now uses a single INSERT ... SELECT ... WHERE NOT EXISTS statement. SQLite/libSQL serializes the conditional check and write as one statement, closing the check-then-act window without a schema migration or destructive cleanup of historical outbox rows.

The existing logical deduplication keys remain unchanged:

  • review email: patch ID
  • Patchwork update: message ID, API URL, and context
  • Patchwork notification email: recipient, subject, and reply target

Validation

  • standalone rustfmt --check passes for src/db.rs
  • git diff --check passes
  • direct SQLite concurrency probe passes for all three statements with 32 separate writers
  • Rust concurrency tests are included for all three outbox paths
  • local cargo test and make check-pr stop before compiling Sashiko because aws-lc-sys rejects the installed GCC 9.4 compiler; GitHub CI is expected to provide the authoritative Rust, clippy, and test results

Outbox deduplication used separate lookup and insert queries. Concurrent
review completions could both observe no row and enqueue duplicate
notifications.

Use conditional inserts so the existence check and write are atomic.
Cover review email, Patchwork update, and Patchwork notification paths
with concurrent-writer tests.

Signed-off-by: Oliver Slapinski <olliefromcanada@gmail.com>
@OllieinCanada
OllieinCanada marked this pull request as ready for review August 15, 2026 05:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant