Repository navigation
Conversation
…` and `add(pendingDatabaseChanges:)`
| if changes[id] == change { | ||
| changes.removeValue(forKey: id) | ||
| } |
There was a problem hiding this comment.
As compared to the add methods which now dedupe on ID, remove must only remove fully matching changes (ID + type). This behavior needs to be preserved. Since storage is no longer a Set, we can't use the convenient subtract method anymore and must manually check for full change equality before removing.
|
Hey @jsutula, thanks for the PR! I rebased this on all the work we merged today, and things are looking good. Will either merge this soon, or may spend some time investigating a fix. |
|
I just pushed 3aec4e3 that now fixes the delete+reinsert bug. Could you give it a test and let me know if it works for you? |
|
Great, looks like a clean fix. To test, I rebased the original live repro setup on top of these changes - jsutula@5271521. Result: data loss no longer occurs on every other update.
|
Refs #418.
Two small stacked commits extracted from #421:
1. Dedupe by ID in
MockSyncEngineStateadd(pendingRecordZoneChanges:)andadd(pendingDatabaseChanges:)According to Apple docs for
CKSyncEngine.State.add(pendingRecordZoneChanges:), for a givenCKRecord.ID, adding a delete after a save discards the save, and adding a save after a delete discards the delete.In other words, pending save and delete changes are deduplicated by
CKRecord.ID, retaining the last change added. The same is true forCKSyncEngine.State.add(pendingDatabaseChanges:), but deduped onCKRecordZone.IDinstead ofCKRecord.ID.Currently
MockSyncEngineStateonly deduplicates fully identical changes (ID + type(save/delete)) in itsaddmethods. This commit changes its implementation to matchCKSyncEngine.Statebehavior and dedupe on ID alone. This is accomplished by switching its internal pending changes storage:OrderedSet<CKSyncEngine.PendingRecordZoneChange>->OrderedDictionary<CKRecord.ID, CKSyncEngine.PendingRecordZoneChange>OrderedSet<CKSyncEngine.PendingDatabaseChange>->OrderedDictionary<CKRecordZone.ID, CKSyncEngine.PendingDatabaseChange>.2. Add failing test to demonstrate delete-then-reinsert issue #418
(failing assertions wrapped in
withKnownIssue)In order to be meaningful, this new test depends on the
MockSyncEngineStatechanges in the first commit. Without the mock changes, a fix for #418 that queues a save after the delete would result inMockSyncEngineStateholding both the pending save and the pending delete (since there's no deduping on ID). With both present, only the delete is handled, and the result would be an unexpectedly empty CloudKit and still-failing assertions, even though the realCKSyncEnginewould discard the delete and send only the save.