Move the operation queue from Account to ArticlesDatabase, which is the rightful owner.
This commit is contained in:
parent
d40eaed1f5
commit
01fc60916e
|
@ -231,14 +231,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
return delegate.refreshProgress
|
||||
}
|
||||
|
||||
private var operationQueue = MainThreadOperationQueue()
|
||||
private enum OperationName {
|
||||
static let FetchAllUnreadCounts = "FetchAllUnreadCounts"
|
||||
static let FetchFeedUnreadCount = "FetchFeedUnreadCount"
|
||||
static let FetchUnreadCountsForFeeds = "FetchUnreadCountsForFeeds"
|
||||
}
|
||||
private static let discardableOperationNames = [OperationName.FetchAllUnreadCounts, OperationName.FetchFeedUnreadCount, OperationName.FetchUnreadCountsForFeeds]
|
||||
|
||||
init?(dataFolder: String, type: AccountType, accountID: String, transport: Transport? = nil) {
|
||||
switch type {
|
||||
case .onMyMac:
|
||||
|
@ -422,9 +414,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
}
|
||||
|
||||
public func suspendDatabase() {
|
||||
operationQueue.suspend()
|
||||
cancelDiscardableOperations()
|
||||
database.suspend()
|
||||
database.cancelAndSuspend()
|
||||
save()
|
||||
metadataFile.suspend()
|
||||
webFeedMetadataFile.suspend()
|
||||
|
@ -436,7 +426,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
public func resumeDatabaseAndDelegate() {
|
||||
database.resume()
|
||||
delegate.resume()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
/// Reload OPML, etc.
|
||||
|
@ -460,12 +449,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
delegate.accountWillBeDeleted(self)
|
||||
}
|
||||
|
||||
public func cancelDiscardableOperations() {
|
||||
for operationName in Self.discardableOperationNames {
|
||||
operationQueue.cancelOperations(named: operationName)
|
||||
}
|
||||
}
|
||||
|
||||
func loadOPMLItems(_ items: [RSOPMLItem], parentFolder: Folder?) {
|
||||
var feedsToAdd = Set<WebFeed>()
|
||||
|
||||
|
@ -1242,43 +1225,34 @@ private extension Account {
|
|||
fetchUnreadCounts(feeds, completion)
|
||||
}
|
||||
else {
|
||||
fetchAllUnreadCounts()
|
||||
fetchAllUnreadCounts(completion)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchUnreadCount(_ feed: WebFeed, _ completion: VoidCompletionBlock?) {
|
||||
let operation = database.createFetchFeedUnreadCountOperation(feedID: feed.webFeedID)
|
||||
operation.name = OperationName.FetchFeedUnreadCount
|
||||
operation.completionBlock = { operation in
|
||||
let fetchOperation = operation as! FetchFeedUnreadCountOperation
|
||||
if let unreadCount = fetchOperation.unreadCount {
|
||||
database.fetchUnreadCount(feed.webFeedID) { result in
|
||||
if let unreadCount = try? result.get() {
|
||||
feed.unreadCount = unreadCount
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
|
||||
operationQueue.add(operation)
|
||||
}
|
||||
|
||||
func fetchUnreadCounts(_ feeds: Set<WebFeed>, _ completion: VoidCompletionBlock?) {
|
||||
let feedIDs = feeds.map { $0.webFeedID }
|
||||
let operation = database.createFetchUnreadCountsForFeedsOperation(feedIDs: Set(feedIDs))
|
||||
operation.name = OperationName.FetchUnreadCountsForFeeds
|
||||
operation.completionBlock = { operation in
|
||||
let fetchOperation = operation as! FetchUnreadCountsForFeedsOperation
|
||||
if let unreadCountDictionary = fetchOperation.unreadCountDictionary {
|
||||
let webFeedIDs = Set(feeds.map { $0.webFeedID })
|
||||
database.fetchUnreadCounts(for: webFeedIDs) { result in
|
||||
if let unreadCountDictionary = try? result.get() {
|
||||
self.processUnreadCounts(unreadCountDictionary: unreadCountDictionary, feeds: feeds)
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
|
||||
operationQueue.add(operation)
|
||||
}
|
||||
|
||||
func fetchAllUnreadCounts() {
|
||||
func fetchAllUnreadCounts(_ completion: VoidCompletionBlock? = nil) {
|
||||
fetchingAllUnreadCounts = true
|
||||
database.fetchAllUnreadCounts { (result) in
|
||||
database.fetchAllUnreadCounts { result in
|
||||
guard let unreadCountDictionary = try? result.get() else {
|
||||
completion?()
|
||||
return
|
||||
}
|
||||
self.processUnreadCounts(unreadCountDictionary: unreadCountDictionary, feeds: self.flattenedWebFeeds())
|
||||
|
@ -1290,6 +1264,7 @@ private extension Account {
|
|||
self.isUnreadCountsInitialized = true
|
||||
self.postUnreadCountDidInitializeNotification()
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,6 +149,26 @@ public final class ArticlesDatabase {
|
|||
operationQueue.add(operation)
|
||||
}
|
||||
|
||||
/// Fetch unread count for a single feed.
|
||||
public func fetchUnreadCount(_ webFeedID: String, _ completion: @escaping SingleUnreadCountCompletionBlock) {
|
||||
let operation = FetchFeedUnreadCountOperation(webFeedID: webFeedID, databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate)
|
||||
operation.completionBlock = { operation in
|
||||
let fetchOperation = operation as! FetchFeedUnreadCountOperation
|
||||
completion(fetchOperation.result)
|
||||
}
|
||||
operationQueue.add(operation)
|
||||
}
|
||||
|
||||
/// Fetch non-zero unread counts for given webFeedIDs.
|
||||
public func fetchUnreadCounts(for webFeedIDs: Set<String>, _ completion: @escaping UnreadCountDictionaryCompletionBlock) {
|
||||
let operation = FetchUnreadCountsForFeedsOperation(webFeedIDs: webFeedIDs, databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate)
|
||||
operation.completionBlock = { operation in
|
||||
let fetchOperation = operation as! FetchUnreadCountsForFeedsOperation
|
||||
completion(fetchOperation.result)
|
||||
}
|
||||
operationQueue.add(operation)
|
||||
}
|
||||
|
||||
public func fetchUnreadCountForToday(for webFeedIDs: Set<String>, completion: @escaping SingleUnreadCountCompletionBlock) {
|
||||
fetchUnreadCount(for: webFeedIDs, since: todayCutoffDate(), completion: completion)
|
||||
}
|
||||
|
@ -199,33 +219,25 @@ public final class ArticlesDatabase {
|
|||
articlesTable.createStatusesIfNeeded(articleIDs, completion)
|
||||
}
|
||||
|
||||
// MARK: - Operations
|
||||
|
||||
public func cancelOperations() {
|
||||
operationQueue.cancelAllOperations()
|
||||
}
|
||||
|
||||
/// Create an operation that fetches the unread count for a single given feedID.
|
||||
public func createFetchFeedUnreadCountOperation(feedID: String) -> FetchFeedUnreadCountOperation {
|
||||
return FetchFeedUnreadCountOperation(feedID: feedID, databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate)
|
||||
}
|
||||
|
||||
/// Create an operation that fetches unread counts for a number of feedIDs.
|
||||
public func createFetchUnreadCountsForFeedsOperation(feedIDs: Set<String>) -> FetchUnreadCountsForFeedsOperation {
|
||||
return FetchUnreadCountsForFeedsOperation(feedIDs: feedIDs, databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate)
|
||||
}
|
||||
|
||||
// MARK: - Suspend and Resume (for iOS)
|
||||
|
||||
/// Cancel current operations and close the database.
|
||||
public func cancelAndSuspend() {
|
||||
cancelOperations()
|
||||
suspend()
|
||||
}
|
||||
|
||||
/// Close the database and stop running database calls.
|
||||
/// Any pending calls will complete first.
|
||||
public func suspend() {
|
||||
operationQueue.suspend()
|
||||
queue.suspend()
|
||||
}
|
||||
|
||||
/// Open the database and allow for running database calls again.
|
||||
public func resume() {
|
||||
queue.resume()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
// MARK: - Caches
|
||||
|
@ -272,4 +284,10 @@ private extension ArticlesDatabase {
|
|||
// 24 hours previous. This is used by the Today smart feed, which should not actually empty out at midnight.
|
||||
return Date(timeIntervalSinceNow: -(60 * 60 * 24)) // This does not need to be more precise.
|
||||
}
|
||||
|
||||
// MARK: - Operations
|
||||
|
||||
func cancelOperations() {
|
||||
operationQueue.cancelAllOperations()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import RSDatabase
|
|||
|
||||
public final class FetchAllUnreadCountsOperation: MainThreadOperation {
|
||||
|
||||
public var result: UnreadCountDictionaryCompletionResult = .failure(.isSuspended)
|
||||
var result: UnreadCountDictionaryCompletionResult = .failure(.isSuspended)
|
||||
|
||||
// MainThreadOperation
|
||||
public var isCanceled = false
|
||||
|
|
|
@ -13,8 +13,7 @@ import RSDatabase
|
|||
/// Fetch the unread count for a single feed.
|
||||
public final class FetchFeedUnreadCountOperation: MainThreadOperation {
|
||||
|
||||
public var unreadCount: Int?
|
||||
public let feedID: String
|
||||
var result: SingleUnreadCountResult = .failure(.isSuspended)
|
||||
|
||||
// MainThreadOperation
|
||||
public var isCanceled = false
|
||||
|
@ -25,9 +24,10 @@ public final class FetchFeedUnreadCountOperation: MainThreadOperation {
|
|||
|
||||
private let queue: DatabaseQueue
|
||||
private let cutoffDate: Date
|
||||
private let webFeedID: String
|
||||
|
||||
init(feedID: String, databaseQueue: DatabaseQueue, cutoffDate: Date) {
|
||||
self.feedID = feedID
|
||||
init(webFeedID: String, databaseQueue: DatabaseQueue, cutoffDate: Date) {
|
||||
self.webFeedID = webFeedID
|
||||
self.queue = databaseQueue
|
||||
self.cutoffDate = cutoffDate
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ private extension FetchFeedUnreadCountOperation {
|
|||
func fetchUnreadCount(_ database: FMDatabase) {
|
||||
let sql = "select count(*) from articles natural join statuses where feedID=? and read=0 and userDeleted=0 and (starred=1 or dateArrived>?);"
|
||||
|
||||
guard let resultSet = database.executeQuery(sql, withArgumentsIn: [feedID, cutoffDate]) else {
|
||||
guard let resultSet = database.executeQuery(sql, withArgumentsIn: [webFeedID, cutoffDate]) else {
|
||||
informOperationDelegateOfCompletion()
|
||||
return
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ private extension FetchFeedUnreadCountOperation {
|
|||
}
|
||||
|
||||
if resultSet.next() {
|
||||
unreadCount = resultSet.long(forColumnIndex: 0)
|
||||
let unreadCount = resultSet.long(forColumnIndex: 0)
|
||||
result = .success(unreadCount)
|
||||
}
|
||||
resultSet.close()
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@ import RSDatabase
|
|||
/// Fetch the unread counts for a number of feeds.
|
||||
public final class FetchUnreadCountsForFeedsOperation: MainThreadOperation {
|
||||
|
||||
public var unreadCountDictionary: UnreadCountDictionary?
|
||||
public let feedIDs: Set<String>
|
||||
var result: UnreadCountDictionaryCompletionResult = .failure(.isSuspended)
|
||||
|
||||
// MainThreadOperation
|
||||
public var isCanceled = false
|
||||
|
@ -25,9 +24,10 @@ public final class FetchUnreadCountsForFeedsOperation: MainThreadOperation {
|
|||
|
||||
private let queue: DatabaseQueue
|
||||
private let cutoffDate: Date
|
||||
private let webFeedIDs: Set<String>
|
||||
|
||||
init(feedIDs: Set<String>, databaseQueue: DatabaseQueue, cutoffDate: Date) {
|
||||
self.feedIDs = feedIDs
|
||||
init(webFeedIDs: Set<String>, databaseQueue: DatabaseQueue, cutoffDate: Date) {
|
||||
self.webFeedIDs = webFeedIDs
|
||||
self.queue = databaseQueue
|
||||
self.cutoffDate = cutoffDate
|
||||
}
|
||||
|
@ -52,11 +52,11 @@ public final class FetchUnreadCountsForFeedsOperation: MainThreadOperation {
|
|||
private extension FetchUnreadCountsForFeedsOperation {
|
||||
|
||||
func fetchUnreadCounts(_ database: FMDatabase) {
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(feedIDs.count))!
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
let sql = "select distinct feedID, count(*) from articles natural join statuses where feedID in \(placeholders) and read=0 and userDeleted=0 and (starred=1 or dateArrived>?) group by feedID;"
|
||||
|
||||
var parameters = [Any]()
|
||||
parameters += Array(feedIDs) as [Any]
|
||||
parameters += Array(webFeedIDs) as [Any]
|
||||
parameters += [cutoffDate] as [Any]
|
||||
|
||||
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
|
||||
|
@ -64,11 +64,12 @@ private extension FetchUnreadCountsForFeedsOperation {
|
|||
return
|
||||
}
|
||||
if isCanceled {
|
||||
resultSet.close()
|
||||
informOperationDelegateOfCompletion()
|
||||
return
|
||||
}
|
||||
|
||||
var d = UnreadCountDictionary()
|
||||
var unreadCountDictionary = UnreadCountDictionary()
|
||||
while resultSet.next() {
|
||||
if isCanceled {
|
||||
resultSet.close()
|
||||
|
@ -77,12 +78,12 @@ private extension FetchUnreadCountsForFeedsOperation {
|
|||
}
|
||||
let unreadCount = resultSet.long(forColumnIndex: 1)
|
||||
if let webFeedID = resultSet.string(forColumnIndex: 0) {
|
||||
d[webFeedID] = unreadCount
|
||||
unreadCountDictionary[webFeedID] = unreadCount
|
||||
}
|
||||
}
|
||||
resultSet.close()
|
||||
|
||||
unreadCountDictionary = d
|
||||
result = .success(unreadCountDictionary)
|
||||
informOperationDelegateOfCompletion()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue