From 9bbecc99c7716c2a336031003be2ee5ecbc8239c Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 12 Jul 2023 20:33:49 -0700 Subject: [PATCH] Continue adopting async/await. Also: rename some Ids to IDs. --- Account/Sources/Account/Account.swift | 26 +++++- .../Account/Feedly/FeedlyAPICaller.swift | 6 +- .../Feedly/FeedlyAccountDelegate.swift | 2 +- .../Feedly/Models/FeedlyResourceId.swift | 14 +-- .../Feedly/Models/FeedlyStreamIds.swift | 4 +- .../FeedlyAddNewFeedOperation.swift | 6 +- .../FeedlyGetStreamIdsOperation.swift | 12 +-- .../FeedlyGetUpdatedArticleIdsOperation.swift | 14 +-- ...edlyIngestStarredArticleIdsOperation.swift | 10 +- ...eedlyIngestStreamArticleIdsOperation.swift | 12 +-- ...eedlyIngestUnreadArticleIdsOperation.swift | 91 +++++++------------ .../FeedlyRequestStreamsOperation.swift | 2 +- .../Operations/FeedlySyncAllOperation.swift | 4 +- .../FeedlySyncStreamContentsOperation.swift | 2 +- .../Services/FeedlyGetStreamIdsService.swift | 6 +- .../NewsBlurAccountDelegate+Internal.swift | 2 +- ...eedlyGetStreamContentsOperationTests.swift | 6 +- .../FeedlyGetStreamIdsOperationTests.swift | 8 +- ...aniseParsedItemsByFeedOperationTests.swift | 6 +- ...edlySyncStreamContentsOperationTests.swift | 6 +- .../Feedly/TestGetPagedStreamIdsService.swift | 12 +-- .../Feedly/TestGetStreamIdsService.swift | 6 +- 22 files changed, 127 insertions(+), 130 deletions(-) diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index 2db078b8b..0a54b1724 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -898,6 +898,8 @@ public enum FetchType { noteStatusesForArticleIDsDidChange(articleIDs: articleIDs, statusKey: statusKey, flag: flag) } + /// Mark articleIDs as read. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Returns a set of new article statuses. func markArticleIDsAsRead(_ articleIDs: Set) async throws { try await markArticleIDs(articleIDs, statusKey: .read, flag: true) } @@ -908,19 +910,37 @@ public enum FetchType { mark(articleIDs: articleIDs, statusKey: .read, flag: true, completion: completion) } - /// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Returns a set of new article statuses. + func markArticleIDsAsUnread(_ articleIDs: Set) async throws { + try await markArticleIDs(articleIDs, statusKey: .read, flag: false) + } + + /// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. /// Returns a set of new article statuses. func markAsUnread(_ articleIDs: Set, completion: DatabaseCompletionBlock? = nil) { mark(articleIDs: articleIDs, statusKey: .read, flag: false, completion: completion) } - /// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Returns a set of new article statuses. + func markArticleIDsAsStarred(_ articleIDs: Set) async throws { + try await markArticleIDs(articleIDs, statusKey: .starred, flag: true) + } + + /// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. /// Returns a set of new article statuses. func markAsStarred(_ articleIDs: Set, completion: DatabaseCompletionBlock? = nil) { mark(articleIDs: articleIDs, statusKey: .starred, flag: true, completion: completion) } - /// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. + /// Returns a set of new article statuses. + func markArticleIDsAsUnstarred(_ articleIDs: Set) async throws { + try await markArticleIDs(articleIDs, statusKey: .starred, flag: false) + } + + /// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification. /// Returns a set of new article statuses. func markAsUnstarred(_ articleIDs: Set, completion: DatabaseCompletionBlock? = nil) { mark(articleIDs: articleIDs, statusKey: .starred, flag: false, completion: completion) diff --git a/Account/Sources/Account/Feedly/FeedlyAPICaller.swift b/Account/Sources/Account/Feedly/FeedlyAPICaller.swift index e84b801bd..3b676c360 100644 --- a/Account/Sources/Account/Feedly/FeedlyAPICaller.swift +++ b/Account/Sources/Account/Feedly/FeedlyAPICaller.swift @@ -671,9 +671,9 @@ extension FeedlyAPICaller: FeedlyGetStreamContentsService { } } -extension FeedlyAPICaller: FeedlyGetStreamIdsService { +extension FeedlyAPICaller: FeedlyGetStreamIDsService { - func getStreamIds(for resource: FeedlyResourceId, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { + func streamIDs(for resource: FeedlyResourceId, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { guard !isSuspended else { return DispatchQueue.main.async { completion(.failure(TransportError.suspended)) @@ -724,7 +724,7 @@ extension FeedlyAPICaller: FeedlyGetStreamIdsService { request.addValue("application/json", forHTTPHeaderField: "Accept-Type") request.addValue("OAuth \(accessToken)", forHTTPHeaderField: HTTPRequestHeader.authorization) - send(request: request, resultType: FeedlyStreamIds.self, dateDecoding: .millisecondsSince1970, keyDecoding: .convertFromSnakeCase) { result in + send(request: request, resultType: FeedlyStreamIDs.self, dateDecoding: .millisecondsSince1970, keyDecoding: .convertFromSnakeCase) { result in switch result { case .success(let (_, collections)): if let response = collections { diff --git a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift index 0fc358a5a..0c7c6a673 100644 --- a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift @@ -186,7 +186,7 @@ final class FeedlyAccountDelegate: AccountDelegate, Logging { let group = DispatchGroup() - let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: caller, database: database, newerThan: nil) + let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: credentials.username, service: caller, database: database, newerThan: nil) group.enter() ingestUnread.completionBlock = { _ in diff --git a/Account/Sources/Account/Feedly/Models/FeedlyResourceId.swift b/Account/Sources/Account/Feedly/Models/FeedlyResourceId.swift index 9e20b7a93..239cca1e0 100644 --- a/Account/Sources/Account/Feedly/Models/FeedlyResourceId.swift +++ b/Account/Sources/Account/Feedly/Models/FeedlyResourceId.swift @@ -44,29 +44,29 @@ extension FeedlyFeedResourceId { } } -struct FeedlyCategoryResourceId: FeedlyResourceId { +struct FeedlyCategoryResourceID: FeedlyResourceId { let id: String enum Global { - static func uncategorized(for userId: String) -> FeedlyCategoryResourceId { + static func uncategorized(for userId: String) -> FeedlyCategoryResourceID { // https://developer.feedly.com/cloud/#global-resource-ids let id = "user/\(userId)/category/global.uncategorized" - return FeedlyCategoryResourceId(id: id) + return FeedlyCategoryResourceID(id: id) } /// All articles from all the feeds the user subscribes to. - static func all(for userId: String) -> FeedlyCategoryResourceId { + static func all(for userId: String) -> FeedlyCategoryResourceID { // https://developer.feedly.com/cloud/#global-resource-ids let id = "user/\(userId)/category/global.all" - return FeedlyCategoryResourceId(id: id) + return FeedlyCategoryResourceID(id: id) } /// All articles from all the feeds the user loves most. - static func mustRead(for userId: String) -> FeedlyCategoryResourceId { + static func mustRead(for userId: String) -> FeedlyCategoryResourceID { // https://developer.feedly.com/cloud/#global-resource-ids let id = "user/\(userId)/category/global.must" - return FeedlyCategoryResourceId(id: id) + return FeedlyCategoryResourceID(id: id) } } } diff --git a/Account/Sources/Account/Feedly/Models/FeedlyStreamIds.swift b/Account/Sources/Account/Feedly/Models/FeedlyStreamIds.swift index a31e1005c..e014fd507 100644 --- a/Account/Sources/Account/Feedly/Models/FeedlyStreamIds.swift +++ b/Account/Sources/Account/Feedly/Models/FeedlyStreamIds.swift @@ -1,5 +1,5 @@ // -// FeedlyStreamIds.swift +// FeedlyStreamIDs.swift // Account // // Created by Kiel Gillard on 18/10/19. @@ -8,7 +8,7 @@ import Foundation -struct FeedlyStreamIds: Decodable { +struct FeedlyStreamIDs: Decodable { let continuation: String? let ids: [String] diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift index 08133151c..4ad145fcb 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift @@ -23,12 +23,12 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl private let database: SyncDatabase private let feedName: String? private let addToCollectionService: FeedlyAddFeedToCollectionService - private let syncUnreadIdsService: FeedlyGetStreamIdsService + private let syncUnreadIdsService: FeedlyGetStreamIDsService private let getStreamContentsService: FeedlyGetStreamContentsService private var feedResourceId: FeedlyFeedResourceId? var addCompletionHandler: ((Result) -> ())? - init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIdsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress) throws { + init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIDsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress) throws { let validator = FeedlyFeedContainerValidator(container: container) @@ -94,7 +94,7 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl createFeeds.downloadProgress = downloadProgress operationQueue.add(createFeeds) - let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: syncUnreadIdsService, database: database, newerThan: nil) + let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: credentials.username, service: syncUnreadIdsService, database: database, newerThan: nil) syncUnread.addDependency(createFeeds) syncUnread.downloadProgress = downloadProgress syncUnread.delegate = self diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamIdsOperation.swift index 04aac1737..2812460e8 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamIdsOperation.swift @@ -1,5 +1,5 @@ // -// FeedlyGetStreamIdsOperation.swift +// FeedlyGetStreamIDsOperation.swift // Account // // Created by Kiel Gillard on 18/10/19. @@ -10,7 +10,7 @@ import Foundation import RSCore protocol FeedlyGetStreamIdsOperationDelegate: AnyObject { - func feedlyGetStreamIdsOperation(_ operation: FeedlyGetStreamIdsOperation, didGet streamIds: FeedlyStreamIds) + func feedlyGetStreamIdsOperation(_ operation: FeedlyGetStreamIdsOperation, didGet streamIds: FeedlyStreamIDs) } /// Single responsibility is to get the stream ids from Feedly. @@ -24,16 +24,16 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP return Set(ids) } - private(set) var streamIds: FeedlyStreamIds? + private(set) var streamIds: FeedlyStreamIDs? let account: Account - let service: FeedlyGetStreamIdsService + let service: FeedlyGetStreamIDsService let continuation: String? let resource: FeedlyResourceId let unreadOnly: Bool? let newerThan: Date? - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, continuation: String? = nil, newerThan: Date? = nil, unreadOnly: Bool?) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, continuation: String? = nil, newerThan: Date? = nil, unreadOnly: Bool?) { self.account = account self.resource = resource self.service = service @@ -45,7 +45,7 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP weak var streamIdsDelegate: FeedlyGetStreamIdsOperationDelegate? override func run() { - service.getStreamIds(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in + service.streamIDs(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in switch result { case .success(let stream): self.streamIds = stream diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyGetUpdatedArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyGetUpdatedArticleIdsOperation.swift index dd7197714..f826db7b3 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyGetUpdatedArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyGetUpdatedArticleIdsOperation.swift @@ -18,18 +18,18 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie private let account: Account private let resource: FeedlyResourceId - private let service: FeedlyGetStreamIdsService + private let service: FeedlyGetStreamIDsService private let newerThan: Date? - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, newerThan: Date?) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, newerThan: Date?) { self.account = account self.resource = resource self.service = service self.newerThan = newerThan } - convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, newerThan: Date?) { - let all = FeedlyCategoryResourceId.Global.all(for: userId) + convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService, newerThan: Date?) { + let all = FeedlyCategoryResourceID.Global.all(for: userId) self.init(account: account, resource: all, service: service, newerThan: newerThan) } @@ -50,10 +50,10 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie return } - service.getStreamIds(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIds(_:)) + service.streamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIds(_:)) } - private func didGetStreamIds(_ result: Result) { + private func didGetStreamIds(_ result: Result) { guard !isCanceled else { didFinish() return @@ -72,7 +72,7 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie getStreamIds(continuation) case .failure(let error): - self.logger.error("Error getting FeedlyStreamIds: \(error.localizedDescription, privacy: .public).") + self.logger.error("Error getting FeedlyStreamIDs: \(error.localizedDescription, privacy: .public).") didFinish(with: error) } } diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift index c77de269e..df3d37664 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStarredArticleIdsOperation.swift @@ -21,16 +21,16 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation, Logging { private let account: Account private let resource: FeedlyResourceId - private let service: FeedlyGetStreamIdsService + private let service: FeedlyGetStreamIDsService private let database: SyncDatabase private var remoteEntryIds = Set() - convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) { + convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) { let resource = FeedlyTagResourceId.Global.saved(for: userId) self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan) } - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) { self.account = account self.resource = resource self.service = service @@ -42,10 +42,10 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation, Logging { } private func getStreamIds(_ continuation: String?) { - service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:)) + service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:)) } - private func didGetStreamIds(_ result: Result) { + private func didGetStreamIds(_ result: Result) { guard !isCanceled else { didFinish() return diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStreamArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStreamArticleIdsOperation.swift index 19fa27c4e..cc052806e 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestStreamArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestStreamArticleIdsOperation.swift @@ -19,16 +19,16 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation, Logging { private let account: Account private let resource: FeedlyResourceId - private let service: FeedlyGetStreamIdsService + private let service: FeedlyGetStreamIDsService - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService) { self.account = account self.resource = resource self.service = service } - convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService) { - let all = FeedlyCategoryResourceId.Global.all(for: userId) + convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService) { + let all = FeedlyCategoryResourceID.Global.all(for: userId) self.init(account: account, resource: all, service: service) } @@ -37,10 +37,10 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation, Logging { } private func getStreamIds(_ continuation: String?) { - service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:)) + service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:)) } - private func didGetStreamIds(_ result: Result) { + private func didGetStreamIds(_ result: Result) { guard !isCanceled else { didFinish() return diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift index c631e0d3d..e267d1b17 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift @@ -4,7 +4,7 @@ // // Created by Kiel Gillard on 18/10/19. // Copyright © 2019 Ranchero Software, LLC. All rights reserved. -// +///Users/brent/Projects/NetNewsWire/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIDsOperation.swift import Foundation import RSCore @@ -22,16 +22,16 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging { private let account: Account private let resource: FeedlyResourceId - private let service: FeedlyGetStreamIdsService + private let service: FeedlyGetStreamIDsService private let database: SyncDatabase - private var remoteEntryIds = Set() + private var remoteEntryIDs = Set() - convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) { - let resource = FeedlyCategoryResourceId.Global.all(for: userId) + convenience init(account: Account, userID: String, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) { + let resource = FeedlyCategoryResourceID.Global.all(for: userID) self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan) } - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) { self.account = account self.resource = resource self.service = service @@ -39,30 +39,30 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging { } override func run() { - getStreamIds(nil) + getStreamIDs(nil) } - private func getStreamIds(_ continuation: String?) { - service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true, completion: didGetStreamIds(_:)) + private func getStreamIDs(_ continuation: String?) { + service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true, completion: didGetStreamIDs(_:)) } - private func didGetStreamIds(_ result: Result) { + private func didGetStreamIDs(_ result: Result) { guard !isCanceled else { didFinish() return } switch result { - case .success(let streamIds): + case .success(let streamIDs): - remoteEntryIds.formUnion(streamIds.ids) + remoteEntryIDs.formUnion(streamIDs.ids) - guard let continuation = streamIds.continuation else { - removeEntryIdsWithPendingStatus() + guard let continuation = streamIDs.continuation else { + removeEntryIDsWithPendingStatus() return } - getStreamIds(continuation) + getStreamIDs(continuation) case .failure(let error): didFinish(with: error) @@ -70,7 +70,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging { } /// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled. - private func removeEntryIdsWithPendingStatus() { + private func removeEntryIDsWithPendingStatus() { guard !isCanceled else { didFinish() return @@ -78,8 +78,8 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging { database.selectPendingReadStatusArticleIDs { result in switch result { - case .success(let pendingArticleIds): - self.remoteEntryIds.subtract(pendingArticleIds) + case .success(let pendingArticleIDs): + self.remoteEntryIDs.subtract(pendingArticleIDs) self.updateUnreadStatuses() @@ -106,51 +106,28 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging { } if let localUnreadArticleIDs { - processUnreadArticleIDs(localUnreadArticleIDs) + await processUnreadArticleIDs(localUnreadArticleIDs) } } } - private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set) { - guard !isCanceled else { - didFinish() - return - } + @MainActor private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set) async { + guard !isCanceled else { + didFinish() + return + } - let remoteUnreadArticleIDs = remoteEntryIds - let group = DispatchGroup() - - final class ReadStatusResults { - var markAsUnreadError: Error? - var markAsReadError: Error? - } - - let results = ReadStatusResults() - - group.enter() - account.markAsUnread(remoteUnreadArticleIDs) { databaseError in - if let databaseError = databaseError { - results.markAsUnreadError = databaseError - } - group.leave() - } + let remoteUnreadArticleIDs = remoteEntryIDs - let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs) - group.enter() - account.markAsRead(articleIDsToMarkRead) { databaseError in - if let databaseError = databaseError { - results.markAsReadError = databaseError - } - group.leave() - } + do { + try await account.markArticleIDsAsUnread(remoteUnreadArticleIDs) - group.notify(queue: .main) { - let markingError = results.markAsReadError ?? results.markAsUnreadError - guard let error = markingError else { - self.didFinish() - return - } - self.didFinish(with: error) - } + let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs) + try await account.markArticleIDsAsRead(articleIDsToMarkRead) + + didFinish() + } catch let error { + didFinish(with: error) + } } } diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyRequestStreamsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyRequestStreamsOperation.swift index ae4eda8d2..e0aa2ca9e 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyRequestStreamsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyRequestStreamsOperation.swift @@ -43,7 +43,7 @@ final class FeedlyRequestStreamsOperation: FeedlyOperation, Logging { // TODO: Prioritise the must read collection/category before others so the most important content for the user loads first. for collection in collectionsProvider.collections { - let resource = FeedlyCategoryResourceId(id: collection.id) + let resource = FeedlyCategoryResourceID(id: collection.id) let operation = FeedlyGetStreamContentsOperation(account: account, resource: resource, service: service, diff --git a/Account/Sources/Account/Feedly/Operations/FeedlySyncAllOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlySyncAllOperation.swift index 79b8efaed..bc2aff12b 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlySyncAllOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlySyncAllOperation.swift @@ -32,7 +32,7 @@ final class FeedlySyncAllOperation: FeedlyOperation, Logging { /// /// Download articles for statuses at the union of those statuses without its corresponding article and those included in 3 (changed since last successful sync). /// - init(account: Account, feedlyUserId: String, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIdsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIdsService, getStreamIdsService: FeedlyGetStreamIdsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress) { + init(account: Account, feedlyUserId: String, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIDsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIDsService, getStreamIdsService: FeedlyGetStreamIDsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress) { self.syncUUID = UUID() self.operationQueue.suspend() @@ -72,7 +72,7 @@ final class FeedlySyncAllOperation: FeedlyOperation, Logging { self.operationQueue.add(getAllArticleIds) // Get each page of unread article ids in the global.all stream for the last 31 days (nil = Feedly API default). - let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: feedlyUserId, service: getUnreadService, database: database, newerThan: nil) + let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: feedlyUserId, service: getUnreadService, database: database, newerThan: nil) getUnread.delegate = self getUnread.addDependency(getAllArticleIds) getUnread.downloadProgress = downloadProgress diff --git a/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift index 1aff8a125..75f0b7bb2 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift @@ -39,7 +39,7 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD } convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamContentsService, newerThan: Date?) { - let all = FeedlyCategoryResourceId.Global.all(for: credentials.username) + let all = FeedlyCategoryResourceID.Global.all(for: credentials.username) self.init(account: account, resource: all, service: service, isPagingEnabled: true, newerThan: newerThan) } diff --git a/Account/Sources/Account/Feedly/Services/FeedlyGetStreamIdsService.swift b/Account/Sources/Account/Feedly/Services/FeedlyGetStreamIdsService.swift index 3d5863e0d..ae9f55493 100644 --- a/Account/Sources/Account/Feedly/Services/FeedlyGetStreamIdsService.swift +++ b/Account/Sources/Account/Feedly/Services/FeedlyGetStreamIdsService.swift @@ -1,5 +1,5 @@ // -// FeedlyGetStreamIdsService.swift +// FeedlyGetStreamIDsService.swift // Account // // Created by Kiel Gillard on 21/10/19. @@ -8,6 +8,6 @@ import Foundation -protocol FeedlyGetStreamIdsService: AnyObject { - func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) +protocol FeedlyGetStreamIDsService: AnyObject { + func streamIDs(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) } diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift index 4d6a6173c..d50685c45 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift +++ b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift @@ -334,7 +334,7 @@ extension NewsBlurAccountDelegate { // Mark articles as unread let deltaUnreadArticleIDs = updatableNewsBlurUnreadStoryHashes.subtracting(currentUnreadArticleIDs) - account.markAsUnread(deltaUnreadArticleIDs) + try await account.markArticleIDsAsUnread(deltaUnreadArticleIDs) // Mark articles as read let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(updatableNewsBlurUnreadStoryHashes) diff --git a/Account/Tests/AccountTests/Feedly/FeedlyGetStreamContentsOperationTests.swift b/Account/Tests/AccountTests/Feedly/FeedlyGetStreamContentsOperationTests.swift index 992ecd4c0..28d8d74fd 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyGetStreamContentsOperationTests.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyGetStreamContentsOperationTests.swift @@ -29,7 +29,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase { func testGetStreamContentsFailure() { let service = TestGetStreamContentsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let getStreamContents = FeedlyGetStreamContentsOperation(account: account, resource: resource, service: service, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log) @@ -49,7 +49,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase { func testValuesPassingForGetStreamContents() { let service = TestGetStreamContentsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let continuation: String? = "abcdefg" let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 86) @@ -97,7 +97,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase { let jsonName = "JSON/feedly_macintosh_initial" transport.testFiles["/v3/streams/contents"] = "\(jsonName).json" - let resource = FeedlyCategoryResourceId(id: "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815") + let resource = FeedlyCategoryResourceID(id: "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815") let getStreamContents = FeedlyGetStreamContentsOperation(account: account, resource: resource, service: caller, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log) let completionExpectation = expectation(description: "Did Finish") diff --git a/Account/Tests/AccountTests/Feedly/FeedlyGetStreamIdsOperationTests.swift b/Account/Tests/AccountTests/Feedly/FeedlyGetStreamIdsOperationTests.swift index c4357507b..d19280bad 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyGetStreamIdsOperationTests.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyGetStreamIdsOperationTests.swift @@ -29,7 +29,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase { func testGetStreamIdsFailure() { let service = TestGetStreamIdsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: service, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log) @@ -49,7 +49,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase { func testValuesPassingForGetStreamIds() { let service = TestGetStreamIdsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let continuation: String? = "gfdsa" let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 1000) @@ -57,7 +57,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase { let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: service, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly, log: support.log) - let mockStreamIds = FeedlyStreamIds(continuation: "1234", ids: ["item/1", "item/2", "item/3"]) + let mockStreamIds = FeedlyStreamIDs(continuation: "1234", ids: ["item/1", "item/2", "item/3"]) service.mockResult = .success(mockStreamIds) service.getStreamIdsExpectation = expectation(description: "Did Call Service") service.parameterTester = { serviceResource, serviceContinuation, serviceNewerThan, serviceUnreadOnly in @@ -92,7 +92,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase { let jsonName = "JSON/feedly_unreads_1000" transport.testFiles["/v3/streams/ids"] = "\(jsonName).json" - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: caller, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log) let completionExpectation = expectation(description: "Did Finish") diff --git a/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift b/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift index 654e9a3b0..0e299c67c 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift @@ -36,7 +36,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase { func testNoEntries() { let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 0, numberOfItemsInFeeds: 0) - let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789") + let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789") let parsedEntries = Set(entries.values.flatMap { $0 }) let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries) @@ -57,7 +57,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase { func testGroupsOneEntryByFeedId() { let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 1, numberOfItemsInFeeds: 1) - let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789") + let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789") let parsedEntries = Set(entries.values.flatMap { $0 }) let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries) @@ -78,7 +78,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase { func testGroupsManyEntriesByFeedId() { let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 100, numberOfItemsInFeeds: 100) - let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789") + let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789") let parsedEntries = Set(entries.values.flatMap { $0 }) let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries) diff --git a/Account/Tests/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift b/Account/Tests/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift index 11819e05f..c90e9cc3c 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift @@ -29,7 +29,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { func testIngestsOnePageSuccess() throws { let service = TestGetStreamContentsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0) let items = service.makeMockFeedlyEntryItem() service.mockResult = .success(FeedlyStream(id: resource.id, updated: nil, continuation: nil, items: items)) @@ -63,7 +63,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { func testIngestsOnePageFailure() { let service = TestGetStreamContentsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0) service.mockResult = .failure(URLError(.timedOut)) @@ -93,7 +93,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { func testIngestsManyPagesSuccess() throws { let service = TestGetPagedStreamContentsService() - let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678") + let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678") let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0) let continuations = (1...10).map { "\($0)" } diff --git a/Account/Tests/AccountTests/Feedly/TestGetPagedStreamIdsService.swift b/Account/Tests/AccountTests/Feedly/TestGetPagedStreamIdsService.swift index da09e094b..ee00abfcf 100644 --- a/Account/Tests/AccountTests/Feedly/TestGetPagedStreamIdsService.swift +++ b/Account/Tests/AccountTests/Feedly/TestGetPagedStreamIdsService.swift @@ -9,14 +9,14 @@ import XCTest @testable import Account -final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService { +final class TestGetPagedStreamIdsService: FeedlyGetStreamIDsService { var parameterTester: ((FeedlyResourceId, String?, Date?, Bool?) -> ())? var getStreamIdsExpectation: XCTestExpectation? - var pages = [String: FeedlyStreamIds]() + var pages = [String: FeedlyStreamIDs]() func addAtLeastOnePage(for resource: FeedlyResourceId, continuations: [String], numberOfEntriesPerPage count: Int) { - pages = [String: FeedlyStreamIds](minimumCapacity: continuations.count + 1) + pages = [String: FeedlyStreamIDs](minimumCapacity: continuations.count + 1) // A continuation is an identifier for the next page. // The first page has a nil identifier. @@ -31,9 +31,9 @@ final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService { } } - private func makeStreamIds(for resource: FeedlyResourceId, continuation: String?, between range: Range) -> FeedlyStreamIds { + private func makeStreamIds(for resource: FeedlyResourceId, continuation: String?, between range: Range) -> FeedlyStreamIDs { let entryIds = range.map { _ in UUID().uuidString } - let stream = FeedlyStreamIds(continuation: continuation, ids: entryIds) + let stream = FeedlyStreamIDs(continuation: continuation, ids: entryIds) return stream } @@ -41,7 +41,7 @@ final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService { return "\(stream.id)@\(continuation ?? "")" } - func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { + func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { let key = TestGetPagedStreamIdsService.getPagingKey(for: resource, continuation: continuation) guard let page = pages[key] else { XCTFail("Missing page for \(resource.id) and continuation \(String(describing: continuation)). Test may time out because the completion will not be called.") diff --git a/Account/Tests/AccountTests/Feedly/TestGetStreamIdsService.swift b/Account/Tests/AccountTests/Feedly/TestGetStreamIdsService.swift index 5ae0de1c4..e4733184c 100644 --- a/Account/Tests/AccountTests/Feedly/TestGetStreamIdsService.swift +++ b/Account/Tests/AccountTests/Feedly/TestGetStreamIdsService.swift @@ -9,13 +9,13 @@ import XCTest @testable import Account -final class TestGetStreamIdsService: FeedlyGetStreamIdsService { +final class TestGetStreamIdsService: FeedlyGetStreamIDsService { - var mockResult: Result? + var mockResult: Result? var parameterTester: ((FeedlyResourceId, String?, Date?, Bool?) -> ())? var getStreamIdsExpectation: XCTestExpectation? - func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { + func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result) -> ()) { guard let result = mockResult else { XCTFail("Missing mock result. Test may time out because the completion will not be called.") return