diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index fce8c1b42..51fb33e68 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -995,7 +995,8 @@ public enum FetchType { // MARK: - AccountMetadataDelegate extension Account: AccountMetadataDelegate { - func valueDidChange(_ accountMetadata: AccountMetadata, key: AccountMetadata.CodingKeys) { + + nonisolated func valueDidChange(_ accountMetadata: AccountMetadata, key: AccountMetadata.CodingKeys) { Task { @MainActor in metadataFile.markAsDirty() } @@ -1006,11 +1007,13 @@ extension Account: AccountMetadataDelegate { extension Account: FeedMetadataDelegate { - func valueDidChange(_ feedMetadata: FeedMetadata, key: FeedMetadata.CodingKeys) { + nonisolated func valueDidChange(_ feedMetadata: FeedMetadata, key: FeedMetadata.CodingKeys) { + + let feedID = feedMetadata.feedID Task { @MainActor in feedMetadataFile.markAsDirty() - guard let feed = existingFeed(withFeedID: feedMetadata.feedID) else { + guard let feed = existingFeed(withFeedID: feedID) else { return } feed.postFeedSettingDidChangeNotification(key) diff --git a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift index 7afeac266..1888f8ea1 100644 --- a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift @@ -57,7 +57,7 @@ final class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate { private extension CloudKitArticlesZoneDelegate { - func delete(recordKeys: [CloudKitRecordKey], pendingStarredStatusArticleIDs: Set) async { + @MainActor func delete(recordKeys: [CloudKitRecordKey], pendingStarredStatusArticleIDs: Set) async { let receivedRecordIDs = recordKeys.filter({ $0.recordType == CloudKitArticlesZone.CloudKitArticleStatus.recordType }).map({ $0.recordID }) let receivedArticleIDs = Set(receivedRecordIDs.map({ stripPrefix($0.externalID) })) diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index 419a9a05b..1a9c7c307 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -445,32 +445,59 @@ private extension FeedbinAccountDelegate { } } + private func delay(seconds: Double) async { + + await withCheckedContinuation { continuation in + self.performBlockAfter(seconds: seconds) { + continuation.resume() + } + } + } + + nonisolated private func performBlockAfter(seconds: Double, block: @escaping @Sendable @MainActor () -> ()) { + + let delayTime = DispatchTime.now() + seconds + DispatchQueue.main.asyncAfter(deadline: delayTime) { + Task { @MainActor in + block() + } + } + } + func checkImportResult(opmlImportResultID: Int, completion: @escaping @Sendable (Result) -> Void) { - DispatchQueue.main.async { + Task { @MainActor in - Timer.scheduledTimer(withTimeInterval: 15, repeats: true) { timer in + var retry = 0 + let maxRetries = 6 // a guess at a good number - Task { @MainActor in + @MainActor func checkResult() async { - os_log(.debug, log: self.log, "Checking status of OPML import...") + if retry >= maxRetries { + return + } + retry = retry + 1 - do { - let importResult = try await self.caller.retrieveOPMLImportResult(importID: opmlImportResultID) + await delay(seconds: 15) + os_log(.debug, log: self.log, "Checking status of OPML import...") - if let importResult, importResult.complete { - os_log(.debug, log: self.log, "Checking status of OPML import successfully completed.") - timer.invalidate() - completion(.success(())) - } + do { + let importResult = try await self.caller.retrieveOPMLImportResult(importID: opmlImportResultID) - } catch { - os_log(.debug, log: self.log, "Import OPML check failed.") - timer.invalidate() - completion(.failure(error)) + if let importResult, importResult.complete { + os_log(.debug, log: self.log, "Checking status of OPML import successfully completed.") + completion(.success(())) + } else { + await checkResult() } + + } catch { + os_log(.debug, log: self.log, "Import OPML check failed.") + completion(.failure(error)) } } + + await checkResult() } }