Skip to content

fix(sync): keep a superseded snapshot until every device has read past it - #1562

Merged
A-EDev merged 2 commits into
mainfrom
fix/sync2-gc-manifest-ack
Oct 29, 2026
Merged

A-EDev merged 2 commits into
mainfrom
fix/sync2-gc-manifest-ack

Conversation

@A-EDev

@A-EDev A-EDev commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Garbage collection could delete a device's own snapshot manifest while other devices hadn't read that manifest's log entry yet. Readers then waited forever at the gap it left. Desktop hit this (the owner's phone is stuck at the Mac's seq 572 because the Mac deleted manifest 573), and Android has the same rule.

  • Facts.superseded() now also requires acked(old.did) >= old.seq: every current device's latest ack has vv[X] >= n for the manifest's own seq n. This follows the spec fix in flow-sync Shorts Track selection #43 (spec/protocol.md, Garbage collection).
  • The other conditions are unchanged: a newer snapshot of the same link must cover it, and every current device must have acked that newer snapshot.

Related issue

Part of #1075 (linked devices).

Change type

  • Bug fix
  • Feature
  • Refactor or maintenance
  • Build, packaging, or CI
  • Documentation

Validation

  • ./gradlew :app:assembleGithubDebug: ok
  • ./gradlew :app:testGithubDebugUnitTest: 4650 passed, 46 skipped, 0 failed. New: GarbageCollectionTest.a_snapshot_stays_until_every_device_read_past_it_even_when_another_covers_it, the Mac case:
    • The Mac's manifest 573 is covered by the phone's acknowledged snapshot, but the phone has read the Mac's log only to 572. The manifest stays.
    • Once the phone acks 573, it can go.
    • Under the old rule, the first assertion fails.
  • ./gradlew ktlintCheck: ok
  • python3 .github/scripts/nightly_notes.py --check: valid
  • I manually tested the affected behavior on an Android device or emulator. (Not run here.)

Test device and Android version: none

Risk and compatibility

  • Superseded manifests stay a little longer: until the slowest current device has read past them.

  • This does not repair a gap that already exists. A device stuck at a deleted manifest needs the Desktop-side handling or a fresh link.

  • Branched from origin/main before fix(sync): stop re-sending applied records and announce only Sync now #1559 merged. It touches none of fix(sync): stop re-sending applied records and announce only Sync now #1559's files.

  • The change does not introduce secrets, private data, or unexpected telemetry.

  • New user-facing text uses Android string resources. (None.)

  • Dependency and lockfile changes are intentional and limited to this PR. (None.)

  • Room schema changes include the required version bump and migration, or this PR does not change the Room schema. (No schema change.)

  • Breaking changes and upgrade steps are clearly documented. (None.)

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 29, 2026
@A-EDev
A-EDev merged commit 0330c3f into main Oct 29, 2026
9 checks passed
@A-EDev
A-EDev deleted the fix/sync2-gc-manifest-ack branch October 29, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant