Remove save if new process that was throwing us out of sync

This commit is contained in:
Maurice Parker 2020-04-28 11:19:33 -05:00
parent 616597231e
commit 128fcbae5d
2 changed files with 24 additions and 106 deletions

View File

@ -95,7 +95,7 @@ final class CloudKitArticlesZone: CloudKitZone {
records.append(makeArticleRecord(saveArticle))
}
saveIfNew(records, completion: completion)
save(records, completion: completion)
}
func deleteArticles(_ webFeedExternalID: String, completion: @escaping ((Result<Void, Error>) -> Void)) {
@ -110,18 +110,12 @@ final class CloudKitArticlesZone: CloudKitZone {
return
}
var newRecords = [CKRecord]()
var modifyRecords = [CKRecord]()
var deleteRecordIDs = [CKRecord.ID]()
for statusArticle in statusArticles {
switch (statusArticle.status.key, statusArticle.status.flag) {
case (.new, true):
newRecords.append(makeStatusRecord(statusArticle))
if let article = statusArticle.article {
newRecords.append(makeArticleRecord(article))
}
case (.new, false):
case (.new, _):
modifyRecords.append(makeStatusRecord(statusArticle))
if let article = statusArticle.article {
if article.status.read == false || article.status.starred == true {
@ -141,25 +135,12 @@ final class CloudKitArticlesZone: CloudKitZone {
}
}
saveIfNew(newRecords) { result in
if case .failure(let error) = result, case CloudKitZoneError.userDeletedZone = error {
self.createZoneRecord() { result in
switch result {
case .success:
self.modifyArticles(statusArticles, completion: completion)
case .failure(let error):
completion(.failure(error))
}
}
} else {
self.modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
switch result {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
}
}
self.modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
switch result {
case .success:
completion(.success(()))
case .failure(let error):
self.handleModifyArticlesError(error, statusArticles: statusArticles, completion: completion)
}
}
}
@ -167,7 +148,22 @@ final class CloudKitArticlesZone: CloudKitZone {
}
private extension CloudKitArticlesZone {
func handleModifyArticlesError(_ error: Error, statusArticles: [(status: SyncStatus, article: Article?)], completion: @escaping ((Result<Void, Error>) -> Void)) {
if case CloudKitZoneError.userDeletedZone = error {
self.createZoneRecord() { result in
switch result {
case .success:
self.modifyArticles(statusArticles, completion: completion)
case .failure(let error):
completion(.failure(error))
}
}
} else {
completion(.failure(error))
}
}
func statusID(_ id: String) -> String {
return "s|\(id)"
}

View File

@ -234,84 +234,6 @@ 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) {
guard !records.isEmpty else {
completion(.success(()))
return
}
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 {
completion(.failure(CloudKitZoneError.unknown))
return
}
switch CloudKitZoneResult.resolve(error) {
case .success:
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):
os_log(.error, log: self.log, "%@ zone save if new retry in %f seconds.", Self.zoneID.zoneName, 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