Repository navigation
Keep one bad snapshot file from costing an object its history - #81
Merged
Merged
Conversation
SnapshotStore wrote snapshots in place and skipped any name already taken, so an interrupted write left a truncated file that Add never repaired, and History threw for the whole object on it. A record a stricter parser now rejects did the same with no crash at all. Snapshots are now written to a temporary file and moved into place. ReadHistory skips any file that does not parse and names it, History returns the readable sets, and Add replaces an unreadable file instead of treating it as already archived. Fixes #62 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0169AU8ddEya4XDCm1FVDCMZ
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.
Requested by Matt · project thread
Before: one truncated or unparseable file in an object's snapshot folder made
SnapshotStore.Historythrow for that object, andAddof the same element set saw the name was taken and skipped it, so the history stayed unreadable until someone deleted the file by hand without being told which one.After: the bad file is skipped and named, the rest of the history is returned, and adding the same element set again replaces it. Snapshots are written to a temporary file and moved into place, so an interrupted write can no longer leave a partial file under a real
<epoch>.jsonname.How:
WriteAtomicallywrites<path>.<guid>.tmpbeside the snapshot andFile.Moves it over the final name; the temporary name doesn't end in.json, so a stray one is invisible to readers. A newReadHistory(id)returns aSnapshotHistoryof the readable sets plus the unreadable paths;History(id)delegates to it. A parse failure isJsonException(malformed, truncated, or a record the parser rejects) orFormatException(an epoch format it doesn't read); I/O faults still propagate.Addcounts a repaired file as new.Tests are in the new
SnapshotStoreTests.csand cover all three acceptance criteria. Mutation-checked: letting the parse failure escape fails 4 of the 6, and restoring the bareFile.Existscheck inAddfails the repair test. The atomic write itself isn't mutation-checkable without a seam (it needs a process to die between two syscalls); the tests cover a stray temp file being ignored and no write leaving one behind.dotnet build -c Releaseanddotnet test -c Releasepass locally (110 tests).Fixes #62
🤖 Generated with Claude Code
https://claude.ai/code/session_0169AU8ddEya4XDCm1FVDCMZ
Generated by Claude Code