From c0b92dfa78534bec67cab7d9737825527603d37c Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 2 Oct 2023 21:01:03 -0700 Subject: [PATCH] Continue converting ArticlesDatabase to async/await. --- Account/Sources/Account/Account.swift | 35 ++++++++++------ .../ArticlesDatabase/ArticlesDatabase.swift | 8 ++-- .../ArticlesDatabase/ArticlesTable.swift | 41 +++++++++---------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index f67ff4a8a..8d137cb5c 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -340,7 +340,7 @@ public enum FetchType { self.metadata.performedApril2020RetentionPolicyChange = true } - self.database.cleanupDatabaseAtStartup(subscribedToFeedIDs: self.flattenedFeeds().feedIDs()) + self.database.cleanupDatabaseAtStartup(subscribedToFeedIDs: self.flattenedFeedIDs()) self.fetchAllUnreadCounts() } @@ -754,15 +754,22 @@ public enum FetchType { } public func fetchUnreadCountForToday(_ completion: @escaping SingleUnreadCountCompletionBlock) { - database.fetchUnreadCountForToday(for: flattenedFeeds().feedIDs(), completion: completion) + Task { @MainActor in + do { + let unreadCount = try await database.unreadCountForTodayForFeedIDs(flattenedFeedIDs()) + completion(.success(unreadCount)) + } catch { + completion(.failure(error as! DatabaseError)) + } + } } public func fetchUnreadCountForStarredArticles(_ completion: @escaping SingleUnreadCountCompletionBlock) { - database.fetchStarredAndUnreadCount(for: flattenedFeeds().feedIDs(), completion: completion) + database.fetchStarredAndUnreadCount(for: flattenedFeedIDs(), completion: completion) } public func fetchCountForStarredArticles() throws -> Int { - return try database.fetchStarredArticlesCount(flattenedFeeds().feedIDs()) + return try database.fetchStarredArticlesCount(flattenedFeedIDs()) } public func fetchUnreadArticleIDs() async throws -> Set { @@ -991,6 +998,10 @@ public enum FetchType { return _flattenedFeeds } + public func flattenedFeedIDs() -> Set { + flattenedFeeds().feedIDs() + } + public func removeFeed(_ feed: Feed) { topLevelFeeds.remove(feed) structureDidChange() @@ -1132,12 +1143,12 @@ extension Account: FeedMetadataDelegate { private extension Account { func fetchStarredArticles(limit: Int?) throws -> Set
{ - return try database.fetchStarredArticles(flattenedFeeds().feedIDs(), limit) + return try database.fetchStarredArticles(flattenedFeedIDs(), limit) } func fetchStarredArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) { Task { @MainActor in - let feedIDs = flattenedFeeds().feedIDs() + let feedIDs = flattenedFeedIDs() do { let articles = try await database.starredArticlesForFeeds(feedIDs, limit) @@ -1157,15 +1168,13 @@ private extension Account { } func fetchTodayArticles(limit: Int?) throws -> Set
{ - return try database.fetchTodayArticles(flattenedFeeds().feedIDs(), limit) + return try database.fetchTodayArticles(flattenedFeedIDs(), limit) } func fetchTodayArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) { Task { @MainActor in - let feedIDs = flattenedFeeds().feedIDs() - do { - let articles = try await database.todayArticlesForFeeds(feedIDs, limit) + let articles = try await database.todayArticlesForFeeds(flattenedFeedIDs(), limit) completion(.success(articles)) } catch { completion(.failure(error as! DatabaseError)) @@ -1213,7 +1222,7 @@ private extension Account { } func fetchArticlesMatching(_ searchString: String) throws -> Set
{ - return try database.fetchArticlesMatching(searchString, flattenedFeeds().feedIDs()) + return try database.fetchArticlesMatching(searchString, flattenedFeedIDs()) } func fetchArticlesMatchingWithArticleIDs(_ searchString: String, _ articleIDs: Set) throws -> Set
{ @@ -1223,8 +1232,8 @@ private extension Account { func fetchArticlesMatchingAsync(_ searchString: String, _ completion: @escaping ArticleSetResultBlock) { Task { @MainActor in - let feedIDs = flattenedFeeds().feedIDs() - + let feedIDs = flattenedFeedIDs() + do { let articles = try await database.articlesForSearchStringInFeeds(searchString, feedIDs) Task { @MainActor in diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift index f959b1ef6..793aa65e9 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift @@ -189,12 +189,12 @@ public typealias ArticleStatusesResultBlock = (ArticleStatusesResult) -> Void try await articlesTable.unreadCountsForFeedIDs(feedIDs) } - public func fetchUnreadCountForToday(for feedIDs: Set, completion: @escaping SingleUnreadCountCompletionBlock) { - fetchUnreadCount(for: feedIDs, since: todayCutoffDate(), completion: completion) + public func unreadCountForTodayForFeedIDs(_ feedIDs: Set) async throws -> Int { + try await unreadCountForFeedIDsSince(feedIDs, todayCutoffDate()) } - public func fetchUnreadCount(for feedIDs: Set, since: Date, completion: @escaping SingleUnreadCountCompletionBlock) { - articlesTable.fetchUnreadCount(feedIDs, since, completion) + public func unreadCountForFeedIDsSince(_ feedIDs: Set, _ since: Date) async throws -> Int { + try await articlesTable.unreadCountForFeedIDsSince(feedIDs, since) } public func fetchStarredAndUnreadCount(for feedIDs: Set, completion: @escaping SingleUnreadCountCompletionBlock) { diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift index a60032a89..709e3136f 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift @@ -458,37 +458,34 @@ final class ArticlesTable: DatabaseTable { } } - func fetchUnreadCount(_ feedIDs: Set, _ since: Date, _ completion: @escaping SingleUnreadCountCompletionBlock) { + func unreadCountForFeedIDsSince(_ feedIDs: Set, _ since: Date) async throws -> Int { // Get unread count for today, for instance. if feedIDs.isEmpty { - completion(.success(0)) - return + return 0 } - - queue.runInDatabase { databaseResult in - func makeDatabaseCalls(_ database: FMDatabase) { - let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(feedIDs.count))! - let sql = "select count(*) from articles natural join statuses where feedID in \(placeholders) and (datePublished > ? or (datePublished is null and dateArrived > ?)) and read=0;" + return try await withCheckedThrowingContinuation { continuation in + queue.runInDatabase { databaseResult in - var parameters = [Any]() - parameters += Array(feedIDs) as [Any] - parameters += [since] as [Any] - parameters += [since] as [Any] + func fetchUnreadCount(_ database: FMDatabase) -> Int { + let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(feedIDs.count))! + let sql = "select count(*) from articles natural join statuses where feedID in \(placeholders) and (datePublished > ? or (datePublished is null and dateArrived > ?)) and read=0;" - let unreadCount = self.numberWithSQLAndParameters(sql, parameters, in: database) + var parameters = [Any]() + parameters += Array(feedIDs) as [Any] + parameters += [since] as [Any] + parameters += [since] as [Any] - DispatchQueue.main.async { - completion(.success(unreadCount)) + let unreadCount = self.numberWithSQLAndParameters(sql, parameters, in: database) + return unreadCount } - } - switch databaseResult { - case .success(let database): - makeDatabaseCalls(database) - case .failure(let databaseError): - DispatchQueue.main.async { - completion(.failure(databaseError)) + switch databaseResult { + case .success(let database): + let unreadCount = fetchUnreadCount(database) + continuation.resume(returning: unreadCount) + case .failure(let databaseError): + continuation.resume(throwing: databaseError) } } }