From 6cd8715eb08252a7332db55b8c9b8c657485d8ce Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Fri, 27 Oct 2023 22:13:29 -0700 Subject: [PATCH] Convert AccountDelegate.syncArticleStatus to async/await. --- Account/Sources/Account/Account.swift | 6 ++-- Account/Sources/Account/AccountDelegate.swift | 2 +- .../FeedbinAccountDelegate.swift | 26 +++++++++------- .../LocalAccountDelegate.swift | 4 +-- .../NewsBlurAccountDelegate.swift | 26 +++++++++------- .../ReaderAPIAccountDelegate.swift | 27 ++++++++-------- Account/Sources/Account/AccountManager.swift | 20 ++++++------ .../CloudKit/CloudKitAccountDelegate.swift | 27 +++++++++------- .../Feedly/FeedlyAccountDelegate.swift | 31 ++++++++++--------- Shared/Timer/ArticleStatusSyncTimer.swift | 6 ++-- 10 files changed, 92 insertions(+), 83 deletions(-) diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index 086ae5f1d..891c57c9f 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -443,8 +443,8 @@ public enum FetchType { } } - public func syncArticleStatus(completion: ((Result) -> Void)? = nil) { - delegate.syncArticleStatus(for: self, completion: completion) + public func syncArticleStatus() async throws { + try await delegate.syncArticleStatus(for: self) } public func importOPML(_ opmlFile: URL, completion: @escaping (Result) -> Void) { @@ -453,7 +453,7 @@ public enum FetchType { return } - delegate.importOPML(for: self, opmlFile: opmlFile) { result in + delegate.importOPML(for: self, opmlFile: opmlFile) { result in Task { @MainActor in switch result { case .success: diff --git a/Account/Sources/Account/AccountDelegate.swift b/Account/Sources/Account/AccountDelegate.swift index 44aad2272..403df0d80 100644 --- a/Account/Sources/Account/AccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegate.swift @@ -26,7 +26,7 @@ import Secrets func receiveRemoteNotification(for account: Account, userInfo: [AnyHashable : Any]) async func refreshAll(for account: Account) async throws - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)?) + func syncArticleStatus(for account: Account) async throws func sendArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) diff --git a/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift index b88cdfe34..b67f10729 100644 --- a/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift @@ -108,20 +108,22 @@ public enum FeedbinAccountDelegateError: String, Error { } } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { - sendArticleStatus(for: account) { result in - switch result { - case .success: - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: - completion?(.success(())) - case .failure(let error): - completion?(.failure(error)) + func syncArticleStatus(for account: Account) async throws { + try await withCheckedThrowingContinuation { continuation in + sendArticleStatus(for: account) { result in + switch result { + case .success: + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } } + case .failure(let error): + continuation.resume(throwing: error) } - case .failure(let error): - completion?(.failure(error)) } } } diff --git a/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift index 73cb92dd7..06eda029a 100644 --- a/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift @@ -72,8 +72,8 @@ final class LocalAccountDelegate: AccountDelegate, Logging { } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { - completion?(.success(())) + func syncArticleStatus(for account: Account) async throws { + return } func sendArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { diff --git a/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift index b0fa288f1..e1ea7eb7e 100644 --- a/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift @@ -131,20 +131,22 @@ final class NewsBlurAccountDelegate: AccountDelegate, Logging { } } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { - sendArticleStatus(for: account) { result in - switch result { - case .success: - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: - completion?(.success(())) - case .failure(let error): - completion?(.failure(error)) + func syncArticleStatus(for account: Account) async throws { + try await withCheckedThrowingContinuation { continuation in + sendArticleStatus(for: account) { result in + switch result { + case .success: + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } } + case .failure(let error): + continuation.resume(throwing: error) } - case .failure(let error): - completion?(.failure(error)) } } } diff --git a/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift index 5c37d36c6..2bfc7d76a 100644 --- a/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift @@ -182,25 +182,26 @@ public enum ReaderAPIAccountDelegateError: LocalizedError { } } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { + func syncArticleStatus(for account: Account) async throws { guard variant != .inoreader else { - completion?(.success(())) return } - sendArticleStatus(for: account) { result in - switch result { - case .success: - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: - completion?(.success(())) - case .failure(let error): - completion?(.failure(error)) + try await withCheckedThrowingContinuation { continuation in + sendArticleStatus(for: account) { result in + switch result { + case .success: + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } } + case .failure(let error): + continuation.resume(throwing: error) } - case .failure(let error): - completion?(.failure(error)) } } } diff --git a/Account/Sources/Account/AccountManager.swift b/Account/Sources/Account/AccountManager.swift index c195e7568..835989fb4 100644 --- a/Account/Sources/Account/AccountManager.swift +++ b/Account/Sources/Account/AccountManager.swift @@ -280,18 +280,16 @@ import RSDatabase } } - public func syncArticleStatusAll(completion: (() -> Void)? = nil) { - let group = DispatchGroup() - - for account in activeAccounts { - group.enter() - account.syncArticleStatus() { _ in - group.leave() - } - } + public func syncArticleStatusAll() async { - group.notify(queue: DispatchQueue.global(qos: .background)) { - completion?() + await withTaskGroup(of: Void.self) { group in + for account in activeAccounts { + group.addTask { + try? await account.syncArticleStatus() + } + } + + await group.waitForAll() } } diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index 889e11024..423f86e52 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -101,20 +101,23 @@ final class CloudKitAccountDelegate: AccountDelegate, Logging { } } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { - sendArticleStatus(for: account) { result in - switch result { - case .success: - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: - completion?(.success(())) - case .failure(let error): - completion?(.failure(error)) + func syncArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + sendArticleStatus(for: account) { result in + switch result { + case .success: + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } } + case .failure(let error): + continuation.resume(throwing: error) } - case .failure(let error): - completion?(.failure(error)) } } } diff --git a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift index 50485d2b2..701b3a1e2 100644 --- a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift @@ -146,22 +146,25 @@ final class FeedlyAccountDelegate: AccountDelegate, Logging { } } - func syncArticleStatus(for account: Account, completion: ((Result) -> Void)? = nil) { - sendArticleStatus(for: account) { result in - switch result { - case .success: - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: - completion?(.success(())) - case .failure(let error): - self.logger.error("Failed to refresh article status for account \(String(describing: account.type), privacy: .public): \(error.localizedDescription, privacy: .public)") - completion?(.failure(error)) + func syncArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + sendArticleStatus(for: account) { result in + switch result { + case .success: + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + self.logger.error("Failed to refresh article status for account \(String(describing: account.type), privacy: .public): \(error.localizedDescription, privacy: .public)") + continuation.resume(throwing: error) + } } + case .failure(let error): + self.logger.error("Failed to send article status for account \(String(describing: account.type), privacy: .public): \(error.localizedDescription, privacy: .public)") + continuation.resume(throwing: error) } - case .failure(let error): - self.logger.error("Failed to send article status for account \(String(describing: account.type), privacy: .public): \(error.localizedDescription, privacy: .public)") - completion?(.failure(error)) } } } diff --git a/Shared/Timer/ArticleStatusSyncTimer.swift b/Shared/Timer/ArticleStatusSyncTimer.swift index 5e0d8ffae..0bbe178ce 100644 --- a/Shared/Timer/ArticleStatusSyncTimer.swift +++ b/Shared/Timer/ArticleStatusSyncTimer.swift @@ -68,8 +68,8 @@ class ArticleStatusSyncTimer { lastTimedRefresh = Date() update() - AccountManager.shared.syncArticleStatusAll() - + Task { + await AccountManager.shared.syncArticleStatusAll() + } } - }