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 {
|
enum Record {
|
||||||
case all
|
case all
|
||||||
|
case new
|
||||||
case statusOnly
|
case statusOnly
|
||||||
case delete
|
case delete
|
||||||
}
|
}
|
||||||
@ -27,6 +28,10 @@ struct CloudKitArticleStatusUpdate {
|
|||||||
return .delete
|
return .delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if statuses.count == 1, statuses.first!.key == .new {
|
||||||
|
return .new
|
||||||
|
}
|
||||||
|
|
||||||
if let article = article {
|
if let article = article {
|
||||||
if article.status.read == false || article.status.starred == true {
|
if article.status.read == false || article.status.starred == true {
|
||||||
return .all
|
return .all
|
||||||
|
@ -111,6 +111,7 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var modifyRecords = [CKRecord]()
|
var modifyRecords = [CKRecord]()
|
||||||
|
var newRecords = [CKRecord]()
|
||||||
var deleteRecordIDs = [CKRecord.ID]()
|
var deleteRecordIDs = [CKRecord.ID]()
|
||||||
|
|
||||||
for statusUpdate in statusUpdates {
|
for statusUpdate in statusUpdates {
|
||||||
@ -118,6 +119,9 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||||||
case .all:
|
case .all:
|
||||||
modifyRecords.append(makeStatusRecord(statusUpdate))
|
modifyRecords.append(makeStatusRecord(statusUpdate))
|
||||||
modifyRecords.append(makeArticleRecord(statusUpdate.article!))
|
modifyRecords.append(makeArticleRecord(statusUpdate.article!))
|
||||||
|
case .new:
|
||||||
|
newRecords.append(makeStatusRecord(statusUpdate))
|
||||||
|
newRecords.append(makeArticleRecord(statusUpdate.article!))
|
||||||
case .delete:
|
case .delete:
|
||||||
deleteRecordIDs.append(CKRecord.ID(recordName: statusID(statusUpdate.articleID), zoneID: Self.zoneID))
|
deleteRecordIDs.append(CKRecord.ID(recordName: statusID(statusUpdate.articleID), zoneID: Self.zoneID))
|
||||||
case .statusOnly:
|
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 {
|
switch result {
|
||||||
case .success:
|
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):
|
case .failure(let error):
|
||||||
self.handleModifyArticlesError(error, statusUpdates: statusUpdates, completion: completion)
|
self.handleModifyArticlesError(error, statusUpdates: statusUpdates, completion: completion)
|
||||||
}
|
}
|
||||||
|
@ -234,6 +234,80 @@ extension CloudKitZone {
|
|||||||
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
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
|
/// Save the CKSubscription
|
||||||
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
||||||
database?.save(subscription) { [weak self] savedSubscription, error in
|
database?.save(subscription) { [weak self] savedSubscription, error in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user