Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CloudKit - which CKErrors should be handled as .partialFailure, and should they also be handled as a non-partial failure?

I've got my basic CloudKit sync engine built and working correctly and I now I am fleshing out my error handling. I'd like a comprehensive list of which errors are possible per record when you receive a .partialFailure response code.

The documentation has a list of all the error codes, but in my searching it hasn't been obvious (to me) which are potentially going to show up inside the partialErrorsByItemID dictionary and which are going to show up only as error codes (or if they can show up as both, maybe when sending only one record?).

In the Apple CloudKit Share code example there is a CloudKitError class to handle errors, and that handles the following partial errors:

.serverRecordChanged
.zoneNotFound
.unknownItem
.batchRequestFailed

but I don't believe that is exhaustive as the rest of the class isn't exhaustive in handling errors that aren't .partialFailure. Surely .invalidArguments would be a possible partial failure error?

Here's what I would guess I need to cover:

.alreadyShared (if sharing)
.assetFileModified (if using Assets)
.assetFileNotFound (if using Assets)
.batchRequestFailed
.constraintViolation
.invalidArguments
.referenceViolation (if sharing)
.serverRecordChanged
.unknownItem
.zoneBusy?
.zoneNotFound

And finally, because these are handled as partial errors, do I also need to handle them as possible error code responses from CloudKit, in the same way I handle non-partial error codes like .serviceUnavailable? I am not using the CKDatabase convenience methods, I'm using the full operations like CKModifyRecordsOperation, if that matters?

Thanks in advance!

like image 239
Brian M Avatar asked Mar 15 '18 18:03

Brian M


1 Answers

In CloudKit, you have convenience API and Batch Operations API. If you are only using the convenience API in your app, this means that you add/update/fetch/delete a single record at a time. Thus, you will never get CKErrorPartialFailure because you are NOT communicating with iCloud Server in batches. If you are using only Batch Operations API in your app, then you will get CKErrorPartialFailure. It is a high-level error that actually contains a sub-error (CKError instance) for each record/zone/subscription included in your operation.

I agree with you that the documentation is not clear what could occur only as a partial error and what could not. Plus what could occur in either case. To answer this question, you can take a simple approach by assuming that all errors might occur in both cases or you either another more detailed oriented approach by finding out the possible cases for each error.

For the second approach, I had to simulate different error scenarios and see which errors I get from the iCloud server. Please take the following points into consideration:

  1. Try as many CKOperation as you can to get list of errors. You have operations for records, zones, database, subscriptions.
  2. Is the operation atomic or not?
  3. Some errors are impossible to simulate because we don't control iCloud Server responses by any means. Example: CKInternalError, CKServerRejectedRequest
  4. Some errors would only occur during Development phase and should not occur during Production phase. Example: CKBadContainer,CKMissingEntitlement,CKBadDatabase
  5. Some errors are clearly non-partial errors because they are more related to the whole request sent to iCloud. Examples: CKIncompatibleVersion, CKServiceUnavailable, CKRequestRateLimited, CKOperationCancelled, CKLimitExceeded, CKServerResponseLost, CKManagedAccountRestricted
  6. Some errors can only occur as partial errors. Example CKBatchRequestFailed. This one only occur for atomic CKOperations
  7. Some errors can occur as both partial/non-partial errors. Examples: CKNotAuthenticated, CKNetworkUnavailable, CKNetworkFailure. They occur as a partial error for record zone operations while they occur as non-partial error for records operations.
  8. Some Zone related errors will appear as partial errors when using Batch Operations API. Examples:CKUserDeletedZone , CKZoneBusy. Exception: CKChangeTokenExpired I got it as a non-partial error when I was performing an operation-based call.
  9. CKZoneNotFound occurs as a partial and non-partial error. If you use CKModifyRecordsOperation to upload to a non-existing zone, you will get a partial error. However, if you use CKFetchRecordZoneChanges to fetch from a non-existing zone, you will get non-partial error.
  10. Merge Conflicts errors occur as a partial error when using Batch Operations API.
  11. In WWDC 2015 Video, CKInvalidArguments was mentioned as one of the errors that might occur as partial error when using Batch Operations API. However, I tried different error scenarios (such as: creating/updating a record in the same request) and it occurs as a non-partial error. So to be in the safe side, I might handle it for both partial and non-partial errors.
  12. CKQuotaExceeded occurs as a non partial error. I managed to reproduce that error by filling my iCloud storage by data from different apps except Photos. Backup will fill most of the storage then it won't be hard to fill in the rest of the available space.
  13. CKUnkownItem occurs as a non-partial error when using convenience API. Also occurs as a partial error when using Batch Operation API.
  14. All the sharing/assets related-errors, I am not familiar with them but I think the relative ones that you listed in your question, are good to be considered as partial errors.
like image 128
Wael Showair Avatar answered Nov 18 '22 21:11

Wael Showair