Fix JSON channel store flush race and missing rollback (#52)#55
Draft
TYRMars wants to merge 1 commit into
Draft
Conversation
JsonFileChannelBindingStore / JsonFileChannelInstanceStore mutated in-memory state under the write lock, then released the lock before flushing the snapshot to disk. This allowed two concurrent writers' atomic_write calls to reorder (last write wins on disk, durably losing a change while memory still showed it), and a failed flush left the in-memory mutation in place with no rollback, so memory diverged from disk. Build the next state without touching the guard, flush it while still holding the write lock (serialising disk writes so they cannot reorder), and commit the in-memory mutation only after the flush succeeds. A failed flush now leaves both memory and disk unchanged. Applied to upsert / delete / delete_for_conversation on the binding store and upsert / delete on the instance store. Adds a regression test that forces a flush failure and asserts the in-memory state rolls back.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #52.
Problem
JsonFileChannelBindingStoreandJsonFileChannelInstanceStoremutated in-memory state under the write lock, then released the lock before flushing to disk. Two failure modes:atomic_write, so the disk writes could reorder (last write wins on disk). A change correct in memory could be durably lost, surfacing only after restart.Vecwas mutated first; a failingflush()propagated the error but left the mutation in place, solookup/listreported a row that was never persisted.Fix
Each write method now:
A failed flush leaves both memory and disk unchanged. Applied to
upsert/delete/delete_for_conversationon the binding store andupsert/deleteon the instance store.Tests
Adds
channel_binding_rolls_back_on_flush_failure, which forces a flush failure (occupies theatomic_writetemp path with a directory) and asserts the in-memory state rolls back, then confirms a later write commits cleanly.cargo test -p harness-storeandcargo clippy -p harness-store --all-targets -- -D warningsboth pass.https://claude.ai/code/session_01FhsDL2qEDL8MQnS7gmSdim
Generated by Claude Code