From c2aa49803feb31b5ebad80aca5823a01df0981a6 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 13 Mar 2024 21:50:22 -0700 Subject: [PATCH] Fix numerous build errors. --- Account/Sources/Account/Account.swift | 95 ++----------------- Account/Sources/Account/AccountManager.swift | 12 +-- Account/Sources/Account/ArticleFetcher.swift | 26 ----- .../CloudKit/CloudKitAccountDelegate.swift | 23 +++-- .../CloudKitSendStatusOperation.swift | 2 +- .../Feedbin/FeedbinAccountDelegate.swift | 23 +++-- .../ReaderAPI/ReaderAPIAccountDelegate.swift | 22 +++-- .../Account/SingleArticleFetcher.swift | 8 -- .../Feedly/FeedlyTestSupport.swift | 2 +- .../Sources/Database/FMDatabase+Extras.swift | 2 +- Shared/SmartFeeds/SmartFeed.swift | 8 -- Shared/SmartFeeds/UnreadFeed.swift | 8 -- .../SyncDatabase/SyncStatusTable.swift | 2 +- 13 files changed, 60 insertions(+), 173 deletions(-) diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index da220aa56..5b8fcf5ae 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -645,31 +645,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, fetchUnreadCounts(for: feeds, completion: completion) } - public func fetchArticles(_ fetchType: FetchType) throws -> Set
{ - switch fetchType { - case .starred(let limit): - return try fetchStarredArticles(limit: limit) - case .unread(let limit): - return try fetchUnreadArticles(limit: limit) - case .today(let limit): - return try fetchTodayArticles(limit: limit) - case .folder(let folder, let readFilter): - if readFilter { - return try fetchUnreadArticles(folder: folder) - } else { - return try fetchArticles(folder: folder) - } - case .feed(let feed): - return try fetchArticles(feed: feed) - case .articleIDs(let articleIDs): - return try fetchArticles(articleIDs: articleIDs) - case .search(let searchString): - return try fetchArticlesMatching(searchString) - case .searchWithArticleIDs(let searchString, let articleIDs): - return try fetchArticlesMatchingWithArticleIDs(searchString, articleIDs) - } - } - public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) { switch fetchType { case .starred(let limit): @@ -934,11 +909,13 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, public func debugRunSearch() { #if DEBUG + Task { let t1 = Date() - let articles = try! fetchArticlesMatching("Brent NetNewsWire") + let articles = try! await fetchArticlesMatching("Brent NetNewsWire") let t2 = Date() print(t2.timeIntervalSince(t1)) print(articles.count) + } #endif } @@ -1022,52 +999,26 @@ extension Account: FeedMetadataDelegate { private extension Account { - func fetchStarredArticles(limit: Int?) throws -> Set
{ - return try database.fetchStarredArticles(flattenedFeeds().feedIDs(), limit) - } - func fetchStarredArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) { database.fetchedStarredArticlesAsync(flattenedFeeds().feedIDs(), limit, completion) } - func fetchUnreadArticles(limit: Int?) throws -> Set
{ - return try fetchUnreadArticles(forContainer: self, limit: limit) - } - func fetchUnreadArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) { fetchUnreadArticlesAsync(forContainer: self, limit: limit, completion) } - func fetchTodayArticles(limit: Int?) throws -> Set
{ - return try database.fetchTodayArticles(flattenedFeeds().feedIDs(), limit) - } - func fetchTodayArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) { database.fetchTodayArticlesAsync(flattenedFeeds().feedIDs(), limit, completion) } - func fetchArticles(folder: Folder) throws -> Set
{ - return try fetchArticles(forContainer: folder) - } - func fetchArticlesAsync(folder: Folder, _ completion: @escaping ArticleSetResultBlock) { fetchArticlesAsync(forContainer: folder, completion) } - func fetchUnreadArticles(folder: Folder) throws -> Set
{ - return try fetchUnreadArticles(forContainer: folder, limit: nil) - } - func fetchUnreadArticlesAsync(folder: Folder, _ completion: @escaping ArticleSetResultBlock) { fetchUnreadArticlesAsync(forContainer: folder, limit: nil, completion) } - func fetchArticles(feed: Feed) throws -> Set
{ - let articles = try database.fetchArticles(feed.feedID) - validateUnreadCount(feed, articles) - return articles - } - func fetchArticlesAsync(feed: Feed, _ completion: @escaping ArticleSetResultBlock) { database.fetchArticlesAsync(feed.feedID) { [weak self] articleSetResult in switch articleSetResult { @@ -1080,14 +1031,12 @@ private extension Account { } } - func fetchArticlesMatching(_ searchString: String) throws -> Set
{ - return try database.fetchArticlesMatching(searchString, flattenedFeeds().feedIDs()) + func fetchArticlesMatching(_ searchString: String) async throws -> Set
{ + + let feedIDs = flattenedFeeds().feedIDs() + return try await database.articlesMatching(searchString: searchString, feedIDs: feedIDs) } - func fetchArticlesMatchingWithArticleIDs(_ searchString: String, _ articleIDs: Set) throws -> Set
{ - return try database.fetchArticlesMatchingWithArticleIDs(searchString, articleIDs) - } - func fetchArticlesMatchingAsync(_ searchString: String, _ completion: @escaping ArticleSetResultBlock) { database.fetchArticlesMatchingAsync(searchString, flattenedFeeds().feedIDs(), completion) } @@ -1096,27 +1045,10 @@ private extension Account { database.fetchArticlesMatchingWithArticleIDsAsync(searchString, articleIDs, completion) } - func fetchArticles(articleIDs: Set) throws -> Set
{ - return try database.fetchArticles(articleIDs: articleIDs) - } - func fetchArticlesAsync(articleIDs: Set, _ completion: @escaping ArticleSetResultBlock) { return database.fetchArticlesAsync(articleIDs: articleIDs, completion) } - func fetchUnreadArticles(feed: Feed) throws -> Set
{ - let articles = try database.fetchUnreadArticles(Set([feed.feedID]), nil) - validateUnreadCount(feed, articles) - return articles - } - - func fetchArticles(forContainer container: Container) throws -> Set
{ - let feeds = container.flattenedFeeds() - let articles = try database.fetchArticles(feeds.feedIDs()) - validateUnreadCountsAfterFetchingUnreadArticles(feeds, articles) - return articles - } - func fetchArticlesAsync(forContainer container: Container, _ completion: @escaping ArticleSetResultBlock) { let feeds = container.flattenedFeeds() database.fetchArticlesAsync(feeds.feedIDs()) { [weak self] (articleSetResult) in @@ -1130,19 +1062,6 @@ private extension Account { } } - func fetchUnreadArticles(forContainer container: Container, limit: Int?) throws -> Set
{ - let feeds = container.flattenedFeeds() - let articles = try database.fetchUnreadArticles(feeds.feedIDs(), limit) - - // We don't validate limit queries because they, by definition, won't correctly match the - // complete unread state for the given container. - if limit == nil { - validateUnreadCountsAfterFetchingUnreadArticles(feeds, articles) - } - - return articles - } - func fetchUnreadArticlesAsync(forContainer container: Container, limit: Int?, _ completion: @escaping ArticleSetResultBlock) { let feeds = container.flattenedFeeds() database.fetchUnreadArticlesAsync(feeds.feedIDs(), limit) { [weak self] (articleSetResult) in diff --git a/Account/Sources/Account/AccountManager.swift b/Account/Sources/Account/AccountManager.swift index 3a82b49cf..e4cf12d5a 100644 --- a/Account/Sources/Account/AccountManager.swift +++ b/Account/Sources/Account/AccountManager.swift @@ -344,17 +344,7 @@ public final class AccountManager: UnreadCountProvider { // These fetch articles from active accounts and return a merged Set
. - public func fetchArticles(_ fetchType: FetchType) throws -> Set
{ - precondition(Thread.isMainThread) - - var articles = Set
() - for account in activeAccounts { - articles.formUnion(try account.fetchArticles(fetchType)) - } - return articles - } - - public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) { + public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) { precondition(Thread.isMainThread) guard activeAccounts.count > 0 else { diff --git a/Account/Sources/Account/ArticleFetcher.swift b/Account/Sources/Account/ArticleFetcher.swift index 007c66e17..4a74ff5b7 100644 --- a/Account/Sources/Account/ArticleFetcher.swift +++ b/Account/Sources/Account/ArticleFetcher.swift @@ -12,18 +12,12 @@ import ArticlesDatabase public protocol ArticleFetcher { - func fetchArticles() throws -> Set
func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) - func fetchUnreadArticles() throws -> Set
func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) } extension Feed: ArticleFetcher { - public func fetchArticles() throws -> Set
{ - return try account?.fetchArticles(.feed(self)) ?? Set
() - } - public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { guard let account = account else { assertionFailure("Expected feed.account, but got nil.") @@ -33,10 +27,6 @@ extension Feed: ArticleFetcher { account.fetchArticlesAsync(.feed(self), completion) } - public func fetchUnreadArticles() throws -> Set
{ - return try fetchArticles().unreadArticles() - } - public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { guard let account = account else { assertionFailure("Expected feed.account, but got nil.") @@ -56,14 +46,6 @@ extension Feed: ArticleFetcher { extension Folder: ArticleFetcher { - public func fetchArticles() throws -> Set
{ - guard let account = account else { - assertionFailure("Expected folder.account, but got nil.") - return Set
() - } - return try account.fetchArticles(.folder(self, false)) - } - public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { guard let account = account else { assertionFailure("Expected folder.account, but got nil.") @@ -73,14 +55,6 @@ extension Folder: ArticleFetcher { account.fetchArticlesAsync(.folder(self, false), completion) } - public func fetchUnreadArticles() throws -> Set
{ - guard let account = account else { - assertionFailure("Expected folder.account, but got nil.") - return Set
() - } - return try account.fetchArticles(.folder(self, true)) - } - public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { guard let account = account else { assertionFailure("Expected folder.account, but got nil.") diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index 6f56eab55..1fc0337f0 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -64,8 +64,8 @@ final class CloudKitAccountDelegate: AccountDelegate { accountZone = CloudKitAccountZone(container: container) articlesZone = CloudKitArticlesZone(container: container) - let databaseFilePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3") - database = SyncDatabase(databaseFilePath: databaseFilePath) + let databasePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3") + database = SyncDatabase(databasePath: databasePath) } func receiveRemoteNotification(for account: Account, userInfo: [AnyHashable : Any], completion: @escaping () -> Void) { @@ -427,8 +427,10 @@ final class CloudKitAccountDelegate: AccountDelegate { accountZone.delegate = CloudKitAcountZoneDelegate(account: account, refreshProgress: refreshProgress, articlesZone: articlesZone) articlesZone.delegate = CloudKitArticlesZoneDelegate(account: account, database: database, articlesZone: articlesZone) - database.resetAllSelectedForProcessing() - + Task { + try await database.resetAllSelectedForProcessing() + } + // Check to see if this is a new account and initialize anything we need if account.externalID == nil { accountZone.findOrCreateAccount() { result in @@ -443,7 +445,6 @@ final class CloudKitAccountDelegate: AccountDelegate { accountZone.subscribeToZoneChanges() articlesZone.subscribeToZoneChanges() } - } func accountWillBeDeleted(_ account: Account) { @@ -458,16 +459,24 @@ final class CloudKitAccountDelegate: AccountDelegate { // MARK: Suspend and Resume (for iOS) func suspendNetwork() { + refresher.suspend() } func suspendDatabase() { - database.suspend() + + Task { + await database.suspend() + } } func resume() { + refresher.resume() - database.resume() + + Task { + await database.resume() + } } } diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index dc997a23c..f2f5b70b1 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -121,7 +121,7 @@ private extension CloudKitSendStatusOperation { return CloudKitArticleStatusUpdate(articleID: key, statuses: value, article: articlesDict[key]) } - func done(_ stop: Bool) { + @Sendable func done(_ stop: Bool) { // Don't clear the last one since we might have had additional ticks added if self.showProgress && self.refreshProgress?.numberRemaining ?? 0 > 1 { self.refreshProgress?.completeTask() diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index 3ec61078d..46564f8b9 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -604,13 +604,19 @@ final class FeedbinAccountDelegate: AccountDelegate { /// Suspend the SQLLite databases func suspendDatabase() { - database.suspend() + + Task { + await database.suspend() + } } /// Make sure no SQLite databases are open and we are ready to issue network requests. func resume() { + caller.resume() - database.resume() + Task { + await database.resume() + } } } @@ -957,13 +963,17 @@ private extension FeedbinAccountDelegate { apiCall(articleIDGroup) { result in switch result { case .success: - self.database.deleteSelectedForProcessing(articleIDGroup.map { String($0) } ) - group.leave() + Task { + try? await self.database.deleteSelectedForProcessing(articleIDGroup.map { String($0) } ) + group.leave() + } case .failure(let error): errorOccurred = true os_log(.error, log: self.log, "Article status sync call failed: %@.", error.localizedDescription) - self.database.resetSelectedForProcessing(articleIDGroup.map { String($0) } ) - group.leave() + Task { + try? await self.database.resetSelectedForProcessing(articleIDGroup.map { String($0) } ) + group.leave() + } } } @@ -976,7 +986,6 @@ private extension FeedbinAccountDelegate { completion(.success(())) } } - } func renameFolderRelationship(for account: Account, fromName: String, toName: String) { diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index b14c52d31..0fa88fe85 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -661,12 +661,18 @@ final class ReaderAPIAccountDelegate: AccountDelegate { /// Suspend the SQLLite databases func suspendDatabase() { - database.suspend() + + Task { + await database.suspend() + } } /// Make sure no SQLite databases are open and we are ready to issue network requests. func resume() { - database.resume() + + Task { + await database.resume() + } } } @@ -885,12 +891,16 @@ private extension ReaderAPIAccountDelegate { apiCall(articleIDGroup) { result in switch result { case .success: - self.database.deleteSelectedForProcessing(articleIDGroup.map { $0 } ) - group.leave() + Task { + try? await self.database.deleteSelectedForProcessing(articleIDGroup.map { $0 } ) + group.leave() + } case .failure(let error): os_log(.error, log: self.log, "Article status sync call failed: %@.", error.localizedDescription) - self.database.resetSelectedForProcessing(articleIDGroup.map { $0 } ) - group.leave() + Task { + try? await self.database.resetSelectedForProcessing(articleIDGroup.map { $0 } ) + group.leave() + } } } diff --git a/Account/Sources/Account/SingleArticleFetcher.swift b/Account/Sources/Account/SingleArticleFetcher.swift index f558fd5fa..8718c2bb4 100644 --- a/Account/Sources/Account/SingleArticleFetcher.swift +++ b/Account/Sources/Account/SingleArticleFetcher.swift @@ -20,18 +20,10 @@ public struct SingleArticleFetcher: ArticleFetcher { self.articleID = articleID } - public func fetchArticles() throws -> Set
{ - return try account.fetchArticles(.articleIDs(Set([articleID]))) - } - public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { return account.fetchArticlesAsync(.articleIDs(Set([articleID])), completion) } - public func fetchUnreadArticles() throws -> Set
{ - return try account.fetchArticles(.articleIDs(Set([articleID]))) - } - public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { return account.fetchArticlesAsync(.articleIDs(Set([articleID])), completion) } diff --git a/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift b/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift index 456c4c1c2..538889dbf 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift @@ -61,7 +61,7 @@ class FeedlyTestSupport { init() { let dataFolder = try! FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) path = dataFolder.appendingPathComponent("\(UUID().uuidString)-Sync.sqlite3").path - database = SyncDatabase(databaseFilePath: path) + database = SyncDatabase(databasePath: path) } deinit { diff --git a/Database/Sources/Database/FMDatabase+Extras.swift b/Database/Sources/Database/FMDatabase+Extras.swift index 0869c8e42..1974421e8 100644 --- a/Database/Sources/Database/FMDatabase+Extras.swift +++ b/Database/Sources/Database/FMDatabase+Extras.swift @@ -21,7 +21,7 @@ public extension FMDatabase { return database } - func executeUpdateInTransaction(_ sql : String, withArgumentsIn parameters: [Any]?) { + func executeUpdateInTransaction(_ sql : String, withArgumentsIn parameters: [Any]? = nil) { beginTransaction() executeUpdate(sql, withArgumentsIn: parameters) diff --git a/Shared/SmartFeeds/SmartFeed.swift b/Shared/SmartFeeds/SmartFeed.swift index 88e1af3f5..69e1f1787 100644 --- a/Shared/SmartFeeds/SmartFeed.swift +++ b/Shared/SmartFeeds/SmartFeed.swift @@ -84,18 +84,10 @@ final class SmartFeed: PseudoFeed { extension SmartFeed: ArticleFetcher { - func fetchArticles() throws -> Set
{ - return try delegate.fetchArticles() - } - func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { delegate.fetchArticlesAsync(completion) } - func fetchUnreadArticles() throws -> Set
{ - return try delegate.fetchUnreadArticles() - } - func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { delegate.fetchUnreadArticlesAsync(completion) } diff --git a/Shared/SmartFeeds/UnreadFeed.swift b/Shared/SmartFeeds/UnreadFeed.swift index 8635f7fb2..bc993785c 100644 --- a/Shared/SmartFeeds/UnreadFeed.swift +++ b/Shared/SmartFeeds/UnreadFeed.swift @@ -66,18 +66,10 @@ final class UnreadFeed: PseudoFeed { extension UnreadFeed: ArticleFetcher { - func fetchArticles() throws -> Set
{ - return try fetchUnreadArticles() - } - func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { fetchUnreadArticlesAsync(completion) } - func fetchUnreadArticles() throws -> Set
{ - return try AccountManager.shared.fetchArticles(fetchType) - } - func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) { AccountManager.shared.fetchArticlesAsync(fetchType, completion) } diff --git a/SyncDatabase/Sources/SyncDatabase/SyncStatusTable.swift b/SyncDatabase/Sources/SyncDatabase/SyncStatusTable.swift index d96e5c99c..fb8067d45 100644 --- a/SyncDatabase/Sources/SyncDatabase/SyncStatusTable.swift +++ b/SyncDatabase/Sources/SyncDatabase/SyncStatusTable.swift @@ -60,7 +60,7 @@ struct SyncStatusTable { func resetAllSelectedForProcessing(database: FMDatabase) { let updateSQL = "update syncStatus set selected = false" - database.executeUpdateInTransaction(updateSQL, withArgumentsIn: nil) + database.executeUpdateInTransaction(updateSQL) } func resetSelectedForProcessing(_ articleIDs: [String], database: FMDatabase) {