Change to save new records only if there isn't already a server side record
This commit is contained in:
parent
aa3b1771e7
commit
6c6f401e3e
|
@ -14,6 +14,7 @@ struct CloudKitArticleStatusUpdate {
|
|||
|
||||
enum Record {
|
||||
case all
|
||||
case new
|
||||
case statusOnly
|
||||
case delete
|
||||
}
|
||||
|
@ -27,6 +28,10 @@ struct CloudKitArticleStatusUpdate {
|
|||
return .delete
|
||||
}
|
||||
|
||||
if statuses.count == 1, statuses.first!.key == .new {
|
||||
return .new
|
||||
}
|
||||
|
||||
if let article = article {
|
||||
if article.status.read == false || article.status.starred == true {
|
||||
return .all
|
||||
|
|
|
@ -111,6 +111,7 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||
}
|
||||
|
||||
var modifyRecords = [CKRecord]()
|
||||
var newRecords = [CKRecord]()
|
||||
var deleteRecordIDs = [CKRecord.ID]()
|
||||
|
||||
for statusUpdate in statusUpdates {
|
||||
|
@ -118,6 +119,9 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||
case .all:
|
||||
modifyRecords.append(makeStatusRecord(statusUpdate))
|
||||
modifyRecords.append(makeArticleRecord(statusUpdate.article!))
|
||||
case .new:
|
||||
newRecords.append(makeStatusRecord(statusUpdate))
|
||||
newRecords.append(makeArticleRecord(statusUpdate.article!))
|
||||
case .delete:
|
||||
deleteRecordIDs.append(CKRecord.ID(recordName: statusID(statusUpdate.articleID), zoneID: Self.zoneID))
|
||||
case .statusOnly:
|
||||
|
@ -126,10 +130,17 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||
}
|
||||
}
|
||||
|
||||
self.modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
|
||||
modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
completion(.success(()))
|
||||
self.saveIfNew(newRecords) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
completion(.success(()))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
self.handleModifyArticlesError(error, statusUpdates: statusUpdates, completion: completion)
|
||||
}
|
||||
|
|
|
@ -234,6 +234,80 @@ extension CloudKitZone {
|
|||
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
||||
}
|
||||
|
||||
/// Saves or modifies the records as long as they are unchanged relative to the local version
|
||||
func saveIfNew(_ records: [CKRecord], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
let op = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: [CKRecord.ID]())
|
||||
op.savePolicy = .ifServerRecordUnchanged
|
||||
op.isAtomic = false
|
||||
|
||||
op.modifyRecordsCompletionBlock = { [weak self] (_, _, error) in
|
||||
|
||||
guard let self = self else { return }
|
||||
|
||||
switch CloudKitZoneResult.resolve(error) {
|
||||
case .success, .partialFailure:
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
case .zoneNotFound:
|
||||
self.createZoneRecord() { result in
|
||||
switch result {
|
||||
case .success:
|
||||
self.saveIfNew(records, completion: completion)
|
||||
case .failure(let error):
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case .userDeletedZone:
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(CloudKitZoneError.userDeletedZone))
|
||||
}
|
||||
|
||||
case .retry(let timeToWait):
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.saveIfNew(records, completion: completion)
|
||||
}
|
||||
|
||||
case .limitExceeded:
|
||||
|
||||
let chunkedRecords = records.chunked(into: 300)
|
||||
|
||||
let group = DispatchGroup()
|
||||
var errorOccurred = false
|
||||
|
||||
for chunk in chunkedRecords {
|
||||
group.enter()
|
||||
self.saveIfNew(chunk) { result in
|
||||
if case .failure(let error) = result {
|
||||
os_log(.error, log: self.log, "%@ zone modify records error: %@", Self.zoneID.zoneName, error.localizedDescription)
|
||||
errorOccurred = true
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
if errorOccurred {
|
||||
completion(.failure(CloudKitZoneError.unknown))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(CloudKitError(error!)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
database?.add(op)
|
||||
}
|
||||
|
||||
/// Save the CKSubscription
|
||||
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
||||
database?.save(subscription) { [weak self] savedSubscription, error in
|
||||
|
|
Loading…
Reference in New Issue