Refactor CloudKit specific feed refreshing out into a standalone class
This commit is contained in:
parent
f0988d1b68
commit
4b54f19a38
@ -35,6 +35,7 @@
|
||||
510BD113232C3E9D002692E4 /* WebFeedMetadataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510BD112232C3E9D002692E4 /* WebFeedMetadataFile.swift */; };
|
||||
510E3317244E0CED00E7A6AF /* TwitterMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510E3316244E0CED00E7A6AF /* TwitterMedia.swift */; };
|
||||
511B9804237CD4270028BCAA /* FeedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511B9803237CD4270028BCAA /* FeedIdentifier.swift */; };
|
||||
5124A1612454C91B00C1245B /* CloudKitFeedRefresher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5124A1602454C91B00C1245B /* CloudKitFeedRefresher.swift */; };
|
||||
512DD4CB2431000600C17B1F /* CKRecord+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512DD4CA2431000600C17B1F /* CKRecord+Extensions.swift */; };
|
||||
512DD4CD2431098700C17B1F /* CloudKitAccountZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */; };
|
||||
5132AAC42448BAD90077840A /* FeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132AAC12448BAD90077840A /* FeedProvider.swift */; };
|
||||
@ -285,6 +286,7 @@
|
||||
511076A3243BD33100D97C8C /* .framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = .framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
511076F4243BD96D00D97C8C /* FeedProvider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FeedProvider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
511B9803237CD4270028BCAA /* FeedIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedIdentifier.swift; sourceTree = "<group>"; };
|
||||
5124A1602454C91B00C1245B /* CloudKitFeedRefresher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitFeedRefresher.swift; sourceTree = "<group>"; };
|
||||
512DD4CA2431000600C17B1F /* CKRecord+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CKRecord+Extensions.swift"; sourceTree = "<group>"; };
|
||||
512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitAccountZoneDelegate.swift; sourceTree = "<group>"; };
|
||||
5132AAC12448BAD90077840A /* FeedProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedProvider.swift; sourceTree = "<group>"; };
|
||||
@ -556,6 +558,7 @@
|
||||
519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */,
|
||||
519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */,
|
||||
5150FFFD243823B800C1A442 /* CloudKitError.swift */,
|
||||
5124A1602454C91B00C1245B /* CloudKitFeedRefresher.swift */,
|
||||
51E4DB2D242633ED0091EB5B /* CloudKitZone.swift */,
|
||||
51C034DE242D65D20014DC71 /* CloudKitZoneResult.swift */,
|
||||
);
|
||||
@ -1172,6 +1175,7 @@
|
||||
519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */,
|
||||
9EEEF71F23545CB4009E9D80 /* FeedlySendArticleStatusesOperation.swift in Sources */,
|
||||
9EBD49C223C67784005AD5CD /* FeedlyEntryIdentifierProviding.swift in Sources */,
|
||||
5124A1612454C91B00C1245B /* CloudKitFeedRefresher.swift in Sources */,
|
||||
846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */,
|
||||
51E490362288C37100C791F0 /* FeedbinDate.swift in Sources */,
|
||||
9EEAE06E235D002D00E3FEE4 /* FeedlyGetCollectionsService.swift in Sources */,
|
||||
|
@ -37,14 +37,18 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
||||
private let accountZone: CloudKitAccountZone
|
||||
private let articlesZone: CloudKitArticlesZone
|
||||
|
||||
weak var account: Account?
|
||||
|
||||
private lazy var refresher: LocalAccountRefresher = {
|
||||
let refresher = LocalAccountRefresher()
|
||||
refresher.delegate = self
|
||||
return refresher
|
||||
}()
|
||||
|
||||
private lazy var cloudKitFeedRefresher: CloudKitFeedRefresher = {
|
||||
return CloudKitFeedRefresher(refreshProgress: refreshProgress, refresher: refresher, articlesZone: articlesZone)
|
||||
}()
|
||||
|
||||
weak var account: Account?
|
||||
|
||||
let behaviors: AccountBehaviors = []
|
||||
let isOPMLImportInProgress = false
|
||||
|
||||
@ -542,7 +546,7 @@ private extension CloudKitAccountDelegate {
|
||||
|
||||
self.refreshProgress.completeTask()
|
||||
|
||||
self.refreshWebFeeds(account, webFeeds) {
|
||||
self.cloudKitFeedRefresher.refresh(account, webFeeds) {
|
||||
self.refreshProgress.clear()
|
||||
account.metadata.lastArticleFetchEndTime = Date()
|
||||
}
|
||||
@ -562,70 +566,6 @@ private extension CloudKitAccountDelegate {
|
||||
fail(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshWebFeeds(_ account: Account, _ webFeeds: Set<WebFeed>, completion: @escaping () -> Void) {
|
||||
|
||||
var newArticles = Set<Article>()
|
||||
var deletedArticles = Set<Article>()
|
||||
|
||||
var refresherWebFeeds = Set<WebFeed>()
|
||||
let group = DispatchGroup()
|
||||
|
||||
refreshProgress.addToNumberOfTasksAndRemaining(2)
|
||||
|
||||
for webFeed in webFeeds {
|
||||
if let components = URLComponents(string: webFeed.url), let feedProvider = FeedProviderManager.shared.best(for: components) {
|
||||
group.enter()
|
||||
feedProvider.refresh(webFeed) { result in
|
||||
switch result {
|
||||
case .success(let parsedItems):
|
||||
|
||||
account.update(webFeed.webFeedID, with: parsedItems) { result in
|
||||
switch result {
|
||||
case .success(let articleChanges):
|
||||
|
||||
newArticles.formUnion(articleChanges.newArticles ?? Set<Article>())
|
||||
deletedArticles.formUnion(articleChanges.deletedArticles ?? Set<Article>())
|
||||
|
||||
self.refreshProgress.completeTask()
|
||||
group.leave()
|
||||
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Feed Provider refresh update error: %@.", error.localizedDescription)
|
||||
self.refreshProgress.completeTask()
|
||||
group.leave()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Feed Provider refresh error: %@.", error.localizedDescription)
|
||||
self.refreshProgress.completeTask()
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
refresherWebFeeds.insert(webFeed)
|
||||
}
|
||||
}
|
||||
|
||||
group.enter()
|
||||
refresher.refreshFeeds(refresherWebFeeds) {
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
|
||||
self.articlesZone.deleteArticles(deletedArticles) { _ in
|
||||
self.refreshProgress.completeTask()
|
||||
self.articlesZone.sendNewArticles(newArticles) { _ in
|
||||
self.refreshProgress.completeTask()
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,10 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
||||
return refresher
|
||||
}()
|
||||
|
||||
private lazy var cloudKitFeedRefresher: CloudKitFeedRefresher = {
|
||||
return CloudKitFeedRefresher(refreshProgress: refreshProgress, refresher: refresher, articlesZone: articlesZone)
|
||||
}()
|
||||
|
||||
init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone, refreshProgress: DownloadProgress?) {
|
||||
self.account = account
|
||||
self.database = database
|
||||
@ -114,7 +118,11 @@ private extension CloudKitArticlesZoneDelegate {
|
||||
if webFeeds.isEmpty {
|
||||
group.leave()
|
||||
} else {
|
||||
self.refresher.refreshFeeds(webFeeds) {
|
||||
if let account = self.account {
|
||||
self.cloudKitFeedRefresher.refresh(account, webFeeds) {
|
||||
group.leave()
|
||||
}
|
||||
} else {
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
94
Frameworks/Account/CloudKit/CloudKitFeedRefresher.swift
Normal file
94
Frameworks/Account/CloudKit/CloudKitFeedRefresher.swift
Normal file
@ -0,0 +1,94 @@
|
||||
//
|
||||
// CloudKitFeedRefresher.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Maurice Parker on 4/25/20.
|
||||
// Copyright © 2020 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSWeb
|
||||
import Articles
|
||||
|
||||
final class CloudKitFeedRefresher {
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit")
|
||||
|
||||
weak var refreshProgress: DownloadProgress?
|
||||
weak var refresher: LocalAccountRefresher?
|
||||
weak var articlesZone: CloudKitArticlesZone?
|
||||
|
||||
init(refreshProgress: DownloadProgress?, refresher: LocalAccountRefresher?, articlesZone: CloudKitArticlesZone?) {
|
||||
self.refreshProgress = refreshProgress
|
||||
self.refresher = refresher
|
||||
self.articlesZone = articlesZone
|
||||
}
|
||||
|
||||
func refresh(_ account: Account, _ webFeeds: Set<WebFeed>, completion: @escaping () -> Void) {
|
||||
guard let refreshProgress = refreshProgress, let refresher = refresher, let articlesZone = articlesZone else { return }
|
||||
|
||||
var newArticles = Set<Article>()
|
||||
var deletedArticles = Set<Article>()
|
||||
|
||||
var refresherWebFeeds = Set<WebFeed>()
|
||||
let group = DispatchGroup()
|
||||
|
||||
refreshProgress.addToNumberOfTasksAndRemaining(2)
|
||||
|
||||
for webFeed in webFeeds {
|
||||
if let components = URLComponents(string: webFeed.url), let feedProvider = FeedProviderManager.shared.best(for: components) {
|
||||
group.enter()
|
||||
feedProvider.refresh(webFeed) { result in
|
||||
switch result {
|
||||
case .success(let parsedItems):
|
||||
|
||||
account.update(webFeed.webFeedID, with: parsedItems) { result in
|
||||
switch result {
|
||||
case .success(let articleChanges):
|
||||
|
||||
newArticles.formUnion(articleChanges.newArticles ?? Set<Article>())
|
||||
deletedArticles.formUnion(articleChanges.deletedArticles ?? Set<Article>())
|
||||
|
||||
refreshProgress.completeTask()
|
||||
group.leave()
|
||||
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "CloudKit Feed refresh update error: %@.", error.localizedDescription)
|
||||
refreshProgress.completeTask()
|
||||
group.leave()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "CloudKit Feed refresh error: %@.", error.localizedDescription)
|
||||
refreshProgress.completeTask()
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
refresherWebFeeds.insert(webFeed)
|
||||
}
|
||||
}
|
||||
|
||||
group.enter()
|
||||
refresher.refreshFeeds(refresherWebFeeds) {
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
|
||||
articlesZone.deleteArticles(deletedArticles) { _ in
|
||||
refreshProgress.completeTask()
|
||||
articlesZone.sendNewArticles(newArticles) { _ in
|
||||
refreshProgress.completeTask()
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user