Keep unsent CloudKit changes across Sync Now (#978)

refreshSync() discarded the persisted engine state and the pending
buffer, and the engine state is where queued saves and deletions live,
so tapping Sync Now within the debounce window dropped history,
progress and bookmark changes. Carry the old engine's pending changes
into the buffer that the new engine adopts, then schedule a send.
This commit is contained in:
Arkadiusz Fal
2026-10-19 21:45:45 +02:00
parent ef372b65d9
commit 4c7ccb83a6

View File

@@ -1629,22 +1629,33 @@ final class CloudKitSyncEngine: @unchecked Sendable {
LoggingService.shared.logCloudKit("Refreshing sync state (clearing local tokens)...")
// Unsent local changes live in the engine state being discarded below;
// carry them over so a refresh never drops queued saves or deletions.
let unsentChanges = (syncEngine?.state.pendingRecordZoneChanges ?? []) + pendingChangesBuffer
// Clear local sync state so CKSyncEngine fetches everything fresh
UserDefaults.standard.removeObject(forKey: syncStateKey)
// Tear down existing engine
debounceTimer?.invalidate()
debounceTimer = nil
pendingChangesBuffer.removeAll()
conflictResolvedRecords.removeAll()
retryCount.removeAll()
syncEngine = nil
pendingChangesBuffer = unsentChanges
updatePendingCount()
// Reinitialize - with the persisted state cleared above, setup starts
// from nil state serialization (forces full fetch)
// from nil state serialization (forces full fetch). Setup hands the
// carried-over buffer to the new engine.
await setupSyncEngine()
if !unsentChanges.isEmpty {
LoggingService.shared.logCloudKit("Refresh sync carried over \(unsentChanges.count) unsent changes")
updatePendingCount()
scheduleDebounceSync()
}
LoggingService.shared.logCloudKit("Refresh sync completed")
}