From 951349ffc5f80a60b25a096c95924e4d61a06b58 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 25 Mar 2024 21:44:25 -0700 Subject: [PATCH] Continue deleting completion-based functions in SyncDatabase. --- .../CloudKitArticlesZoneDelegate.swift | 56 +++++++++---------- .../Feedbin/FeedbinAccountDelegate.swift | 34 ++++++----- ...edlyIngestStarredArticleIdsOperation.swift | 16 +++--- ...eedlyIngestUnreadArticleIdsOperation.swift | 16 +++--- .../NewsBlurAccountDelegate+Internal.swift | 25 +++++---- .../ReaderAPI/ReaderAPIAccountDelegate.swift | 19 +++---- .../Sources/SyncDatabase/SyncDatabase.swift | 29 +--------- 7 files changed, 81 insertions(+), 114 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift index bfa90191e..7861e2153 100644 --- a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift @@ -20,38 +20,39 @@ import CloudKitExtras class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate { private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit") - + weak var account: Account? var database: SyncDatabase weak var articlesZone: CloudKitArticlesZone? var compressionQueue = DispatchQueue(label: "Articles Zone Delegate Compression Queue") - + init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone) { self.account = account self.database = database self.articlesZone = articlesZone } - + func cloudKitDidModify(changed: [CKRecord], deleted: [CloudKitRecordKey], completion: @escaping (Result) -> Void) { - + database.selectPendingReadStatusArticleIDs() { result in switch result { case .success(let pendingReadStatusArticleIDs): - self.database.selectPendingStarredStatusArticleIDs() { result in - switch result { - case .success(let pendingStarredStatusArticleIDs): + Task { @MainActor in + do { + + let pendingStarredStatusArticleIDs = (try await self.database.selectPendingStarredStatusArticleIDs()) ?? Set() self.delete(recordKeys: deleted, pendingStarredStatusArticleIDs: pendingStarredStatusArticleIDs) { Task { @MainActor in self.update(records: changed, - pendingReadStatusArticleIDs: pendingReadStatusArticleIDs, - pendingStarredStatusArticleIDs: pendingStarredStatusArticleIDs, - completion: completion) + pendingReadStatusArticleIDs: pendingReadStatusArticleIDs, + pendingStarredStatusArticleIDs: pendingStarredStatusArticleIDs, + completion: completion) } } - - case .failure(let error): + + } catch { os_log(.error, log: self.log, "Error occurred getting pending starred records: %@", error.localizedDescription) completion(.failure(CloudKitZoneError.unknown)) } @@ -70,12 +71,12 @@ private extension CloudKitArticlesZoneDelegate { let receivedRecordIDs = recordKeys.filter({ $0.recordType == CloudKitArticlesZone.CloudKitArticleStatus.recordType }).map({ $0.recordID }) let receivedArticleIDs = Set(receivedRecordIDs.map({ stripPrefix($0.externalID) })) let deletableArticleIDs = receivedArticleIDs.subtracting(pendingStarredStatusArticleIDs) - + guard !deletableArticleIDs.isEmpty else { completion() return } - + Task { @MainActor in try? await self.database.deleteSelectedForProcessing(Array(deletableArticleIDs)) self.account?.delete(articleIDs: deletableArticleIDs) { _ in @@ -98,7 +99,7 @@ private extension CloudKitArticlesZoneDelegate { var errorOccurred = false let group = DispatchGroup() - + group.enter() account?.markAsUnread(updateableUnreadArticleIDs) { databaseError in MainActor.assumeIsolated { @@ -147,7 +148,7 @@ private extension CloudKitArticlesZoneDelegate { compressionQueue.async { let parsedItems = records.compactMap { self.makeParsedItem($0) } let feedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) } - + DispatchQueue.main.async { for (feedID, parsedItems) in feedIDsAndItems { group.enter() @@ -174,7 +175,7 @@ private extension CloudKitArticlesZoneDelegate { } } } - + group.notify(queue: DispatchQueue.main) { if errorOccurred { completion(.failure(CloudKitZoneError.unknown)) @@ -183,7 +184,7 @@ private extension CloudKitArticlesZoneDelegate { } } } - + func stripPrefix(_ externalID: String) -> String { return String(externalID[externalID.index(externalID.startIndex, offsetBy: 2)..() - + let decoder = JSONDecoder() - + if let encodedParsedAuthors = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.parsedAuthors] as? [String] { for encodedParsedAuthor in encodedParsedAuthors { if let data = encodedParsedAuthor.data(using: .utf8), let parsedAuthor = try? decoder.decode(ParsedAuthor.self, from: data) { @@ -204,26 +205,26 @@ private extension CloudKitArticlesZoneDelegate { } } } - + guard let uniqueID = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.uniqueID] as? String, - let feedURL = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.feedURL] as? String else { + let feedURL = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.feedURL] as? String else { return nil } - + var contentHTML = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTML] as? String if let contentHTMLData = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTMLData] as? NSData { if let decompressedContentHTMLData = try? contentHTMLData.decompressed(using: .lzfse) { contentHTML = String(data: decompressedContentHTMLData as Data, encoding: .utf8) } } - + var contentText = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentText] as? String if let contentTextData = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentTextData] as? NSData { if let decompressedContentTextData = try? contentTextData.decompressed(using: .lzfse) { contentText = String(data: decompressedContentTextData as Data, encoding: .utf8) } } - + let parsedItem = ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, @@ -241,8 +242,7 @@ private extension CloudKitArticlesZoneDelegate { authors: parsedAuthors, tags: nil, attachments: nil) - + return parsedItem } - } diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index 1c2840704..ffbcdbf05 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -1360,54 +1360,52 @@ private extension FeedbinAccountDelegate { return } - database.selectPendingStarredStatusArticleIDs() { result in + Task { @MainActor in + + do { + let pendingArticleIDs = (try await self.database.selectPendingStarredStatusArticleIDs()) ?? Set() - MainActor.assumeIsolated { @MainActor func process(_ pendingArticleIDs: Set) { - + let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } ) let updatableFeedbinStarredArticleIDs = feedbinStarredArticleIDs.subtracting(pendingArticleIDs) - + account.fetchStarredArticleIDs { articleIDsResult in - + MainActor.assumeIsolated { guard let currentStarredArticleIDs = try? articleIDsResult.get() else { return } - + let group = DispatchGroup() - + // Mark articles as starred let deltaStarredArticleIDs = updatableFeedbinStarredArticleIDs.subtracting(currentStarredArticleIDs) group.enter() account.markAsStarred(deltaStarredArticleIDs) { _ in group.leave() } - + // Mark articles as unstarred let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(updatableFeedbinStarredArticleIDs) group.enter() account.markAsUnstarred(deltaUnstarredArticleIDs) { _ in group.leave() } - + group.notify(queue: DispatchQueue.main) { completion() } } } - - } - - switch result { - case .success(let pendingArticleIDs): - process(pendingArticleIDs) - case .failure(let error): - os_log(.error, log: self.log, "Sync Article Starred Status failed: %@.", error.localizedDescription) } + + process(pendingArticleIDs) + + } catch { + os_log(.error, log: self.log, "Sync Article Starred Status failed: %@.", error.localizedDescription) } } - } func deleteTagging(for account: Account, with feed: Feed, from container: Container?, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift index 646e06db2..1a51b090b 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift @@ -77,17 +77,15 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation { return } - database.selectPendingStarredStatusArticleIDs { result in - MainActor.assumeIsolated { - switch result { - case .success(let pendingArticleIds): - self.remoteEntryIds.subtract(pendingArticleIds) + Task { @MainActor in - self.updateStarredStatuses() - - case .failure(let error): - self.didFinish(with: error) + do { + if let pendingArticleIDs = try await self.database.selectPendingStarredStatusArticleIDs() { + self.remoteEntryIds.subtract(pendingArticleIDs) } + self.updateStarredStatuses() + } catch { + self.didFinish(with: error) } } } diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift index 882da8b85..cf7b1cf08 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift @@ -78,17 +78,15 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation { return } - database.selectPendingReadStatusArticleIDs { result in - MainActor.assumeIsolated { - switch result { - case .success(let pendingArticleIds): - self.remoteEntryIds.subtract(pendingArticleIds) + Task { @MainActor in - self.updateUnreadStatuses() - - case .failure(let error): - self.didFinish(with: error) + do { + if let pendingArticleIDs = try await self.database.selectPendingReadStatusArticleIDs() { + self.remoteEntryIds.subtract(pendingArticleIDs) } + self.updateUnreadStatuses() + } catch { + self.didFinish(with: error) } } } diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift index 14c8034c2..2bda79cca 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift +++ b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift @@ -381,8 +381,11 @@ extension NewsBlurAccountDelegate { return } - database.selectPendingStarredStatusArticleIDs() { result in - MainActor.assumeIsolated { + Task { @MainActor in + + do { + let pendingArticleIDs = (try await database.selectPendingStarredStatusArticleIDs()) ?? Set() + @MainActor func process(_ pendingStoryHashes: Set) { let newsBlurStarredStoryHashes = Set(hashes.map { $0.hash } ) @@ -393,23 +396,23 @@ extension NewsBlurAccountDelegate { guard let currentStarredArticleIDs = try? articleIDsResult.get() else { return } - + let group = DispatchGroup() - + // Mark articles as starred let deltaStarredArticleIDs = updatableNewsBlurUnreadStoryHashes.subtracting(currentStarredArticleIDs) group.enter() account.markAsStarred(deltaStarredArticleIDs) { _ in group.leave() } - + // Mark articles as unstarred let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(updatableNewsBlurUnreadStoryHashes) group.enter() account.markAsUnstarred(deltaUnstarredArticleIDs) { _ in group.leave() } - + group.notify(queue: DispatchQueue.main) { completion() } @@ -417,12 +420,10 @@ extension NewsBlurAccountDelegate { } } - switch result { - case .success(let pendingArticleIDs): - process(pendingArticleIDs) - case .failure(let error): - os_log(.error, log: self.log, "Sync Story Starred Status failed: %@.", error.localizedDescription) - } + process(pendingArticleIDs) + + } catch { + os_log(.error, log: self.log, "Sync Story Starred Status failed: %@.", error.localizedDescription) } } } diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index 5a8508b28..9a6732d7e 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -1161,9 +1161,12 @@ private extension ReaderAPIAccountDelegate { return } - database.selectPendingStarredStatusArticleIDs() { result in + Task { @MainActor in + + do { + + let pendingArticleIDs = (try await self.database.selectPendingStarredStatusArticleIDs()) ?? Set() - MainActor.assumeIsolated { @MainActor func process(_ pendingArticleIDs: Set) { let updatableReaderUnreadArticleIDs = Set(articleIDs).subtracting(pendingArticleIDs) @@ -1197,15 +1200,11 @@ private extension ReaderAPIAccountDelegate { } } - switch result { - case .success(let pendingArticleIDs): - process(pendingArticleIDs) - case .failure(let error): - os_log(.error, log: self.log, "Sync Article Starred Status failed: %@.", error.localizedDescription) - } + process(pendingArticleIDs) + + } catch { + os_log(.error, log: self.log, "Sync Article Starred Status failed: %@.", error.localizedDescription) } } - } - } diff --git a/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift b/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift index f831b2122..ecdf1dd0c 100644 --- a/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift +++ b/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift @@ -68,7 +68,7 @@ public actor SyncDatabase { return syncStatusTable.selectPendingStarredStatusArticleIDs(database: database) } - public func resetAllSelectedForProcessing() throws { + public func resetAllSelectedForProcessing() throws { guard let database else { throw DatabaseError.suspended @@ -179,33 +179,6 @@ public extension SyncDatabase { } } } - - nonisolated func selectPendingStarredStatusArticleIDs(completion: @escaping SyncStatusArticleIDsCompletionBlock) { - - Task { @MainActor in - do { - if let articleIDs = try await self.selectPendingStarredStatusArticleIDs() { - completion(.success(articleIDs)) - } else { - completion(.success(Set())) - } - } catch { - completion(.failure(DatabaseError.suspended)) - } - } - } - - nonisolated func resetAllSelectedForProcessing(completion: DatabaseCompletionBlock? = nil) { - - Task { @MainActor in - do { - try await self.resetAllSelectedForProcessing() - completion?(nil) - } catch { - completion?(DatabaseError.suspended) - } - } - } } private extension SyncDatabase {