Wheeler cloud sync: union-merge instead of pull-replace - #140
Merged
Conversation
authInit previously replaced the entire local trade array with the cloud copy whenever the remote savedAt was newer. A trade entered locally while signed out (or before its push landed) never bumps wheeler_cloud_ts, so a later boot pull would silently clobber it — how an IBIT CSP went missing. Reconcile by union-merging local + remote by trade id (mergeTradesById): a trade on only one side is always kept; the newer side wins shared-id conflicts. Converge whichever store is behind. Deletions still don't propagate (accepted tradeoff vs. silent loss). Adds test/unit/wheeler-merge.test.js incl. the local-only-survives-pull regression. All 190 tests pass; both builds clean.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Problem
A Wheeler trade entered on one device could silently vanish.
authInitreplaced the entire local trade array with the cloud copy whenever the remote
savedAtwas newer. Entering a trade doesn't bumpwheeler_cloud_ts, so adevice holding an unpushed local trade looks "stale" and a later boot pull
clobbers it. This is how a manually-entered IBIT CSP went missing (present in
neither local nor cloud after the fact).
Fix
Reconcile local and remote by union-merging by trade
id(mergeTradesById)instead of wholesale replacement:
idconflicts (preserves edit last-write-wins),remote-only trades down),
Applied to the incident: signing in on the device that still holds the IBIT
CSP now merges it up to the cloud instead of pulling PURR-only down over it.
Known limitation (deliberate)
Deletions do not propagate — a deleted trade can reappear from another
device's copy. Mild, visible annoyance vs. silent data loss; syncing deletes
needs tombstones (out of scope). Noted in code + ADR 0007 context.
Tests
test/unit/wheeler-merge.test.js(6 cases) incl. the local-only-survives-pullregression. All 190 tests pass; both builds clean.
🤖 Generated with Claude Code