YapDatabase
YapDatabase copied to clipboard
recordChangeTag not getting saved after YapDatabaseCloudKitTransaction.mergeRecord
I posted about this on the mailing list, but no replies so far. To summarize, it seems that when I call YapDatabaseCloudKitTransaction.mergeRecord
with a record I received from a CKFetchRecordChangesOperation
, the new record's recordChangeTag
isn't getting saved.
It's likely this is just a bug in my code, but I can't see what I'm doing wrong if so. To compound the problem, I can't figure out how to set YapDB's logging level. YapDatabaseLogging.h
has various #defines, but it's not clear to me how to actually use them, especially in the context of CocoaPods.
I figured out how to enable logging, but it hasn't helped so far. I've looked over my code many times and compared it to CloudKitTodo, but can't see why my remote record's change tag isn't getting saved.
In case more detail would help: on startup, my app suspends the YDBCK extension and does a CKFetchRecordChangesOperation
before resuming it. Taking the record I get from that operation, I compare its change tag to YDBCK's local record change tag (obtained via getRecordChangeTag
) and see that they are different (let's say the local record's change tag is "a" and the remote record's tag is "b").
So I invoke mergeRecord
, which calls my mergeBlock with what seem like the right values: pendingLocalRecord
is nil, and updatedPendingLocalRecord
has the new change tag "b" as I'd expect. All my mergeBlock does then is call setObject:forKey:inCollection:
, and everything seems to work.
But the next time my app modifies the database object with that key/collection, YDBCK invokes my recordHandler with a record whose change tag still has the old value "a". So of course when YDBCK then tries to send the updated record to CloudKit, it gets a ServerRecordChanged
error.
AFAICT I'm doing everything as I'm supposed to, so I'm stumped. Any help whatsoever would be much appreciated.
Things are even stranger than I thought. The new recordChangeTag
is getting saved, at least according to what getRecordChangeTag
tells me after my CKFetchRecordChangesOperation
(and the transaction it creates) finishes. So the current situation is:
- YDBCK does save the new remote
recordChangeTag
somewhere after myCKFetchRecordChangesOperation
. - Nevertheless, the next time that database record changes locally,
YapDatabaseCloudKitTransaction._handleChangeWithRowid
is somehow still seeing the oldrecordChangeTag
, which causes conflicts when YDBCK tries to push the change to CloudKit.
At this point I can only suspect a bug in YDBCK, but I don't currently understand its internals well enough to get any farther. Can a developer please help me out here?
With a clearer picture of what's happening, I'm now reasonably certain this is a YDBCK bug. To summarize:
My code asks YDBCK to merge a record received from CloudKit with an existing local record. My mergeBlock
just calls transaction.setObject
to save the remote record, and doesn't touch updatedPendingLocalRecord
. But YDBCK doesn't save the new CKRecord
to its internal cloudKit_record
table, meaning its recordChangeTag
is now stale, which causes conflicts the next time YDBCK tries to update that record.
@robbiehanson , if you don't currently have time to look at this, could I instead get a brief explication of the execution path by which YDBCK saves updated CKRecord
s to disk after a merge? If I understood that better, I'd have a higher chance of tracking down what's going wrong.
This comment in YapDatabaseCloudKitTransaction.m
made me suspicious, since there should be no CKModifyRecordsOperation
involved when I'm refetching and merging a record.
So I tried changing the maybeUpdateRecordTableRowWithHash:info:
call below it to updateRecordTableRowWithHash:record:outSanitizedRecord:
. That does seem to solve the merging problem, but my understanding of YDBCK is not deep enough to say whether it's the right approach or might break something else.
@robbiehanson, any comments?
@zsau Maybe it is better to check if the change is coming from remote merge. Here is my fix: https://github.com/ainopara/YapDatabase/commit/5e9bf96e94c6a1d4014b1b0f963ed6b4cef341b4