Skip to content

snapshots: never of a save a sync is writing, never incomplete - #54

Open
ChakraFusion wants to merge 2 commits into
Liquid-co:dev-publicfrom
ChakraFusion:pr/snapshot-safety
Open

ChakraFusion wants to merge 2 commits into
Liquid-co:dev-publicfrom
ChakraFusion:pr/snapshot-safety

Conversation

@ChakraFusion

Copy link
Copy Markdown

As offered in #21. Builds on #23 (own writes), which it needs for the watcher's own/other classification.

  • A pull of a save of many files overflowed the watcher's event queue again and again, and each overflow was taken for the game saving: up to 76 automatic snapshots of a half-pulled save for one pull. An overflow while a sync is writing the game, or was a moment ago (BeingWritten), is now taken for the sync's. A burst is looked at only once no sync is writing the game at that moment (WritingNow), so a change the game makes right after a pull is still snapshotted at once.
  • A snapshot that couldn't read every file is discarded rather than kept as a save that never existed.
  • *.opensave.tmp files are never archived.

(The fork version also limits #26's "mirror the peer's snapshot when already in sync" to games without history. That part will follow #26.)

🤖 Generated with Claude Code

ChakraFusion and others added 2 commits October 13, 2026 20:31
New package internal/owntouch records the paths OpenSave itself writes,
removes, creates or re-dates: pulled files, a peer's deletions, the folders a
pull creates, the files "keep theirs" removes and the mtimes "keep mine"
touches. The watcher classifies every event by it: a burst made only of
OpenSave's own changes moves the recorded hash and nothing else - no
auto-snapshot, and no OnChanged sending the sync straight back out.

Before, every change a sync applied looked exactly like the game saving. A peer
deleting files one request at a time produced an auto-snapshot every couple of
seconds, each of a save that was neither the old one nor the new one; they
filled the retention budget and pushed out the snapshots that mattered.

- a file counts as OpenSave's only if nothing wrote it after the mark (its
  mtime is not later), so a game saving straight after a sync is still the
  game's change.
- once OpenSave is done with a file (renamed into place, re-dated to the
  peer's time) it records the time and size it left it with, and from then
  on the file is OpenSave's only while it has exactly those - a game saving
  within the two seconds the time comparison allows is still the game's.
- a path found gone counts as OpenSave's only if OpenSave removed it
  (MarkRemoved): a file it pulled and the game or a person then deleted is
  their change.
- the rescan after new folders come under watch is OpenSave's own when it
  created those folders (a pull of a save with subfolders), and someone
  else's otherwise.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A pull of a save of many files overflowed the watcher's event queue again
and again, and each overflow was taken for the game saving: an automatic
snapshot of a half-pulled save every few seconds - 76 on one device for one
pull - which pushed the complete ones out of retention.

- The watcher asks whether a sync is writing the game (BeingWritten). If
  so, an overflow is taken for the sync's, and the burst is looked at only
  once the sync has finished.
- A snapshot that could not read every file is discarded, not kept: it
  would stand in the history as a save that never existed. The watcher
  leaves the change unrecorded and takes it again at its next pass; a sync
  that needed the copy before replacing files does not replace them.
- OpenSave's own temporary files (*.opensave.tmp) are never archived.

Builds on the own-writes change (Liquid-co#23).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@vercel

vercel Bot commented Oct 14, 2026

Copy link
Copy Markdown

@ChakraFusion is attempting to deploy a commit to the sivadaboi's projects Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
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