Persist paste pull cursor for discarded oversized remote pastes - #4703
Merged
Conversation
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.
Closes #4702
Problem
#4699 discards oversized remote non-file pastes without storing them, but the pull cursor only advances in memory. After a restart,
PastePullService.init()rebuilds each device's cursor from the maxcreateTimeof stored pastes — which never includes a discarded paste. If the newest paste from a peer was discarded, every restart re-pulls it, re-discards it, and re-notifies, repeatedly transferring tens of MB until the peer produces a newer stored paste.Changes
PastePullCursorEntitytable (appInstanceIdPK,maxCreateTime) with SQLDelight migration3.sqm. The migration usesCREATE TABLE IF NOT EXISTSso it stays idempotent underDesktopDriverFactory's migration replay after a fresh create.PasteReleaseService.discardOversizedRemoteNonFilePaste) upserts the cursor with the discarded paste'screateTime; the SQL upsert takesMAX(existing, excluded)so the cursor never moves backwards.PastePullService.init()restores each device's cursor as the max of the stored-paste maxcreateTimeand the durable cursor.SyncDeviceManager.removeDevice(reached by both local unpair and remoteNOTIFY_REMOVE) now deletes the device's cursor row alongside the other local state.PasteDaois injected directly rather than going throughPastePullServiceto avoid a constructor dependency cycle viaSyncManager.Safety notes
createTimeorder and persisted inline, so the cursor can never cover an older item that has not yet been stored.createTime > :createTime, so a cursor equal to the discarded paste'screateTimeis sufficient to suppress re-pulls.Tests
PasteDaoTest: cursor upsert is monotonic; delete only removes the given device's row.PasteReleaseServiceRemoteDiscardTest: discarding upserts the durable cursor exactly once.PastePullServiceTest(new):init()merges stored max and durable cursor per device; in-memory updates never write the durable cursor.SyncDeviceManagerTest:removeDevicedeletes the cursor row.Note for mobile:
shared/commonMainchanges include the new table +3.sqm; the mobile repos must pick up the migration file when syncing shared code.