fix(sqlite): stop actors on head fence mismatch#4977
Conversation
4fb3acf to
337772d
Compare
Code Review: fix(sqlite): stop actors on head fence mismatchOverviewThis PR hardens Rivet Actor SQLite storage against lifecycle overlap by adding Depot head-fence checks for SQLite reads and commits. The core idea is sound: Depot is the authority for The design is well-conceived and the test coverage is solid. A few things worth addressing before this lands: Issues1. Missing log in In 2. Duplicated
3. The 4. Missing newline at EOF in The diff shows no newline at end of file. All other artifact files end with a newline. 5. Missing blank line before The Observations (non-blocking)
No VFS-level test for read-path fence rejection. Protocol / Backward CompatibilityThe v4 to v5 conversion looks correct: SummaryThe core invariant (Depot is the authority, mismatch is fatal, actor stops) is correctly implemented end-to-end. The test coverage is good. The blocking items are the missing |
Code Review: fix(sqlite): stop actors on head fence mismatchOverviewThis PR hardens Rivet Actor SQLite storage against concurrent access by introducing a head fence check using a monotonically-increasing The approach is sound and the implementation is generally clean. A few items worth attention below. IssuesMissing newline in error artifact
When
Identical logic appears in Minor Observations
Test CoverageGood. Tests cover:
Missing: a test verifying the remote fence path through pegboard-envoy produces a structured SummaryThe core logic is correct and well-tested. Three items worth addressing before merge:
|

Stack Context
This stack hardens Rivet Actor SQLite storage against lifecycle overlap, where multiple actor instances can observe or write the same Depot-backed SQLite database concurrently.
What?
depot.head_fence_mismatcherrors through pegboard-envoy and envoy protocol v5.Why?
SQLite corruption symptoms around actor lifecycle churn point to overlapping actor instances accessing the same database. Depot is the authority for the current SQLite head, so this PR checks expected vs actual head inside Depot transactions and treats mismatches as a fatal lifecycle invariant violation instead of allowing continued reads or writes.
Validation
cargo check -p depot-client -p rivetkit-corecargo check -p depot-client-embedded -p pegboard-envoy -p rivetkit-corecargo check -p rivetkit-corecargo test -p depot-client fatal_sqlite_error_reports_first_message_through_worker_boundary -- --nocapturecargo test -p depot-client head_fence_ioerr_maps_to_fatal_worker_error_and_future_operations_fail_closed -- --nocapturecargo test -p depot-client resolve_pages_sends_known_head_txid_as_read_fence -- --nocapturecargo test -p depot --test conveyer_commit head_fence -- --nocapturecargo test -p rivetkit-core remote_head_fence_mismatch_stops_actor_once -- --nocapturegit diff --check