Hey,
I'm currently working on adding CloudKit support to the GRDB
SQLite database in my app. CKSyncEngine
, though still a bit tricky to wrap your head around, is amazing!
I have most of the basic setup implemented and some very easy cases already work, which is really exciting!
However, I do have some questions regarding data consistency across devices. I'm not sure though, that these questions are actually "correct" to ask. Maybe my entire approach is inherently flawed.
Say we add two records to the pending changes of the sync engine:
// I'm simplifying CKRecord.ID to be a String here
syncEngine.state.add(pendingRecordZoneChanges: [.saveRecord("1"), .saveRecord("2")]
Let's also say that both records are tightly connected. For example, they could be in a one-to-one relationship and must always be added to the database together because the app relies on the existence of either none or both.
After that call, at some later point, the system will call the sync engine's delegate nextRecordZoneChangeBatch(_:syncEngine:)
for us to batch the changes together to send to iCloud.
First question: Can we guarantee that records "1" and "2" always land in the exact same batch, and are never separated?
Looking at the example code, there are two line that worry me a bit:
// (Sample project: `SyncedDatabase.swift, lines 132-133`)
let scope = context.options.scope
let changes = syncEngine.state.pendingRecordZoneChanges.filter { scope.contains($0) }
The scope
could lead to one of the two records being filtered out. However, my assumption is that the scope will always be .all
when the system calls it from an automatically managed schedule, and only differs when you manually specify a different value through calling syncEngine.sendChanges(_:)
. Is that correct?
Now back to the example. Say we successfully batched records "1" and "2" together and the changes have been sent to iCloud. Awesome!
What happens next? Other connected devices will, at some point, fetch those changes and apply them to their respective local databases.
Second question: Can we guarantee that iCloud sends the exact same batches from earlier to other devices and does not create new batches from all the changes?
I'm worried that iCloud might take all stored changes and "re-batch" them for whatever reason (efficiency, for example). Because that could cause records "1" and "2" to be separated into different batches. A second device could end up receiving "1" and, for at least some period of time, will not receive "2", which would be an "illegal" state of the data.
I'd appreciate any help or clarification on this :)
Thanks a lot!