diff --git a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift index 6b304c1a4..cbd4eab29 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift @@ -569,14 +569,15 @@ private extension CloudKitAccountDelegate { func combinedRefresh(_ account: Account, _ webFeeds: Set, completion: @escaping () -> Void) { - var newAndUpdatedArticles = Set
() + var newArticles = Set
() + var updatedArticles = Set
() var deletedArticles = Set
() var refresherWebFeeds = Set() let group = DispatchGroup() - - refreshProgress.addToNumberOfTasksAndRemaining(2) - + + refreshProgress.addToNumberOfTasksAndRemaining(3) + for webFeed in webFeeds { if let components = URLComponents(string: webFeed.url), let feedProvider = FeedProviderManager.shared.best(for: components) { group.enter() @@ -588,8 +589,8 @@ private extension CloudKitAccountDelegate { switch result { case .success(let articleChanges): - newAndUpdatedArticles.formUnion(articleChanges.newArticles ?? Set
()) - newAndUpdatedArticles.formUnion(articleChanges.updatedArticles ?? Set
()) + newArticles.formUnion(articleChanges.newArticles ?? Set
()) + updatedArticles.formUnion(articleChanges.updatedArticles ?? Set
()) deletedArticles.formUnion(articleChanges.deletedArticles ?? Set
()) self.refreshProgress.completeTask() @@ -616,25 +617,48 @@ private extension CloudKitAccountDelegate { group.enter() refresher.refreshFeeds(refresherWebFeeds) { refresherNewArticles, refresherUpdatedArticles, refresherDeletedArticles in - newAndUpdatedArticles.formUnion(refresherNewArticles) - newAndUpdatedArticles.formUnion(refresherUpdatedArticles) + newArticles.formUnion(refresherNewArticles) + updatedArticles.formUnion(refresherUpdatedArticles) deletedArticles.formUnion(refresherDeletedArticles) group.leave() } group.notify(queue: DispatchQueue.main) { - - self.articlesZone.deleteArticles(deletedArticles) { _ in - self.refreshProgress.completeTask() - self.saveNewArticles(newAndUpdatedArticles) { + self.processRecords(new: newArticles, updated: updatedArticles, deleted: deletedArticles) { + self.articlesZone.fetchChangesInZone() { _ in + self.refreshProgress.completeTask() completion() } } - } } + func processRecords(new: Set
, updated: Set
, deleted: Set
, completion: @escaping () -> Void) { + + self.articlesZone.deleteArticles(deleted) { result in + self.refreshProgress.completeTask() + switch result { + case .success: + self.articlesZone.modifyArticles(updated) { result in + self.refreshProgress.completeTask() + switch result { + case .success: + self.saveNewArticles(new) { + completion() + } + case .failure(let error): + os_log(.error, log: self.log, "CloudKit modify articles error: %@.", error.localizedDescription) + completion() + } + } + case .failure(let error): + os_log(.error, log: self.log, "CloudKit delete articles error: %@.", error.localizedDescription) + completion() + } + } + } + func saveNewArticles(_ articles: Set
, completion: @escaping () -> Void) { let group = DispatchGroup() @@ -643,22 +667,22 @@ private extension CloudKitAccountDelegate { for articleGroup in articleGroups { group.enter() - self.articlesZone.saveNewArticles(articleGroup) { _ in + self.articlesZone.saveNewArticles(articleGroup) { result in self.refreshProgress.completeTask() group.leave() + if case .failure(let error) = result { + os_log(.error, log: self.log, "CloudKit new articles error: %@.", error.localizedDescription) + } } } group.notify(queue: DispatchQueue.main) { - self.articlesZone.fetchChangesInZone() { _ in - self.refreshProgress.completeTask() - completion() - } + completion() } } func createProviderWebFeed(for account: Account, urlComponents: URLComponents, editedName: String?, container: Container, feedProvider: FeedProvider, completion: @escaping (Result) -> Void) { - refreshProgress.addToNumberOfTasksAndRemaining(5) + refreshProgress.addToNumberOfTasksAndRemaining(6) feedProvider.assignName(urlComponents) { result in self.refreshProgress.completeTask() @@ -691,20 +715,17 @@ private extension CloudKitAccountDelegate { switch result { case .success(let articleChanges): - var newAndUpdatedArticles = articleChanges.newArticles ?? Set
() - newAndUpdatedArticles.formUnion(articleChanges.updatedArticles ?? Set
()) + let newArticles = articleChanges.newArticles ?? Set
() + let updatedArticles = articleChanges.updatedArticles ?? Set
() let deletedArticles = articleChanges.deletedArticles ?? Set
() - self.articlesZone.deleteArticles(deletedArticles) { _ in - self.refreshProgress.completeTask() - self.articlesZone.saveNewArticles(newAndUpdatedArticles) { _ in - self.articlesZone.fetchChangesInZone() { _ in - self.refreshProgress.clear() - completion(.success(feed)) - } + self.processRecords(new: newArticles, updated: updatedArticles, deleted: deletedArticles) { + self.articlesZone.fetchChangesInZone() { _ in + self.refreshProgress.clear() + completion(.success(feed)) } } - + case .failure(let error): self.refreshProgress.clear() completion(.failure(error)) @@ -733,7 +754,7 @@ private extension CloudKitAccountDelegate { func createRSSWebFeed(for account: Account, url: URL, editedName: String?, container: Container, completion: @escaping (Result) -> Void) { BatchUpdate.shared.start() - refreshProgress.addToNumberOfTasksAndRemaining(5) + refreshProgress.addToNumberOfTasksAndRemaining(6) FeedFinder.find(url: url) { result in self.refreshProgress.completeTask() @@ -774,22 +795,18 @@ private extension CloudKitAccountDelegate { feed.externalID = externalID - var newAndUpdatedArticles = articleChanges.newArticles ?? Set
() - newAndUpdatedArticles.formUnion(articleChanges.updatedArticles ?? Set
()) + let newArticles = articleChanges.newArticles ?? Set
() + let updatedArticles = articleChanges.updatedArticles ?? Set
() let deletedArticles = articleChanges.deletedArticles ?? Set
() - self.articlesZone.deleteArticles(deletedArticles) { _ in - self.refreshProgress.completeTask() - self.articlesZone.saveNewArticles(newAndUpdatedArticles) { _ in - self.articlesZone.fetchChangesInZone() { _ in - self.refreshProgress.clear() - completion(.success(feed)) - } + self.processRecords(new: newArticles, updated: updatedArticles, deleted: deletedArticles) { + self.articlesZone.fetchChangesInZone() { _ in + self.refreshProgress.clear() + completion(.success(feed)) } } case .failure(let error): - BatchUpdate.shared.end() self.refreshProgress.clear() completion(.failure(error)) } @@ -797,6 +814,7 @@ private extension CloudKitAccountDelegate { } case .failure(let error): + BatchUpdate.shared.end() self.refreshProgress.clear() completion(.failure(error)) } diff --git a/Frameworks/Account/CloudKit/CloudKitArticlesZone.swift b/Frameworks/Account/CloudKit/CloudKitArticlesZone.swift index 001cefa88..174b028cf 100644 --- a/Frameworks/Account/CloudKit/CloudKitArticlesZone.swift +++ b/Frameworks/Account/CloudKit/CloudKitArticlesZone.swift @@ -79,8 +79,13 @@ final class CloudKitArticlesZone: CloudKitZone { return } - let records = makeRecords(articles) + var records = [CKRecord]() + let saveArticles = articles.filter { $0.status.read == false || $0.status.starred == true } + for saveArticle in saveArticles { + records.append(contentsOf: makeArticleRecords(saveArticle)) + } + saveIfNew(records, completion: completion) } @@ -115,7 +120,17 @@ final class CloudKitArticlesZone: CloudKitZone { return } - let records = makeRecords(articles) + var records = [CKRecord]() + + let saveArticles = articles.filter { $0.status.read == false || $0.status.starred == true } + for saveArticle in saveArticles { + records.append(contentsOf: makeArticleRecords(saveArticle)) + } + + let hollowArticles = articles.subtracting(saveArticles) + for hollowArticle in hollowArticles { + records.append(contentsOf: makeHollowArticleRecords(hollowArticle)) + } self.modify(recordsToSave: records, recordIDsToDelete: []) { result in switch result { @@ -146,22 +161,6 @@ private extension CloudKitArticlesZone { } } - func makeRecords(_ articles: Set
) -> [CKRecord] { - var records = [CKRecord]() - - let saveArticles = articles.filter { $0.status.read == false || $0.status.starred == true } - for saveArticle in saveArticles { - records.append(contentsOf: makeArticleRecords(saveArticle)) - } - - let hollowArticles = articles.subtracting(saveArticles) - for hollowArticle in hollowArticles { - records.append(contentsOf: makeHollowArticleRecords(hollowArticle)) - } - - return records - } - func makeArticleRecords(_ article: Article) -> [CKRecord] { var records = [CKRecord]()