Configuring CloudKit CKModifyRecordsOperation retries to prevent duplicate writes
0 reputation · 25 Feb 2024, 03:26 UTC
0 reputation · 25 Feb 2024, 03:26 UTC
Configure a CloudKit modify operation so that a retry after a timeout or rate‑limited error does not create a duplicate record and does not silently overwrite concurrent edits made by another client.
The operation uses a fixed CKRecord.ID to guarantee idempotency, but the chosen savePolicy (.ifServerRecordUnchanged, .changedKeys, .allKeys) determines how a retried save interacts with the server version. When the server returns CKError.serverRecordChanged, the app must decide whether to treat the error as a final conflict, merge the locally changed keys, or overwrite the server record. Additionally, partialFailure results and the isAtomic flag affect whether a batch‑level retry resends only the failed records or the whole set, and the retry‑after delay must be respected to avoid hitting rate limits.
Because the documentation leaves the conflict‑resolution strategy to the developer, the exact behavior that satisfies both “no duplicate writes” and “preserve concurrent edits” remains an open decision.
30775 reputation · 25 Feb 2024, 04:10 UTC
To prevent duplicate records and avoid overwriting concurrent edits during a retry, use savePolicy = .ifServerRecordUnchanged. This policy ensures the operation only succeeds if the record's change tag on the server matches the tag of the local record being uploaded.
Because .ifServerRecordUnchanged will trigger a CKError.serverRecordChanged if another client has modified the record, you must implement a merge strategy rather than a blind retry. The recommended workflow is:
userInfo dictionary of the CKError.serverRecordChanged error.CKModifyRecordsOperation with the merged record.To handle partial failures without duplicating work or creating inconsistent states, configure the operation as follows:
isAtomic = true: This ensures that the entire batch succeeds or fails together. If the operation is not atomic, some records may save while others fail, complicating the retry logic.CKError.partialFailure: If isAtomic is false, you must inspect the CKPartialErrorsByItemIDKey in the error's userInfo. Only retry the specific CKRecord.IDs that failed.CKErrorRetryAfterKey: Always check the userInfo for a retry delay. Attempting a retry before this duration expires often results in immediate subsequent rate-limiting errors.| Goal | Configuration/Action |
|---|---|
| Prevent Overwrites | savePolicy = .ifServerRecordUnchanged |
| Prevent Duplicates | Use fixed CKRecord.ID |
| Handle Conflicts | Merge local keys into server record version |
| Batch Integrity | isAtomic = true |
Diagnostic Note: Are you using a custom CKRecordZone? If you are using the Default Zone, certain atomic behaviors and batching limits differ from Custom Zones, which may change how partialFailure is handled.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.