Continue converting ArticlesDatabase to async/await.

This commit is contained in:
Brent Simmons
2023-10-01 21:58:45 -07:00
parent 10732e45c7
commit 0c376828d2
4 changed files with 57 additions and 116 deletions

View File

@@ -668,8 +668,8 @@ public enum FetchType {
structureDidChange()
}
public func updateUnreadCounts(for feeds: Set<Feed>, completion: VoidCompletionBlock? = nil) {
fetchUnreadCounts(for: feeds, completion: completion)
public func updateUnreadCounts(for feeds: Set<Feed>) {
fetchUnreadCounts(for: feeds)
}
public func fetchUnreadArticlesBetween(limit: Int?, before: Date?, after: Date?) throws -> Set<Article> {
@@ -1454,50 +1454,46 @@ private extension Account {
/// Fetch unread counts for zero or more feeds.
///
/// Uses the most efficient method based on how many feeds were passed in.
func fetchUnreadCounts(for feeds: Set<Feed>, completion: VoidCompletionBlock?) {
func fetchUnreadCounts(for feeds: Set<Feed>) {
if feeds.isEmpty {
completion?()
return
}
if feeds.count == 1, let feed = feeds.first {
fetchUnreadCount(feed, completion)
fetchUnreadCount(feed)
}
else if feeds.count < 10 {
fetchUnreadCounts(feeds, completion)
fetchUnreadCounts(feeds)
}
else {
fetchAllUnreadCounts(completion)
fetchAllUnreadCounts()
}
}
func fetchUnreadCount(_ feed: Feed, _ completion: VoidCompletionBlock?) {
func fetchUnreadCount(_ feed: Feed) {
Task { @MainActor in
if let unreadCount = try? await database.unreadCountForFeed(feed.feedID) {
feed.unreadCount = unreadCount
}
completion?()
}
}
func fetchUnreadCounts(_ feeds: Set<Feed>, _ completion: VoidCompletionBlock?) {
let feedIDs = Set(feeds.map { $0.feedID })
database.fetchUnreadCounts(for: feedIDs) { result in
Task { @MainActor in
if let unreadCountDictionary = try? result.get() {
self.processUnreadCounts(unreadCountDictionary: unreadCountDictionary, feeds: feeds)
}
completion?()
}
func fetchUnreadCounts(_ feeds: Set<Feed>) {
Task { @MainActor in
let feedIDs = Set(feeds.map { $0.feedID })
if let unreadCountDictionary = try? await database.unreadCountsForFeedIDs(feedIDs) {
self.processUnreadCounts(unreadCountDictionary: unreadCountDictionary, feeds: feeds)
}
}
}
func fetchAllUnreadCounts(_ completion: VoidCompletionBlock? = nil) {
func fetchAllUnreadCounts() {
fetchingAllUnreadCounts = true
database.fetchAllUnreadCounts { result in
Task { @MainActor in
guard let unreadCountDictionary = try? result.get() else {
completion?()
return
return
}
self.processUnreadCounts(unreadCountDictionary: unreadCountDictionary, feeds: self.flattenedFeeds())
@@ -1508,7 +1504,6 @@ private extension Account {
self.isUnreadCountsInitialized = true
self.postUnreadCountDidInitializeNotification()
}
completion?()
}
}
}

View File

@@ -185,14 +185,8 @@ public typealias ArticleStatusesResultBlock = (ArticleStatusesResult) -> Void
try await articlesTable.unreadCountForFeedID(feedID)
}
/// Fetch non-zero unread counts for given feedIDs.
public func fetchUnreadCounts(for feedIDs: Set<String>, _ completion: @escaping UnreadCountDictionaryCompletionBlock) {
let operation = FetchUnreadCountsForFeedsOperation(feedIDs: feedIDs, databaseQueue: queue)
operation.completionBlock = { operation in
let fetchOperation = operation as! FetchUnreadCountsForFeedsOperation
completion(fetchOperation.result)
}
operationQueue.add(operation)
public func unreadCountsForFeedIDs(_ feedIDs: Set<String>) async throws -> UnreadCountDictionary {
try await articlesTable.unreadCountsForFeedIDs(feedIDs)
}
public func fetchUnreadCountForToday(for feedIDs: Set<String>, completion: @escaping SingleUnreadCountCompletionBlock) {

View File

@@ -420,6 +420,44 @@ final class ArticlesTable: DatabaseTable {
}
}
func unreadCountsForFeedIDs(_ feedIDs: Set<String>) async throws -> UnreadCountDictionary {
try await withCheckedThrowingContinuation { continuation in
queue.runInDatabase { databaseResult in
func fetchUnreadCounts(_ database: FMDatabase) -> UnreadCountDictionary {
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(feedIDs.count))!
let sql = "select distinct feedID, count(*) from articles natural join statuses where feedID in \(placeholders) and read=0 group by feedID;"
let parameters = Array(feedIDs) as [Any]
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
return UnreadCountDictionary()
}
var unreadCountDictionary = UnreadCountDictionary()
while resultSet.next() {
let unreadCount = resultSet.long(forColumnIndex: 1)
if let feedID = resultSet.string(forColumnIndex: 0) {
unreadCountDictionary[feedID] = unreadCount
}
}
resultSet.close()
return unreadCountDictionary
}
switch databaseResult {
case .success(let database):
let unreadCountDictionary = fetchUnreadCounts(database)
continuation.resume(returning: unreadCountDictionary)
case .failure(let databaseError):
continuation.resume(throwing: databaseError)
}
}
}
}
func fetchUnreadCount(_ feedIDs: Set<String>, _ since: Date, _ completion: @escaping SingleUnreadCountCompletionBlock) {
// Get unread count for today, for instance.
if feedIDs.isEmpty {

View File

@@ -1,86 +0,0 @@
//
// FetchUnreadCountsForFeedsOperation.swift
// ArticlesDatabase
//
// Created by Brent Simmons on 2/1/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import RSCore
import RSDatabase
import RSDatabaseObjC
/// Fetch the unread counts for a number of feeds.
public final class FetchUnreadCountsForFeedsOperation: MainThreadOperation {
var result: UnreadCountDictionaryCompletionResult = .failure(.isSuspended)
// MainThreadOperation
public var isCanceled = false
public var id: Int?
public weak var operationDelegate: MainThreadOperationDelegate?
public var name: String? = "FetchUnreadCountsForFeedsOperation"
public var completionBlock: MainThreadOperation.MainThreadOperationCompletionBlock?
private let queue: DatabaseQueue
private let feedIDs: Set<String>
init(feedIDs: Set<String>, databaseQueue: DatabaseQueue) {
self.feedIDs = feedIDs
self.queue = databaseQueue
}
public func run() {
queue.runInDatabase { databaseResult in
if self.isCanceled {
self.informOperationDelegateOfCompletion()
return
}
switch databaseResult {
case .success(let database):
self.fetchUnreadCounts(database)
case .failure:
self.informOperationDelegateOfCompletion()
}
}
}
}
private extension FetchUnreadCountsForFeedsOperation {
func fetchUnreadCounts(_ database: FMDatabase) {
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(feedIDs.count))!
let sql = "select distinct feedID, count(*) from articles natural join statuses where feedID in \(placeholders) and read=0 group by feedID;"
let parameters = Array(feedIDs) as [Any]
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
informOperationDelegateOfCompletion()
return
}
if isCanceled {
resultSet.close()
informOperationDelegateOfCompletion()
return
}
var unreadCountDictionary = UnreadCountDictionary()
while resultSet.next() {
if isCanceled {
resultSet.close()
informOperationDelegateOfCompletion()
return
}
let unreadCount = resultSet.long(forColumnIndex: 1)
if let feedID = resultSet.string(forColumnIndex: 0) {
unreadCountDictionary[feedID] = unreadCount
}
}
resultSet.close()
result = .success(unreadCountDictionary)
informOperationDelegateOfCompletion()
}
}