Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

the safeCopy method of CKRecord (YapDatabaseCloudKit) is slow and will casue UI freeze when handlePartialFailure called. #246

Closed
ainopara opened this issue Nov 17, 2015 · 2 comments

Comments

@ainopara
Copy link
Contributor

As shown in profile screen shot, changeSetsFromPreviousCommits method is called to get the first change set (i.e. last failed change set), but all the CKRecords in the change set queue will be safe copied.
In my case, there are 50 records in every change set and 130 change sets in queue waiting to upload, and unfortunately some records in upload queue is already exists in cloud server while client think it is up to date, that will lead to handlePartialFailure be called.
I can try to dispatch the handle code to background thread to avoid UI freeze but it will still consume cpu time and drain battery.

robbiehanson added a commit that referenced this issue Nov 24, 2015
@robbiehanson
Copy link
Contributor

I believe I've addressed the performance problems via the above referenced commits. Please give them a try and let me know.

In my case, there are [...] 130 change sets in queue waiting to upload

That's a lot of change sets in the queue. Is this normal? Is there perhaps a problem that's preventing changeSets from getting to the server?

Your screenshot shows that [CloutKitManager _refetchMissedRecordIDs] is being invoked. This may be a problem. From the code:

if ([failedChangeSet.uuid isEqualToString:lastChangeSetUUID] && self.lastSuccessfulFetchResultWasNoData)
{
    // We screwed up a merge somehow.
    //
    // Here's what happend:
    // - We fetched all the record changes (via CKFetchRecordChangesOperation).
    // - But we failed to merge the fetched changes into our local CKRecord(s).
    //   This could be a bug in YapDatabaseCloudKit.
    //   Or maybe a bug in your CKFetchRecordChangesOperation.fetchRecordChangesCompletionBlock implementation.
    // - So at this point we'd normally fall into an infinite loop:
    //     - We do a CKFetchRecordChangesOperation
    //     - Find there's no new data (since prevServerChangeToken)
    //     - Attempt to upload our modified CKRecord(s)
    //     - Get a partial failure
    //     - We do a CKFetchRecordChangesOperation
    //     - ... infinte loop
    //
    // This is a common problem you might run into during the normal development cycle.
    // So we print out a warning here to let you know about the problem.
    //
    // And then we refetch the missed records.
    // Hopefully refetching & re-merging should solve the infinite loop problem.

    self.needsRefetchMissedRecordIDs = YES;
    [self _refetchMissedRecordIDs];
}

Is there a chance your code is in an infinite loop, and continually:

  • Fails to upload a changeSet (partial failure, one or more records is out-of-date)
  • Out-of-date record(s) are fetched
  • Results are not properly merged
  • Retries upload
  • Fails to upload a changeSet (partial failure, one or more records is out-of-date)
  • ...

@ainopara
Copy link
Contributor Author

Thank you for your update.
In my use case, I store forum thread visit history, and the CKRecordID can be same for history data generated in difference device.
The failure is due to some mistake on my code when trying to offer switch to disable cloudkit sync.
It will not lead to an infinite loop because the failure is just caused by forget to delete ServerChangeToken when unregistering the cloudkit extension. Then when the cloudkit extension be registered next time(people turn the switch on), It will trying to generate all the CKRecord corresponding to those keys in database. Fetch record changes will be skipped with the ServerChangeToken, as a result, app will upload those CKRecord generated by itself rather than server version, so server will say the record to insert is already existed in server. handlePartialFailure method can resolve by refetch the server record and merge it to database.
I also noticed an issue that will lead to failed merge, I think it is better to talk about that in a new issue.
At last, Thank you for your good works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants