2019-07-06 05:06:31 +02:00
|
|
|
//
|
|
|
|
// FetchRequestOperation.swift
|
|
|
|
// NetNewsWire
|
|
|
|
//
|
|
|
|
// Created by Brent Simmons on 6/20/19.
|
|
|
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import Account
|
|
|
|
import Articles
|
2024-03-11 02:17:04 +01:00
|
|
|
import Database
|
2019-07-06 05:06:31 +02:00
|
|
|
|
|
|
|
// Main thread only.
|
|
|
|
// Runs an asynchronous fetch.
|
|
|
|
|
|
|
|
typealias FetchRequestOperationResultBlock = (Set<Article>, FetchRequestOperation) -> Void
|
|
|
|
|
2019-10-14 07:08:05 +02:00
|
|
|
final class FetchRequestOperation {
|
2019-07-06 05:06:31 +02:00
|
|
|
|
|
|
|
let id: Int
|
2024-02-26 06:17:00 +01:00
|
|
|
let readFilterEnabledTable: [SidebarItemIdentifier: Bool]
|
2019-07-06 05:06:31 +02:00
|
|
|
let resultBlock: FetchRequestOperationResultBlock
|
|
|
|
var isCanceled = false
|
|
|
|
var isFinished = false
|
2020-09-13 01:09:42 +02:00
|
|
|
private let fetchers: [ArticleFetcher]
|
2019-07-06 05:06:31 +02:00
|
|
|
|
2024-02-26 06:17:00 +01:00
|
|
|
init(id: Int, readFilterEnabledTable: [SidebarItemIdentifier: Bool], fetchers: [ArticleFetcher], resultBlock: @escaping FetchRequestOperationResultBlock) {
|
2019-07-06 05:06:31 +02:00
|
|
|
precondition(Thread.isMainThread)
|
|
|
|
self.id = id
|
2020-09-09 00:14:49 +02:00
|
|
|
self.readFilterEnabledTable = readFilterEnabledTable
|
2020-09-13 01:09:42 +02:00
|
|
|
self.fetchers = fetchers
|
2019-07-06 05:06:31 +02:00
|
|
|
self.resultBlock = resultBlock
|
|
|
|
}
|
|
|
|
|
2024-03-19 05:08:37 +01:00
|
|
|
@MainActor func run(_ completion: @escaping (FetchRequestOperation) -> Void) {
|
2019-07-06 05:06:31 +02:00
|
|
|
precondition(Thread.isMainThread)
|
|
|
|
precondition(!isFinished)
|
|
|
|
|
2019-10-14 07:08:05 +02:00
|
|
|
var didCallCompletion = false
|
|
|
|
|
|
|
|
func callCompletionIfNeeded() {
|
|
|
|
if !didCallCompletion {
|
|
|
|
didCallCompletion = true
|
|
|
|
completion(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-06 05:06:31 +02:00
|
|
|
if isCanceled {
|
2019-10-14 07:08:05 +02:00
|
|
|
callCompletionIfNeeded()
|
2019-07-06 05:06:31 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-13 01:09:42 +02:00
|
|
|
if fetchers.isEmpty {
|
2019-07-06 05:06:31 +02:00
|
|
|
isFinished = true
|
|
|
|
resultBlock(Set<Article>(), self)
|
2019-10-14 07:08:05 +02:00
|
|
|
callCompletionIfNeeded()
|
2019-07-06 05:06:31 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-13 01:09:42 +02:00
|
|
|
let numberOfFetchers = fetchers.count
|
2019-07-06 05:06:31 +02:00
|
|
|
var fetchersReturned = 0
|
|
|
|
var fetchedArticles = Set<Article>()
|
2019-11-22 02:54:35 +01:00
|
|
|
|
2024-03-25 06:56:09 +01:00
|
|
|
func process(_ articles: Set<Article>?) {
|
2019-11-22 02:54:35 +01:00
|
|
|
precondition(Thread.isMainThread)
|
|
|
|
guard !self.isCanceled else {
|
|
|
|
callCompletionIfNeeded()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!self.isFinished)
|
|
|
|
|
2024-03-25 06:56:09 +01:00
|
|
|
if let articles {
|
|
|
|
fetchedArticles.formUnion(articles)
|
|
|
|
}
|
|
|
|
|
2019-11-22 02:54:35 +01:00
|
|
|
fetchersReturned += 1
|
|
|
|
if fetchersReturned == numberOfFetchers {
|
|
|
|
self.isFinished = true
|
|
|
|
self.resultBlock(fetchedArticles, self)
|
|
|
|
callCompletionIfNeeded()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-25 06:56:09 +01:00
|
|
|
Task { @MainActor in
|
|
|
|
for fetcher in fetchers {
|
|
|
|
if (fetcher as? SidebarItem)?.readFiltered(readFilterEnabledTable: readFilterEnabledTable) ?? true {
|
|
|
|
let articles = try? await fetcher.fetchUnreadArticles()
|
2019-12-17 07:45:59 +01:00
|
|
|
process(articles)
|
2024-03-25 06:56:09 +01:00
|
|
|
} else {
|
|
|
|
let articles = try? await fetcher.fetchArticles()
|
2019-12-17 07:45:59 +01:00
|
|
|
process(articles)
|
2019-07-06 05:06:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|