From 4a5cb237a0f715b58c341d1d3cc136d22207f5a5 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 25 Mar 2024 22:47:43 -0700 Subject: [PATCH] Delete last completion-based method in SyncDatabase. --- .../CloudKitSendStatusOperation.swift | 56 +++++++++---------- .../Feedbin/FeedbinAccountDelegate.swift | 31 +++++----- .../FeedlySendArticleStatusesOperation.swift | 18 ++---- .../NewsBlur/NewsBlurAccountDelegate.swift | 30 +++++----- .../ReaderAPI/ReaderAPIAccountDelegate.swift | 33 +++++------ .../Sources/SyncDatabase/SyncDatabase.swift | 28 ---------- 6 files changed, 79 insertions(+), 117 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index c31143cf3..55d377829 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -67,43 +67,39 @@ class CloudKitSendStatusOperation: MainThreadOperation { } private extension CloudKitSendStatusOperation { - + func selectForProcessing() { - database.selectForProcessing(limit: blockSize) { result in - MainActor.assumeIsolated { - switch result { - case .success(let syncStatuses): + Task { @MainActor in - @MainActor func stopProcessing() { - if self.showProgress { - self.refreshProgress?.completeTask() - } - os_log(.debug, log: self.log, "Done sending article statuses.") - self.operationDelegate?.operationDidComplete(self) - } - - guard syncStatuses.count > 0 else { - stopProcessing() - return - } - - self.processStatuses(syncStatuses) { stop in - if stop { - stopProcessing() - } else { - self.selectForProcessing() - } - } - - case .failure(let databaseError): - os_log(.error, log: self.log, "Send status error: %@.", databaseError.localizedDescription) - self.operationDelegate?.cancelOperation(self) + @MainActor func stopProcessing() { + if self.showProgress { + self.refreshProgress?.completeTask() } + os_log(.debug, log: self.log, "Done sending article statuses.") + self.operationDelegate?.operationDidComplete(self) + } + + do { + guard let syncStatuses = try await self.database.selectForProcessing(limit: blockSize), !syncStatuses.isEmpty else { + stopProcessing() + return + } + + self.processStatuses(Array(syncStatuses)) { stop in + if stop { + stopProcessing() + } else { + self.selectForProcessing() + } + } + } catch { + os_log(.error, log: self.log, "Send status error: %@.", error.localizedDescription) + self.operationDelegate?.cancelOperation(self) } } } - + @MainActor func processStatuses(_ syncStatuses: [SyncStatus], completion: @escaping (Bool) -> Void) { guard let account = account, let articlesZone = articlesZone else { completion(true) diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index 89d67f0f1..1700b5e93 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -134,18 +134,21 @@ final class FeedbinAccountDelegate: AccountDelegate { os_log(.debug, log: log, "Sending article statuses...") - database.selectForProcessing { result in + Task { @MainActor in + + do { + + let syncStatuses = (try await self.database.selectForProcessing()) ?? Set() - MainActor.assumeIsolated { @MainActor func processStatuses(_ syncStatuses: [SyncStatus]) { let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false } let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true } let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true } let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false } - + let group = DispatchGroup() var errorOccurred = false - + group.enter() self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) { result in group.leave() @@ -153,7 +156,7 @@ final class FeedbinAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) { result in group.leave() @@ -161,7 +164,7 @@ final class FeedbinAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) { result in group.leave() @@ -169,7 +172,7 @@ final class FeedbinAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) { result in group.leave() @@ -177,7 +180,7 @@ final class FeedbinAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.notify(queue: DispatchQueue.main) { os_log(.debug, log: self.log, "Done sending article statuses.") if errorOccurred { @@ -187,13 +190,11 @@ final class FeedbinAccountDelegate: AccountDelegate { } } } - - switch result { - case .success(let syncStatuses): - processStatuses(syncStatuses) - case .failure(let databaseError): - completion(.failure(databaseError)) - } + + processStatuses(Array(syncStatuses)) + + } catch { + completion(.failure(error)) } } } diff --git a/Account/Sources/Account/Feedly/Operations/FeedlySendArticleStatusesOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlySendArticleStatusesOperation.swift index eeaed5759..be38291db 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlySendArticleStatusesOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlySendArticleStatusesOperation.swift @@ -28,19 +28,13 @@ final class FeedlySendArticleStatusesOperation: FeedlyOperation { override func run() { os_log(.debug, log: log, "Sending article statuses...") - database.selectForProcessing { result in - MainActor.assumeIsolated { - if self.isCanceled { - self.didFinish() - return - } + Task { @MainActor in - switch result { - case .success(let syncStatuses): - self.processStatuses(syncStatuses) - case .failure: - self.didFinish() - } + do { + let syncStatuses = (try await self.database.selectForProcessing()) ?? Set() + self.processStatuses(Array(syncStatuses)) + } catch { + self.didFinish() } } } diff --git a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift index 5f91466b3..5f91b8166 100644 --- a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift @@ -134,10 +134,11 @@ final class NewsBlurAccountDelegate: AccountDelegate { func sendArticleStatus(for account: Account, completion: @escaping (Result) -> ()) { os_log(.debug, log: log, "Sending story statuses...") - database.selectForProcessing { result in + Task { @MainActor in + + do { + let syncStatuses = (try await self.database.selectForProcessing()) ?? Set() - MainActor.assumeIsolated { - @MainActor func processStatuses(_ syncStatuses: [SyncStatus]) { let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false @@ -151,10 +152,10 @@ final class NewsBlurAccountDelegate: AccountDelegate { let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false } - + let group = DispatchGroup() var errorOccurred = false - + group.enter() self.sendStoryStatuses(createUnreadStatuses, throttle: true, apiCall: self.caller.markAsUnread) { result in group.leave() @@ -162,7 +163,7 @@ final class NewsBlurAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendStoryStatuses(deleteUnreadStatuses, throttle: false, apiCall: self.caller.markAsRead) { result in group.leave() @@ -170,7 +171,7 @@ final class NewsBlurAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendStoryStatuses(createStarredStatuses, throttle: true, apiCall: self.caller.star) { result in group.leave() @@ -178,7 +179,7 @@ final class NewsBlurAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.enter() self.sendStoryStatuses(deleteStarredStatuses, throttle: true, apiCall: self.caller.unstar) { result in group.leave() @@ -186,7 +187,7 @@ final class NewsBlurAccountDelegate: AccountDelegate { errorOccurred = true } } - + group.notify(queue: DispatchQueue.main) { os_log(.debug, log: self.log, "Done sending article statuses.") if errorOccurred { @@ -196,13 +197,10 @@ final class NewsBlurAccountDelegate: AccountDelegate { } } } - - switch result { - case .success(let syncStatuses): - processStatuses(syncStatuses) - case .failure(let databaseError): - completion(.failure(databaseError)) - } + + processStatuses(Array(syncStatuses)) + } catch { + completion(.failure(error)) } } } diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index 817bccb97..2ecb4a0a5 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -199,52 +199,53 @@ final class ReaderAPIAccountDelegate: AccountDelegate { } func sendArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { + os_log(.debug, log: log, "Sending article statuses...") - database.selectForProcessing { result in + Task { @MainActor in + + do { + + let syncStatuses = (try await self.database.selectForProcessing()) ?? Set() - MainActor.assumeIsolated { - @MainActor func processStatuses(_ syncStatuses: [SyncStatus]) { + let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false } let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true } let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true } let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false } - + let group = DispatchGroup() - + group.enter() self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) { group.leave() } - + group.enter() self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) { group.leave() } - + group.enter() self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) { group.leave() } - + group.enter() self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) { group.leave() } - + group.notify(queue: DispatchQueue.main) { os_log(.debug, log: self.log, "Done sending article statuses.") completion(.success(())) } } - - switch result { - case .success(let syncStatuses): - processStatuses(syncStatuses) - case .failure(let databaseError): - completion(.failure(databaseError)) - } + + processStatuses(Array(syncStatuses)) + } catch { + completion(.failure(error)) } } } diff --git a/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift b/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift index 1e5d42412..aa5579cf2 100644 --- a/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift +++ b/SyncDatabase/Sources/SyncDatabase/SyncDatabase.swift @@ -110,34 +110,6 @@ public actor SyncDatabase { } } -// MARK: - Compatibility - -// Use the below until switching to the async version of the API. - -public typealias SyncStatusesResult = Result, DatabaseError> -public typealias SyncStatusesCompletionBlock = @Sendable (SyncStatusesResult) -> Void - -public typealias SyncStatusArticleIDsResult = Result, DatabaseError> -public typealias SyncStatusArticleIDsCompletionBlock = @Sendable (SyncStatusArticleIDsResult) -> Void - -public extension SyncDatabase { - - nonisolated func selectForProcessing(limit: Int? = nil, completion: @escaping SyncStatusesCompletionBlock) { - - Task { @MainActor in - do { - if let syncStatuses = try await self.selectForProcessing(limit: limit) { - completion(.success(Array(syncStatuses))) - } else { - completion(.success([SyncStatus]())) - } - } catch { - completion(.failure(DatabaseError.suspended)) - } - } - } -} - private extension SyncDatabase { static let creationStatements = """