Use MainThreadOperationQueue with Feedly syncing.
This commit is contained in:
parent
cbc24e3a2e
commit
39db00c022
@ -177,7 +177,6 @@
|
||||
9EF1B10723590D61000A486A /* FeedlyGetStreamIdsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF1B10623590D61000A486A /* FeedlyGetStreamIdsOperation.swift */; };
|
||||
9EF1B10923590E93000A486A /* FeedlyStreamIds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF1B10823590E93000A486A /* FeedlyStreamIds.swift */; };
|
||||
9EF2602C23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF2602B23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift */; };
|
||||
9EF35F7A234E830E003AE2AE /* FeedlyCompoundOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF35F79234E830E003AE2AE /* FeedlyCompoundOperation.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -839,11 +838,11 @@
|
||||
848934F51F62484F00CEBD24 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
848934FE1F62484F00CEBD24 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
ProvisioningStyle = Automatic;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -975,7 +974,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84C8B3F41F89DE430053CCA6 /* DataExtensions.swift in Sources */,
|
||||
9EF35F7A234E830E003AE2AE /* FeedlyCompoundOperation.swift in Sources */,
|
||||
552032F9229D5D5A009559E0 /* ReaderAPISubscription.swift in Sources */,
|
||||
84C3654A1F899F3B001EC85C /* CombinedRefreshProgress.swift in Sources */,
|
||||
9EC688EE232C58E800A8D0A2 /* OAuthAuthorizationCodeGranting.swift in Sources */,
|
||||
|
@ -57,16 +57,14 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Feedly")
|
||||
private let database: SyncDatabase
|
||||
|
||||
private weak var currentSyncAllOperation: FeedlySyncAllOperation?
|
||||
private let operationQueue: OperationQueue
|
||||
private weak var currentSyncAllOperation: MainThreadOperation?
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
|
||||
init(dataFolder: String, transport: Transport?, api: FeedlyAPICaller.API) {
|
||||
self.operationQueue = OperationQueue()
|
||||
// Many operations have their own operation queues, such as the sync all operation.
|
||||
// Making this a serial queue at this higher level of abstraction means we can ensure,
|
||||
// for example, a `FeedlyRefreshAccessTokenOperation` occurs before a `FeedlySyncAllOperation`,
|
||||
// improving our ability to debug, reason about and predict the behaviour of the code.
|
||||
self.operationQueue.maxConcurrentOperationCount = 1
|
||||
|
||||
if let transport = transport {
|
||||
self.caller = FeedlyAPICaller(transport: transport, api: api)
|
||||
@ -135,7 +133,8 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
// Ensure remote articles have the same status as they do locally.
|
||||
let send = FeedlySendArticleStatusesOperation(database: database, service: caller, log: log)
|
||||
send.completionBlock = {
|
||||
send.completionBlock = { operation in
|
||||
// TODO: not call with success if operation was canceled? Not sure.
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(()))
|
||||
}
|
||||
@ -159,7 +158,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: caller, database: database, newerThan: nil, log: log)
|
||||
|
||||
group.enter()
|
||||
ingestUnread.completionBlock = {
|
||||
ingestUnread.completionBlock = { _ in
|
||||
group.leave()
|
||||
|
||||
}
|
||||
@ -167,7 +166,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
let ingestStarred = FeedlyIngestStarredArticleIdsOperation(account: account, credentials: credentials, service: caller, database: database, newerThan: nil, log: log)
|
||||
|
||||
group.enter()
|
||||
ingestStarred.completionBlock = {
|
||||
ingestStarred.completionBlock = { _ in
|
||||
group.leave()
|
||||
}
|
||||
|
||||
@ -175,7 +174,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
operationQueue.addOperations([ingestUnread, ingestStarred], waitUntilFinished: false)
|
||||
operationQueue.addOperations([ingestUnread, ingestStarred])
|
||||
}
|
||||
|
||||
func importOPML(for account: Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
@ -500,8 +499,8 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
|
||||
func accountWillBeDeleted(_ account: Account) {
|
||||
let logout = FeedlyLogoutOperation(account: account, service: caller, log: log)
|
||||
// Dispatch on the main queue because the lifetime of the account delegate is uncertain.
|
||||
OperationQueue.main.addOperation(logout)
|
||||
// Dispatch on the shared queue because the lifetime of the account delegate is uncertain.
|
||||
MainThreadOperationQueue.shared.addOperation(logout)
|
||||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
|
@ -9,9 +9,10 @@
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
private let operationQueue: OperationQueue
|
||||
private let operationQueue: MainThreadOperationQueue
|
||||
|
||||
var addCompletionHandler: ((Result<Void, Error>) -> ())?
|
||||
|
||||
@ -20,8 +21,8 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate,
|
||||
let validator = FeedlyFeedContainerValidator(container: container, userId: credentials.username)
|
||||
let (folder, collectionId) = try validator.getValidContainer()
|
||||
|
||||
self.operationQueue = OperationQueue()
|
||||
self.operationQueue.isSuspended = true
|
||||
self.operationQueue = MainThreadOperationQueue()
|
||||
self.operationQueue.suspend()
|
||||
|
||||
super.init()
|
||||
|
||||
@ -34,13 +35,13 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate,
|
||||
|
||||
let createFeeds = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: addRequest, log: log)
|
||||
createFeeds.downloadProgress = progress
|
||||
createFeeds.addDependency(addRequest)
|
||||
self.operationQueue.make(createFeeds, dependOn: addRequest)
|
||||
self.operationQueue.addOperation(createFeeds)
|
||||
|
||||
let finishOperation = FeedlyCheckpointOperation()
|
||||
finishOperation.checkpointDelegate = self
|
||||
finishOperation.downloadProgress = progress
|
||||
finishOperation.addDependency(createFeeds)
|
||||
self.operationQueue.make(finishOperation, dependOn: createFeeds)
|
||||
self.operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
@ -50,11 +51,9 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate,
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
operationQueue.isSuspended = false
|
||||
override func run() {
|
||||
super.run()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) {
|
||||
@ -65,7 +64,7 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate,
|
||||
}
|
||||
|
||||
func feedlyCheckpointOperationDidReachCheckpoint(_ operation: FeedlyCheckpointOperation) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -35,17 +35,16 @@ final class FeedlyAddFeedToCollectionOperation: FeedlyOperation, FeedlyFeedsAndF
|
||||
return feedResource
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
return didFinish()
|
||||
}
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.addFeed(with: feedResource, title: feedName, toCollectionWith: collectionId) { [weak self] result in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
guard !self.isCancelled else {
|
||||
return self.didFinish()
|
||||
if self.isCanceled {
|
||||
self.didFinish()
|
||||
return
|
||||
}
|
||||
self.didCompleteRequest(result)
|
||||
}
|
||||
|
@ -10,9 +10,10 @@ import Foundation
|
||||
import os.log
|
||||
import SyncDatabase
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlySearchOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
private let operationQueue: OperationQueue
|
||||
private let operationQueue: MainThreadOperationQueue
|
||||
private let folder: Folder
|
||||
private let collectionId: String
|
||||
private let url: String
|
||||
@ -26,15 +27,15 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
private let log: OSLog
|
||||
|
||||
var addCompletionHandler: ((Result<WebFeed, Error>) -> ())?
|
||||
|
||||
|
||||
init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIdsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress, log: OSLog) throws {
|
||||
|
||||
let validator = FeedlyFeedContainerValidator(container: container, userId: credentials.username)
|
||||
(self.folder, self.collectionId) = try validator.getValidContainer()
|
||||
|
||||
self.url = url
|
||||
self.operationQueue = OperationQueue()
|
||||
self.operationQueue.isSuspended = true
|
||||
self.operationQueue = MainThreadOperationQueue()
|
||||
self.operationQueue.suspend()
|
||||
self.account = account
|
||||
self.credentials = credentials
|
||||
self.database = database
|
||||
@ -55,27 +56,21 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
self.operationQueue.addOperation(search)
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
operationQueue.cancelAllOperations()
|
||||
super.cancel()
|
||||
|
||||
didFinish()
|
||||
|
||||
// Operation should silently cancel.
|
||||
operationQueue.cancelAllOperations()
|
||||
addCompletionHandler = nil
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
operationQueue.isSuspended = false
|
||||
}
|
||||
|
||||
|
||||
private var feedResourceId: FeedlyFeedResourceId?
|
||||
|
||||
func feedlySearchOperation(_ operation: FeedlySearchOperation, didGet response: FeedlyFeedsSearchResponse) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
return
|
||||
}
|
||||
guard let first = response.results.first else {
|
||||
@ -91,24 +86,24 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
self.operationQueue.addOperation(addRequest)
|
||||
|
||||
let createFeeds = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: addRequest, log: log)
|
||||
createFeeds.addDependency(addRequest)
|
||||
operationQueue.make(createFeeds, dependOn: addRequest)
|
||||
createFeeds.downloadProgress = downloadProgress
|
||||
self.operationQueue.addOperation(createFeeds)
|
||||
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: syncUnreadIdsService, database: database, newerThan: nil, log: log)
|
||||
syncUnread.addDependency(createFeeds)
|
||||
operationQueue.make(syncUnread, dependOn: createFeeds)
|
||||
syncUnread.downloadProgress = downloadProgress
|
||||
self.operationQueue.addOperation(syncUnread)
|
||||
|
||||
let syncFeed = FeedlySyncStreamContentsOperation(account: account, resource: feedResourceId, service: getStreamContentsService, newerThan: nil, log: log)
|
||||
syncFeed.addDependency(syncUnread)
|
||||
operationQueue.make(syncFeed, dependOn: syncUnread)
|
||||
syncFeed.downloadProgress = downloadProgress
|
||||
self.operationQueue.addOperation(syncFeed)
|
||||
|
||||
let finishOperation = FeedlyCheckpointOperation()
|
||||
finishOperation.checkpointDelegate = self
|
||||
finishOperation.downloadProgress = downloadProgress
|
||||
finishOperation.addDependency(syncFeed)
|
||||
operationQueue.make(finishOperation, dependOn: syncFeed)
|
||||
self.operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
@ -120,7 +115,7 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
}
|
||||
|
||||
func feedlyCheckpointOperationDidReachCheckpoint(_ operation: FeedlyCheckpointOperation) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,9 @@ final class FeedlyCheckpointOperation: FeedlyOperation {
|
||||
|
||||
weak var checkpointDelegate: FeedlyCheckpointOperationDelegate?
|
||||
|
||||
override func main() {
|
||||
defer { didFinish() }
|
||||
guard !isCancelled else {
|
||||
return
|
||||
override func run() {
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
checkpointDelegate?.feedlyCheckpointOperationDidReachCheckpoint(self)
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ final class FeedlyCreateFeedsForCollectionFoldersOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
defer { didFinish() }
|
||||
|
||||
guard !isCancelled else { return }
|
||||
override func run() {
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
||||
let pairs = feedsAndFoldersProvider.feedsAndFolders
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
|
||||
class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
private let account: Account
|
||||
@ -15,13 +16,12 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
private let missingArticleEntryIdProvider: FeedlyEntryIdentifierProviding
|
||||
private let updatedArticleEntryIdProvider: FeedlyEntryIdentifierProviding
|
||||
private let getEntriesService: FeedlyGetEntriesService
|
||||
private let operationQueue: OperationQueue
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
private let finishOperation: FeedlyCheckpointOperation
|
||||
|
||||
init(account: Account, missingArticleEntryIdProvider: FeedlyEntryIdentifierProviding, updatedArticleEntryIdProvider: FeedlyEntryIdentifierProviding, getEntriesService: FeedlyGetEntriesService, log: OSLog) {
|
||||
self.account = account
|
||||
self.operationQueue = OperationQueue()
|
||||
self.operationQueue.isSuspended = true
|
||||
self.operationQueue.suspend()
|
||||
self.missingArticleEntryIdProvider = missingArticleEntryIdProvider
|
||||
self.updatedArticleEntryIdProvider = updatedArticleEntryIdProvider
|
||||
self.getEntriesService = getEntriesService
|
||||
@ -35,18 +35,16 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
os_log(.debug, log: log, "Cancelling %{public}@.", self)
|
||||
// TODO: fix error on below line: "Expression type '()' is ambiguous without more context"
|
||||
//os_log(.debug, log: log, "Cancelling %{public}@.", self)
|
||||
operationQueue.cancelAllOperations()
|
||||
super.cancel()
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
// override of cancel calls didFinish().
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
var articleIds = missingArticleEntryIdProvider.entryIds
|
||||
articleIds.formUnion(updatedArticleEntryIdProvider.entryIds)
|
||||
|
||||
@ -64,7 +62,7 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
parsedItemProvider: getEntries,
|
||||
log: log)
|
||||
organiseByFeed.delegate = self
|
||||
organiseByFeed.addDependency(getEntries)
|
||||
self.operationQueue.make(organiseByFeed, dependOn: getEntries)
|
||||
self.operationQueue.addOperation(organiseByFeed)
|
||||
|
||||
let updateAccount = FeedlyUpdateAccountFeedsWithItemsOperation(account: account,
|
||||
@ -72,13 +70,13 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
log: log)
|
||||
|
||||
updateAccount.delegate = self
|
||||
updateAccount.addDependency(organiseByFeed)
|
||||
self.operationQueue.make(updateAccount, dependOn: organiseByFeed)
|
||||
self.operationQueue.addOperation(updateAccount)
|
||||
|
||||
finishOperation.addDependency(updateAccount)
|
||||
|
||||
self.operationQueue.make(finishOperation, dependOn: updateAccount)
|
||||
}
|
||||
|
||||
operationQueue.isSuspended = false
|
||||
operationQueue.resume()
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +91,8 @@ extension FeedlyDownloadArticlesOperation: FeedlyOperationDelegate {
|
||||
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) {
|
||||
assert(Thread.isMainThread)
|
||||
os_log(.debug, log: log, "%{public}@ failed with error: %{public}@.", operation, error as NSError)
|
||||
// TODO: fix error for below line "Error is not convertible to NSError"
|
||||
//os_log(.debug, log: log, "%{public}@ failed with error: %{public}@.", operation, error as NSError)
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,7 @@ final class FeedlyFetchIdsForMissingArticlesOperation: FeedlyOperation, FeedlyEn
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
account.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate { result in
|
||||
switch result {
|
||||
case .success(let articleIds):
|
||||
|
@ -26,11 +26,8 @@ final class FeedlyGetCollectionsOperation: FeedlyOperation, FeedlyCollectionProv
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
os_log(.debug, log: log, "Requesting collections.")
|
||||
|
||||
|
@ -37,12 +37,13 @@ final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, Fe
|
||||
FeedlyEntryParser(entry: $0).parsedItemRepresentation
|
||||
})
|
||||
|
||||
if parsed.count != entries.count {
|
||||
let entryIds = Set(entries.map { $0.id })
|
||||
let parsedIds = Set(parsed.map { $0.uniqueID })
|
||||
let difference = entryIds.subtracting(parsedIds)
|
||||
os_log(.debug, log: log, "%{public}@ dropping articles with ids: %{public}@.", self, difference)
|
||||
}
|
||||
// TODO: Fix the below. There’s an error on the os.log line: "Expression type '()' is ambiguous without more context"
|
||||
// if parsed.count != entries.count {
|
||||
// let entryIds = Set(entries.map { $0.id })
|
||||
// let parsedIds = Set(parsed.map { $0.uniqueID })
|
||||
// let difference = entryIds.subtracting(parsedIds)
|
||||
// os_log(.debug, log: log, "%{public}@ dropping articles with ids: %{public}@.", self, difference)
|
||||
// }
|
||||
|
||||
storedParsedEntries = parsed
|
||||
|
||||
@ -53,11 +54,7 @@ final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, Fe
|
||||
return name ?? String(describing: Self.self)
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
override func run() {
|
||||
|
||||
service.getEntries(for: provider.entryIds) { result in
|
||||
switch result {
|
||||
|
@ -97,11 +97,8 @@ final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProvid
|
||||
self.init(account: account, resource: resourceProvider.resource, service: service, newerThan: newerThan, unreadOnly: unreadOnly, log: log)
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.getStreamContents(for: resourceProvider.resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
|
@ -47,11 +47,8 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
||||
|
||||
weak var streamIdsDelegate: FeedlyGetStreamIdsOperationDelegate?
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
|
@ -39,12 +39,8 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
||||
|
||||
private var storedUpdatedArticleIds = Set<String>()
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
@ -59,7 +55,7 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
@ -37,12 +37,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
@ -51,7 +46,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -75,7 +70,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
|
||||
/// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled.
|
||||
private func removeEntryIdsWithPendingStatus() {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -94,7 +89,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func updateStarredStatuses() {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -111,7 +106,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
func processStarredArticleIDs(_ localStarredArticleIDs: Set<String>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
@ -32,12 +32,7 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
||||
self.init(account: account, resource: all, service: service, log: log)
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
@ -46,7 +41,7 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
@ -38,12 +38,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
@ -52,7 +47,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -76,7 +71,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
|
||||
/// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled.
|
||||
private func removeEntryIdsWithPendingStatus() {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -95,7 +90,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func updateUnreadStatuses() {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@ -112,7 +107,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set<String>) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
@ -24,11 +24,7 @@ final class FeedlyLogoutOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
override func run() {
|
||||
os_log("Requesting logout of %{public}@ account.", "\(account.type)")
|
||||
service.logout(completion: didCompleteLogout(_:))
|
||||
}
|
||||
|
@ -33,10 +33,10 @@ final class FeedlyMirrorCollectionsAsFoldersOperation: FeedlyOperation, FeedlyCo
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
defer { didFinish() }
|
||||
|
||||
guard !isCancelled else { return }
|
||||
override func run() {
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
||||
let localFolders = account.folders ?? Set()
|
||||
let collections = collectionsProvider.collections
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
protocol FeedlyOperationDelegate: class {
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error)
|
||||
@ -15,10 +16,26 @@ protocol FeedlyOperationDelegate: class {
|
||||
|
||||
/// Abstract class common to all the tasks required to ingest content from Feedly into NetNewsWire.
|
||||
/// Each task should try to have a single responsibility so they can be easily composed with others.
|
||||
class FeedlyOperation: Operation {
|
||||
|
||||
class FeedlyOperation: MainThreadOperation {
|
||||
|
||||
weak var delegate: FeedlyOperationDelegate?
|
||||
|
||||
|
||||
// MainThreadOperationDelegate
|
||||
var isCanceled = false {
|
||||
didSet {
|
||||
if isCanceled {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
var id: Int?
|
||||
weak var operationDelegate: MainThreadOperationDelegate?
|
||||
var completionBlock: FeedlyOperation.MainThreadOperationCompletionBlock?
|
||||
var name: String?
|
||||
|
||||
var isExecuting = false
|
||||
var isFinished = false
|
||||
|
||||
var downloadProgress: DownloadProgress? {
|
||||
didSet {
|
||||
guard downloadProgress == nil || !isExecuting else {
|
||||
@ -28,85 +45,29 @@ class FeedlyOperation: Operation {
|
||||
downloadProgress?.addToNumberOfTasksAndRemaining(1)
|
||||
}
|
||||
}
|
||||
|
||||
override var isAsynchronous: Bool {
|
||||
return true
|
||||
|
||||
// Override this. Call super.run() first in the overridden method.
|
||||
func run() {
|
||||
isExecuting = true
|
||||
}
|
||||
|
||||
|
||||
// Called when isCanceled is set to true. Useful to override.
|
||||
func cancel() {
|
||||
didFinish()
|
||||
}
|
||||
|
||||
func didFinish() {
|
||||
assert(Thread.isMainThread)
|
||||
assert(!isFinished, "Finished operation is attempting to finish again.")
|
||||
|
||||
precondition(Thread.isMainThread)
|
||||
isExecuting = false
|
||||
isFinished = true
|
||||
downloadProgress = nil
|
||||
|
||||
updateExecutingAndFinished(false, true)
|
||||
if !isCanceled {
|
||||
operationDelegate?.operationDidComplete(self)
|
||||
}
|
||||
}
|
||||
|
||||
func didFinish(_ error: Error) {
|
||||
assert(Thread.isMainThread)
|
||||
assert(!isFinished, "Finished operation is attempting to finish again.")
|
||||
delegate?.feedlyOperation(self, didFailWith: error)
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
// If the operation never started, disown the download progress.
|
||||
if !isExecuting && !isFinished, downloadProgress != nil {
|
||||
DispatchQueue.main.async {
|
||||
self.downloadProgress = nil
|
||||
}
|
||||
}
|
||||
super.cancel()
|
||||
}
|
||||
|
||||
override func start() {
|
||||
guard !isCancelled else {
|
||||
updateExecutingAndFinished(false, true)
|
||||
|
||||
if downloadProgress != nil {
|
||||
DispatchQueue.main.async {
|
||||
self.downloadProgress = nil
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
updateExecutingAndFinished(true, false)
|
||||
DispatchQueue.main.async {
|
||||
self.main()
|
||||
}
|
||||
}
|
||||
|
||||
override var isExecuting: Bool {
|
||||
return isExecutingOperation
|
||||
}
|
||||
|
||||
override var isFinished: Bool {
|
||||
return isFinishedOperation
|
||||
}
|
||||
|
||||
private var isExecutingOperation = false
|
||||
private var isFinishedOperation = false
|
||||
|
||||
private func updateExecutingAndFinished(_ executing: Bool, _ finished: Bool) {
|
||||
let isExecutingDidChange = executing != isExecutingOperation
|
||||
let isFinishedDidChange = finished != isFinishedOperation
|
||||
|
||||
if isFinishedDidChange {
|
||||
willChangeValue(forKey: #keyPath(isFinished))
|
||||
}
|
||||
if isExecutingDidChange {
|
||||
willChangeValue(forKey: #keyPath(isExecuting))
|
||||
}
|
||||
isExecutingOperation = executing
|
||||
isFinishedOperation = finished
|
||||
|
||||
if isExecutingDidChange {
|
||||
didChangeValue(forKey: #keyPath(isExecuting))
|
||||
}
|
||||
if isFinishedDidChange {
|
||||
didChangeValue(forKey: #keyPath(isFinished))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ final class FeedlyOrganiseParsedItemsByFeedOperation: FeedlyOperation, FeedlyPar
|
||||
}
|
||||
|
||||
var parsedItemsKeyedByFeedId: [String : Set<ParsedItem>] {
|
||||
assert(Thread.isMainThread) // Needs to be on main thread because Feed is a main-thread-only model type.
|
||||
precondition(Thread.isMainThread) // Needs to be on main thread because Feed is a main-thread-only model type.
|
||||
return itemsKeyedByFeedId
|
||||
}
|
||||
|
||||
@ -38,10 +38,11 @@ final class FeedlyOrganiseParsedItemsByFeedOperation: FeedlyOperation, FeedlyPar
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
defer { didFinish() }
|
||||
|
||||
guard !isCancelled else { return }
|
||||
override func run() {
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
super.run()
|
||||
|
||||
let items = parsedItemProvider.parsedEntries
|
||||
var dict = [String: Set<ParsedItem>](minimumCapacity: items.count)
|
||||
@ -57,8 +58,6 @@ final class FeedlyOrganiseParsedItemsByFeedOperation: FeedlyOperation, FeedlyPar
|
||||
}
|
||||
}()
|
||||
dict[key] = value
|
||||
|
||||
guard !isCancelled else { return }
|
||||
}
|
||||
|
||||
os_log(.debug, log: log, "Grouped %i items by %i feeds for %@", items.count, dict.count, parsedItemProvider.parsedItemProviderName)
|
||||
|
@ -23,12 +23,7 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
let refreshToken: Credentials
|
||||
|
||||
do {
|
||||
|
@ -35,10 +35,11 @@ final class FeedlyRequestStreamsOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
defer { didFinish() }
|
||||
|
||||
guard !isCancelled else { return }
|
||||
override func run() {
|
||||
super.run()
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
||||
assert(queueDelegate != nil, "This is not particularly useful unless the `queueDelegate` is non-nil.")
|
||||
|
||||
|
@ -31,12 +31,9 @@ class FeedlySearchOperation: FeedlyOperation {
|
||||
self.searchService = service
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
searchService.getFeeds(for: query, count: 1, locale: locale.identifier) { result in
|
||||
switch result {
|
||||
case .success(let response):
|
||||
|
@ -23,15 +23,15 @@ final class FeedlySendArticleStatusesOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
os_log(.debug, log: log, "Sending article statuses...")
|
||||
|
||||
database.selectForProcessing { result in
|
||||
if self.isCanceled {
|
||||
self.didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let syncStatuses):
|
||||
self.processStatuses(syncStatuses)
|
||||
|
@ -10,10 +10,11 @@ import Foundation
|
||||
import os.log
|
||||
import SyncDatabase
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
/// Single responsibility is to compose the operations necessary to get the entire set of articles, feeds and folders with the statuses the user expects between now and a certain date in the past.
|
||||
final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
private let operationQueue: OperationQueue
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
private let log: OSLog
|
||||
let syncUUID: UUID
|
||||
|
||||
@ -34,8 +35,7 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
init(account: Account, credentials: Credentials, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIdsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIdsService, getStreamIdsService: FeedlyGetStreamIdsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress, log: OSLog) {
|
||||
self.syncUUID = UUID()
|
||||
self.log = log
|
||||
self.operationQueue = OperationQueue()
|
||||
self.operationQueue.isSuspended = true
|
||||
self.operationQueue.suspend()
|
||||
|
||||
super.init()
|
||||
|
||||
@ -51,31 +51,31 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
let getCollections = FeedlyGetCollectionsOperation(service: getCollectionsService, log: log)
|
||||
getCollections.delegate = self
|
||||
getCollections.downloadProgress = downloadProgress
|
||||
getCollections.addDependency(sendArticleStatuses)
|
||||
self.operationQueue.make(getCollections, dependOn: sendArticleStatuses)
|
||||
self.operationQueue.addOperation(getCollections)
|
||||
|
||||
// Ensure a folder exists for each Collection, removing Folders without a corresponding Collection.
|
||||
let mirrorCollectionsAsFolders = FeedlyMirrorCollectionsAsFoldersOperation(account: account, collectionsProvider: getCollections, log: log)
|
||||
mirrorCollectionsAsFolders.delegate = self
|
||||
mirrorCollectionsAsFolders.addDependency(getCollections)
|
||||
self.operationQueue.make(mirrorCollectionsAsFolders, dependOn: getCollections)
|
||||
self.operationQueue.addOperation(mirrorCollectionsAsFolders)
|
||||
|
||||
// Ensure feeds are created and grouped by their folders.
|
||||
let createFeedsOperation = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: mirrorCollectionsAsFolders, log: log)
|
||||
createFeedsOperation.delegate = self
|
||||
createFeedsOperation.addDependency(mirrorCollectionsAsFolders)
|
||||
self.operationQueue.make(createFeedsOperation, dependOn: mirrorCollectionsAsFolders)
|
||||
self.operationQueue.addOperation(createFeedsOperation)
|
||||
|
||||
let getAllArticleIds = FeedlyIngestStreamArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, log: log)
|
||||
getAllArticleIds.delegate = self
|
||||
getAllArticleIds.downloadProgress = downloadProgress
|
||||
getAllArticleIds.addDependency(createFeedsOperation)
|
||||
self.operationQueue.make(getAllArticleIds, dependOn: createFeedsOperation)
|
||||
self.operationQueue.addOperation(getAllArticleIds)
|
||||
|
||||
// Get each page of unread article ids in the global.all stream for the last 31 days (nil = Feedly API default).
|
||||
let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: getUnreadService, database: database, newerThan: nil, log: log)
|
||||
getUnread.delegate = self
|
||||
getUnread.addDependency(getAllArticleIds)
|
||||
self.operationQueue.make(getUnread, dependOn: getAllArticleIds)
|
||||
getUnread.downloadProgress = downloadProgress
|
||||
self.operationQueue.addOperation(getUnread)
|
||||
|
||||
@ -84,24 +84,24 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
let getUpdated = FeedlyGetUpdatedArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, newerThan: lastSuccessfulFetchStartDate, log: log)
|
||||
getUpdated.delegate = self
|
||||
getUpdated.downloadProgress = downloadProgress
|
||||
getUpdated.addDependency(createFeedsOperation)
|
||||
self.operationQueue.make(getUpdated, dependOn: createFeedsOperation)
|
||||
self.operationQueue.addOperation(getUpdated)
|
||||
|
||||
// Get each page of the article ids for starred articles.
|
||||
let getStarred = FeedlyIngestStarredArticleIdsOperation(account: account, credentials: credentials, service: getStarredService, database: database, newerThan: nil, log: log)
|
||||
getStarred.delegate = self
|
||||
getStarred.downloadProgress = downloadProgress
|
||||
getStarred.addDependency(createFeedsOperation)
|
||||
self.operationQueue.make(getStarred, dependOn: createFeedsOperation)
|
||||
self.operationQueue.addOperation(getStarred)
|
||||
|
||||
// Now all the possible article ids we need have a status, fetch the article ids for missing articles.
|
||||
let getMissingIds = FeedlyFetchIdsForMissingArticlesOperation(account: account, log: log)
|
||||
getMissingIds.delegate = self
|
||||
getMissingIds.downloadProgress = downloadProgress
|
||||
getMissingIds.addDependency(getAllArticleIds)
|
||||
getMissingIds.addDependency(getUnread)
|
||||
getMissingIds.addDependency(getStarred)
|
||||
getMissingIds.addDependency(getUpdated)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getAllArticleIds)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getUnread)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getStarred)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getUpdated)
|
||||
self.operationQueue.addOperation(getMissingIds)
|
||||
|
||||
// Download all the missing and updated articles
|
||||
@ -112,15 +112,15 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
log: log)
|
||||
downloadMissingArticles.delegate = self
|
||||
downloadMissingArticles.downloadProgress = downloadProgress
|
||||
downloadMissingArticles.addDependency(getMissingIds)
|
||||
downloadMissingArticles.addDependency(getUpdated)
|
||||
self.operationQueue.make(downloadMissingArticles, dependOn: getMissingIds)
|
||||
self.operationQueue.make(downloadMissingArticles, dependOn: getUpdated)
|
||||
self.operationQueue.addOperation(downloadMissingArticles)
|
||||
|
||||
// Once this operation's dependencies, their dependencies etc finish, we can finish.
|
||||
let finishOperation = FeedlyCheckpointOperation()
|
||||
finishOperation.checkpointDelegate = self
|
||||
finishOperation.downloadProgress = downloadProgress
|
||||
finishOperation.addDependency(downloadMissingArticles)
|
||||
self.operationQueue.make(finishOperation, dependOn: downloadMissingArticles)
|
||||
self.operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
@ -140,14 +140,10 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
||||
syncCompletionHandler = nil
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
// override of cancel calls didFinish().
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
os_log(.debug, log: log, "Starting sync %{public}@", syncUUID.uuidString)
|
||||
operationQueue.isSuspended = false
|
||||
operationQueue.resume()
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +164,8 @@ extension FeedlySyncAllOperation: FeedlyOperationDelegate {
|
||||
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) {
|
||||
assert(Thread.isMainThread)
|
||||
os_log(.debug, log: log, "%{public}@ failed with error: %{public}@.", operation, error as NSError)
|
||||
// TODO: fix error for below line "Error is not convertible to NSError"
|
||||
//os_log(.debug, log: log, "%{public}@ failed with error: %{public}@.", operation, error as NSError)
|
||||
|
||||
syncCompletionHandler?(.failure(error))
|
||||
syncCompletionHandler = nil
|
||||
|
@ -9,11 +9,12 @@
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSParser
|
||||
import RSCore
|
||||
|
||||
final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlyGetStreamContentsOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let operationQueue: OperationQueue
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
private let service: FeedlyGetStreamContentsService
|
||||
private let newerThan: Date?
|
||||
private let log: OSLog
|
||||
@ -23,8 +24,7 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
self.operationQueue = OperationQueue()
|
||||
self.operationQueue.isSuspended = true
|
||||
self.operationQueue.suspend()
|
||||
self.newerThan = newerThan
|
||||
self.log = log
|
||||
self.finishOperation = FeedlyCheckpointOperation()
|
||||
@ -48,22 +48,17 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func main() {
|
||||
guard !isCancelled else {
|
||||
// override of cancel calls didFinish().
|
||||
return
|
||||
}
|
||||
|
||||
operationQueue.isSuspended = false
|
||||
override func run() {
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
func enqueueOperations(for continuation: String?) {
|
||||
os_log(.debug, log: log, "Requesting page for %@", resource.id)
|
||||
let operations = pageOperations(for: continuation)
|
||||
operationQueue.addOperations(operations, waitUntilFinished: false)
|
||||
operationQueue.addOperations(operations)
|
||||
}
|
||||
|
||||
func pageOperations(for continuation: String?) -> [Operation] {
|
||||
func pageOperations(for continuation: String?) -> [MainThreadOperation] {
|
||||
let getPage = FeedlyGetStreamContentsOperation(account: account,
|
||||
resource: resource,
|
||||
service: service,
|
||||
@ -82,20 +77,20 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
||||
|
||||
getPage.delegate = self
|
||||
getPage.streamDelegate = self
|
||||
|
||||
organiseByFeed.addDependency(getPage)
|
||||
|
||||
operationQueue.make(organiseByFeed, dependOn: getPage)
|
||||
organiseByFeed.delegate = self
|
||||
|
||||
updateAccount.addDependency(organiseByFeed)
|
||||
|
||||
operationQueue.make(updateAccount, dependOn: organiseByFeed)
|
||||
updateAccount.delegate = self
|
||||
|
||||
finishOperation.addDependency(updateAccount)
|
||||
|
||||
|
||||
operationQueue.make(finishOperation, dependOn: updateAccount)
|
||||
|
||||
return [getPage, organiseByFeed, updateAccount]
|
||||
}
|
||||
|
||||
func feedlyGetStreamContentsOperation(_ operation: FeedlyGetStreamContentsOperation, didGetContentsOf stream: FeedlyStream) {
|
||||
guard !isCancelled else {
|
||||
guard !isCanceled else {
|
||||
os_log(.debug, log: log, "Cancelled requesting page for %@", resource.id)
|
||||
return
|
||||
}
|
||||
|
@ -22,13 +22,7 @@ final class FeedlyUpdateAccountFeedsWithItemsOperation: FeedlyOperation {
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func main() {
|
||||
precondition(Thread.isMainThread) // Needs to be on main thread because Feed is a main-thread-only model type.
|
||||
guard !isCancelled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
override func run() {
|
||||
let webFeedIDsAndItems = organisedItemsProvider.parsedItemsKeyedByFeedId
|
||||
|
||||
account.update(webFeedIDsAndItems: webFeedIDsAndItems, defaultRead: true) { databaseError in
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c6638e4d4282f41e1a3eddced6c2ae822fb34613
|
||||
Subproject commit 3a2d030e8237bdb6ebbd6c389358aaae34d2d3b0
|
Loading…
x
Reference in New Issue
Block a user