Fix downloadProgress for local account.

This commit is contained in:
Brent Simmons
2024-11-27 22:26:38 -08:00
parent ece6e521e5
commit 72f7a7cadf
4 changed files with 51 additions and 38 deletions

View File

@@ -25,12 +25,10 @@ final class LocalAccountDelegate: AccountDelegate {
weak var account: Account?
private lazy var refresher: LocalAccountRefresher? = {
let refresher = LocalAccountRefresher()
refresher.delegate = self
return refresher
lazy var refreshProgress: DownloadProgress = {
refresher!.downloadProgress
}()
let behaviors: AccountBehaviors = []
let isOPMLImportInProgress = false
@@ -38,8 +36,12 @@ final class LocalAccountDelegate: AccountDelegate {
var credentials: Credentials?
var accountMetadata: AccountMetadata?
let refreshProgress = DownloadProgress(numberOfTasks: 0)
private lazy var refresher: LocalAccountRefresher? = {
let refresher = LocalAccountRefresher()
refresher.delegate = self
return refresher
}()
func receiveRemoteNotification(for account: Account, userInfo: [AnyHashable : Any], completion: @escaping () -> Void) {
completion()
}
@@ -51,7 +53,6 @@ final class LocalAccountDelegate: AccountDelegate {
}
let webFeeds = account.flattenedWebFeeds()
refreshProgress.addToNumberOfTasksAndRemaining(webFeeds.count)
let group = DispatchGroup()
@@ -61,11 +62,9 @@ final class LocalAccountDelegate: AccountDelegate {
}
group.notify(queue: DispatchQueue.main) {
self.refreshProgress.clear()
account.metadata.lastArticleFetchEndTime = Date()
completion(.success(()))
}
}
func syncArticleStatus(for account: Account, completion: ((Result<Void, Error>) -> Void)? = nil) {
@@ -79,17 +78,17 @@ final class LocalAccountDelegate: AccountDelegate {
func refreshArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
completion(.success(()))
}
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
var fileData: Data?
do {
fileData = try Data(contentsOf: opmlFile)
} catch {
completion(.failure(error))
return
}
guard let opmlData = fileData else {
completion(.success(()))
return
@@ -119,7 +118,6 @@ final class LocalAccountDelegate: AccountDelegate {
}
completion(.success(()))
}
func createWebFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<WebFeed, Error>) -> Void) {
@@ -230,28 +228,24 @@ private extension LocalAccountDelegate {
// container before the name has been downloaded. This will put it in the sidebar
// with an Untitled name if we don't delay it being added to the sidebar.
BatchUpdate.shared.start()
refreshProgress.addToNumberOfTasksAndRemaining(1)
FeedFinder.find(url: url) { result in
switch result {
case .success(let feedSpecifiers):
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers),
let url = URL(string: bestFeedSpecifier.urlString) else {
self.refreshProgress.completeTask()
BatchUpdate.shared.end()
completion(.failure(AccountError.createErrorNotFound))
return
}
if account.hasWebFeed(withURL: bestFeedSpecifier.urlString) {
self.refreshProgress.completeTask()
BatchUpdate.shared.end()
completion(.failure(AccountError.createErrorAlreadySubscribed))
return
}
InitialFeedDownloader.download(url) { parsedFeed in
self.refreshProgress.completeTask()
if let parsedFeed = parsedFeed {
let feed = account.createWebFeed(with: nil, url: url.absoluteString, webFeedID: url.absoluteString, homePageURL: nil)
@@ -266,17 +260,12 @@ private extension LocalAccountDelegate {
BatchUpdate.shared.end()
completion(.failure(AccountError.createErrorNotFound))
}
}
case .failure:
BatchUpdate.shared.end()
self.refreshProgress.completeTask()
completion(.failure(AccountError.createErrorNotFound))
}
}
}
}

View File

@@ -19,10 +19,14 @@ protocol LocalAccountRefresherDelegate {
final class LocalAccountRefresher {
var delegate: LocalAccountRefresherDelegate?
lazy var downloadProgress: DownloadProgress = {
downloadSession.downloadProgress
}()
private var completion: (() -> Void)? = nil
private var isSuspended = false
var delegate: LocalAccountRefresherDelegate?
private lazy var downloadSession: DownloadSession = {
return DownloadSession(delegate: self)
}()

View File

@@ -30,9 +30,6 @@ public final class DownloadProgress {
public var numberRemaining = 0 {
didSet {
if numberRemaining == 0 && numberOfTasks != 0 {
numberOfTasks = 0
}
if numberRemaining != oldValue {
postDidChangeNotification()
}

View File

@@ -19,7 +19,9 @@ public protocol DownloadSessionDelegate {
}
@objc public final class DownloadSession: NSObject {
public let downloadProgress = DownloadProgress(numberOfTasks: 0)
private var urlSession: URLSession!
private var tasksInProgress = Set<URLSessionTask>()
private var tasksPending = Set<URLSessionTask>()
@@ -71,6 +73,7 @@ public protocol DownloadSessionDelegate {
addDataTask(url)
}
urlsInSession.formUnion(urls)
updateDownloadProgress()
}
}
@@ -79,10 +82,12 @@ public protocol DownloadSessionDelegate {
extension DownloadSession: URLSessionTaskDelegate {
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
tasksInProgress.remove(task)
defer {
removeTask(task)
}
guard let info = infoForTask(task) else {
removeTask(task)
return
}
@@ -106,7 +111,11 @@ extension DownloadSession: URLSessionTaskDelegate {
extension DownloadSession: URLSessionDataDelegate {
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
defer {
updateDownloadProgress()
}
tasksInProgress.insert(dataTask)
tasksPending.remove(dataTask)
@@ -178,8 +187,8 @@ private extension DownloadSession {
}
func addDataTaskFromQueueIfNecessary() {
guard tasksPending.count < 500, let representedObject = queue.popLast() else { return }
addDataTask(representedObject)
guard tasksPending.count < 500, let url = queue.popLast() else { return }
addDataTask(url)
}
func infoForTask(_ task: URLSessionTask) -> DownloadInfo? {
@@ -193,10 +202,7 @@ private extension DownloadSession {
addDataTaskFromQueueIfNecessary()
if tasksInProgress.count + tasksPending.count < 1 {
urlsInSession.removeAll()
delegate.downloadSessionDidComplete(self)
}
updateDownloadProgress()
}
func urlStringIsBlackListedRedirect(_ urlString: String) -> Bool {
@@ -251,6 +257,23 @@ private extension DownloadSession {
return currentString == urlString ? nil : currentString
}
// MARK: - Download Progress
func updateDownloadProgress() {
downloadProgress.numberOfTasks = urlsInSession.count
let numberRemaining = tasksPending.count + tasksInProgress.count + queue.count
downloadProgress.numberRemaining = min(numberRemaining, downloadProgress.numberOfTasks)
// Complete?
if downloadProgress.numberOfTasks > 0 && downloadProgress.numberRemaining < 1 {
delegate.downloadSessionDidComplete(self)
urlsInSession.removeAll()
downloadProgress.numberOfTasks = 0
}
}
// MARK: - 429 Too Many Requests
func handle429Response(_ dataTask: URLSessionDataTask, _ response: URLResponse) {