Merge branch 'ios-candidate' of https://github.com/Ranchero-Software/NetNewsWire into ios-candidate
This commit is contained in:
commit
fd1d84dff8
|
@ -399,7 +399,6 @@
|
|||
9EF1B10623590D61000A486A /* FeedlyGetStreamIdsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedlyGetStreamIdsOperation.swift; sourceTree = "<group>"; };
|
||||
9EF1B10823590E93000A486A /* FeedlyStreamIds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedlyStreamIds.swift; sourceTree = "<group>"; };
|
||||
9EF2602B23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedlyGetUpdatedArticleIdsOperation.swift; sourceTree = "<group>"; };
|
||||
9EF35F79234E830E003AE2AE /* FeedlyCompoundOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedlyCompoundOperation.swift; sourceTree = "<group>"; };
|
||||
D511EEB5202422BB00712EC3 /* Account_project_debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_debug.xcconfig; sourceTree = "<group>"; };
|
||||
D511EEB6202422BB00712EC3 /* Account_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_target.xcconfig; sourceTree = "<group>"; };
|
||||
D511EEB7202422BB00712EC3 /* Account_project_release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_release.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -700,7 +699,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
9E1D1554233431A600F4944C /* FeedlyOperation.swift */,
|
||||
9EF35F79234E830E003AE2AE /* FeedlyCompoundOperation.swift */,
|
||||
9E1D154C233370D800F4944C /* FeedlySyncAllOperation.swift */,
|
||||
9EA643D2239305680018A28C /* FeedlySearchOperation.swift */,
|
||||
9E7299D623505E9600DAEFB7 /* FeedlyAddFeedToCollectionOperation.swift */,
|
||||
9EB1D575238E6A3900A753D7 /* FeedlyAddNewFeedOperation.swift */,
|
||||
|
@ -721,7 +720,6 @@
|
|||
9EEEF7202355277F009E9D80 /* FeedlyIngestStarredArticleIdsOperation.swift */,
|
||||
9E84DC462359A23200D6E809 /* FeedlyIngestUnreadArticleIdsOperation.swift */,
|
||||
9EF2602B23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift */,
|
||||
9E1D154C233370D800F4944C /* FeedlySyncAllOperation.swift */,
|
||||
9E672393236F7CA0000BE141 /* FeedlyRefreshAccessTokenOperation.swift */,
|
||||
9E784EBD237E890600099B1B /* FeedlyLogoutOperation.swift */,
|
||||
9E5DE60D23C3F4B70064DA30 /* FeedlyFetchIdsForMissingArticlesOperation.swift */,
|
||||
|
|
|
@ -12,18 +12,17 @@ import RSWeb
|
|||
import RSCore
|
||||
|
||||
class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
private let operationQueue: MainThreadOperationQueue
|
||||
|
||||
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
var addCompletionHandler: ((Result<Void, Error>) -> ())?
|
||||
|
||||
|
||||
init(account: Account, credentials: Credentials, resource: FeedlyFeedResourceId, service: FeedlyAddFeedToCollectionService, container: Container, progress: DownloadProgress, log: OSLog) throws {
|
||||
|
||||
let validator = FeedlyFeedContainerValidator(container: container)
|
||||
let (folder, collectionId) = try validator.getValidContainer()
|
||||
|
||||
self.operationQueue = MainThreadOperationQueue()
|
||||
self.operationQueue.suspend()
|
||||
|
||||
|
||||
super.init()
|
||||
|
||||
self.downloadProgress = progress
|
||||
|
@ -35,26 +34,24 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate,
|
|||
|
||||
let createFeeds = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: addRequest, log: log)
|
||||
createFeeds.downloadProgress = progress
|
||||
self.operationQueue.make(createFeeds, dependOn: addRequest)
|
||||
createFeeds.addDependency(addRequest)
|
||||
self.operationQueue.addOperation(createFeeds)
|
||||
|
||||
let finishOperation = FeedlyCheckpointOperation()
|
||||
finishOperation.checkpointDelegate = self
|
||||
finishOperation.downloadProgress = progress
|
||||
self.operationQueue.make(finishOperation, dependOn: createFeeds)
|
||||
finishOperation.addDependency(createFeeds)
|
||||
self.operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
operationQueue.cancelAllOperations()
|
||||
super.cancel()
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
override func didCancel() {
|
||||
operationQueue.cancelAllOperations()
|
||||
addCompletionHandler = nil
|
||||
}
|
||||
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) {
|
||||
addCompletionHandler?(.failure(error))
|
||||
|
|
|
@ -13,13 +13,14 @@ protocol FeedlyAddFeedToCollectionService {
|
|||
}
|
||||
|
||||
final class FeedlyAddFeedToCollectionOperation: FeedlyOperation, FeedlyFeedsAndFoldersProviding, FeedlyResourceProviding {
|
||||
|
||||
let feedName: String?
|
||||
let collectionId: String
|
||||
let service: FeedlyAddFeedToCollectionService
|
||||
let account: Account
|
||||
let folder: Folder
|
||||
let feedResource: FeedlyFeedResourceId
|
||||
|
||||
|
||||
init(account: Account, folder: Folder, feedResource: FeedlyFeedResourceId, feedName: String? = nil, collectionId: String, service: FeedlyAddFeedToCollectionService) {
|
||||
self.account = account
|
||||
self.folder = folder
|
||||
|
@ -36,8 +37,6 @@ final class FeedlyAddFeedToCollectionOperation: FeedlyOperation, FeedlyFeedsAndF
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.addFeed(with: feedResource, title: feedName, toCollectionWith: collectionId) { [weak self] result in
|
||||
guard let self = self else {
|
||||
return
|
||||
|
@ -49,8 +48,11 @@ final class FeedlyAddFeedToCollectionOperation: FeedlyOperation, FeedlyFeedsAndF
|
|||
self.didCompleteRequest(result)
|
||||
}
|
||||
}
|
||||
|
||||
private func didCompleteRequest(_ result: Result<[FeedlyFeed], Error>) {
|
||||
}
|
||||
|
||||
private extension FeedlyAddFeedToCollectionOperation {
|
||||
|
||||
func didCompleteRequest(_ result: Result<[FeedlyFeed], Error>) {
|
||||
switch result {
|
||||
case .success(let feedlyFeeds):
|
||||
feedsAndFolders = [(feedlyFeeds, folder)]
|
||||
|
@ -58,13 +60,13 @@ final class FeedlyAddFeedToCollectionOperation: FeedlyOperation, FeedlyFeedsAndF
|
|||
let feedsWithCreatedFeedId = feedlyFeeds.filter { $0.id == resource.id }
|
||||
|
||||
if feedsWithCreatedFeedId.isEmpty {
|
||||
didFinish(AccountError.createErrorNotFound)
|
||||
didFinish(with: AccountError.createErrorNotFound)
|
||||
} else {
|
||||
didFinish()
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import RSWeb
|
|||
import RSCore
|
||||
|
||||
class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlySearchOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
private let operationQueue: MainThreadOperationQueue
|
||||
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
private let folder: Folder
|
||||
private let collectionId: String
|
||||
private let url: String
|
||||
|
@ -25,16 +26,16 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
private let syncUnreadIdsService: FeedlyGetStreamIdsService
|
||||
private let getStreamContentsService: FeedlyGetStreamContentsService
|
||||
private let log: OSLog
|
||||
|
||||
private var feedResourceId: FeedlyFeedResourceId?
|
||||
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)
|
||||
(self.folder, self.collectionId) = try validator.getValidContainer()
|
||||
|
||||
self.url = url
|
||||
self.operationQueue = MainThreadOperationQueue()
|
||||
self.operationQueue.suspend()
|
||||
self.account = account
|
||||
self.credentials = credentials
|
||||
|
@ -44,9 +45,9 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
self.syncUnreadIdsService = syncUnreadIdsService
|
||||
self.getStreamContentsService = getStreamContentsService
|
||||
self.log = log
|
||||
|
||||
|
||||
super.init()
|
||||
|
||||
|
||||
self.downloadProgress = progress
|
||||
|
||||
let search = FeedlySearchOperation(query: url, locale: .current, service: searchService)
|
||||
|
@ -57,24 +58,20 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
super.cancel()
|
||||
override func didCancel() {
|
||||
operationQueue.cancelAllOperations()
|
||||
addCompletionHandler = nil
|
||||
}
|
||||
|
||||
private var feedResourceId: FeedlyFeedResourceId?
|
||||
|
||||
func feedlySearchOperation(_ operation: FeedlySearchOperation, didGet response: FeedlyFeedsSearchResponse) {
|
||||
guard !isCanceled else {
|
||||
return
|
||||
}
|
||||
guard let first = response.results.first else {
|
||||
return didFinish(AccountError.createErrorNotFound)
|
||||
return didFinish(with: AccountError.createErrorNotFound)
|
||||
}
|
||||
|
||||
let feedResourceId = FeedlyFeedResourceId(id: first.feedId)
|
||||
|
@ -86,24 +83,24 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
operationQueue.addOperation(addRequest)
|
||||
|
||||
let createFeeds = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: addRequest, log: log)
|
||||
operationQueue.make(createFeeds, dependOn: addRequest)
|
||||
createFeeds.addDependency(addRequest)
|
||||
createFeeds.downloadProgress = downloadProgress
|
||||
operationQueue.addOperation(createFeeds)
|
||||
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: syncUnreadIdsService, database: database, newerThan: nil, log: log)
|
||||
operationQueue.make(syncUnread, dependOn: createFeeds)
|
||||
syncUnread.addDependency(createFeeds)
|
||||
syncUnread.downloadProgress = downloadProgress
|
||||
operationQueue.addOperation(syncUnread)
|
||||
|
||||
let syncFeed = FeedlySyncStreamContentsOperation(account: account, resource: feedResourceId, service: getStreamContentsService, isPagingEnabled: false, newerThan: nil, log: log)
|
||||
operationQueue.make(syncFeed, dependOn: syncUnread)
|
||||
syncFeed.addDependency(syncUnread)
|
||||
syncFeed.downloadProgress = downloadProgress
|
||||
operationQueue.addOperation(syncFeed)
|
||||
|
||||
let finishOperation = FeedlyCheckpointOperation()
|
||||
finishOperation.checkpointDelegate = self
|
||||
finishOperation.downloadProgress = downloadProgress
|
||||
operationQueue.make(finishOperation, dependOn: syncFeed)
|
||||
finishOperation.addDependency(syncFeed)
|
||||
operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
|
@ -118,7 +115,6 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
guard !isCanceled else {
|
||||
return
|
||||
}
|
||||
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
@ -126,14 +122,12 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
guard let handler = addCompletionHandler else {
|
||||
return
|
||||
}
|
||||
|
||||
if let feedResource = feedResourceId, let feed = folder.existingWebFeed(withWebFeedID: feedResource.id) {
|
||||
handler(.success(feed))
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
handler(.failure(AccountError.createErrorNotFound))
|
||||
}
|
||||
|
||||
addCompletionHandler = nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,12 @@ protocol FeedlyCheckpointOperationDelegate: class {
|
|||
func feedlyCheckpointOperationDidReachCheckpoint(_ operation: FeedlyCheckpointOperation)
|
||||
}
|
||||
|
||||
/// Single responsibility is to let the delegate know an instance is executing. The semantics are up to the delegate.
|
||||
/// Let the delegate know an instance is executing. The semantics are up to the delegate.
|
||||
final class FeedlyCheckpointOperation: FeedlyOperation {
|
||||
|
||||
weak var checkpointDelegate: FeedlyCheckpointOperationDelegate?
|
||||
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ final class FeedlyCreateFeedsForCollectionFoldersOperation: FeedlyOperation {
|
|||
let account: Account
|
||||
let feedsAndFoldersProvider: FeedlyFeedsAndFoldersProviding
|
||||
let log: OSLog
|
||||
|
||||
|
||||
init(account: Account, feedsAndFoldersProvider: FeedlyFeedsAndFoldersProviding, log: OSLog) {
|
||||
self.feedsAndFoldersProvider = feedsAndFoldersProvider
|
||||
self.account = account
|
||||
|
@ -23,7 +23,6 @@ final class FeedlyCreateFeedsForCollectionFoldersOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
||||
|
||||
private let account: Account
|
||||
private let log: OSLog
|
||||
private let missingArticleEntryIdProvider: FeedlyEntryIdentifierProviding
|
||||
|
@ -27,24 +29,12 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
|||
self.getEntriesService = getEntriesService
|
||||
self.finishOperation = FeedlyCheckpointOperation()
|
||||
self.log = log
|
||||
|
||||
super.init()
|
||||
|
||||
self.finishOperation.checkpointDelegate = self
|
||||
self.operationQueue.addOperation(self.finishOperation)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
// 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 run() {
|
||||
super.run()
|
||||
|
||||
var articleIds = missingArticleEntryIdProvider.entryIds
|
||||
articleIds.formUnion(updatedArticleEntryIdProvider.entryIds)
|
||||
|
||||
|
@ -62,7 +52,7 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
|||
parsedItemProvider: getEntries,
|
||||
log: log)
|
||||
organiseByFeed.delegate = self
|
||||
self.operationQueue.make(organiseByFeed, dependOn: getEntries)
|
||||
organiseByFeed.addDependency(getEntries)
|
||||
self.operationQueue.addOperation(organiseByFeed)
|
||||
|
||||
let updateAccount = FeedlyUpdateAccountFeedsWithItemsOperation(account: account,
|
||||
|
@ -70,14 +60,21 @@ class FeedlyDownloadArticlesOperation: FeedlyOperation {
|
|||
log: log)
|
||||
|
||||
updateAccount.delegate = self
|
||||
self.operationQueue.make(updateAccount, dependOn: organiseByFeed)
|
||||
updateAccount.addDependency(organiseByFeed)
|
||||
self.operationQueue.addOperation(updateAccount)
|
||||
|
||||
self.operationQueue.make(finishOperation, dependOn: updateAccount)
|
||||
finishOperation.addDependency(updateAccount)
|
||||
}
|
||||
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
override func didCancel() {
|
||||
// TODO: fix error on below line: "Expression type '()' is ambiguous without more context"
|
||||
//os_log(.debug, log: log, "Cancelling %{public}@.", self)
|
||||
operationQueue.cancelAllOperations()
|
||||
didFinish()
|
||||
}
|
||||
}
|
||||
|
||||
extension FeedlyDownloadArticlesOperation: FeedlyCheckpointOperationDelegate {
|
||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
|||
import os.log
|
||||
|
||||
final class FeedlyFetchIdsForMissingArticlesOperation: FeedlyOperation, FeedlyEntryIdentifierProviding {
|
||||
|
||||
private let account: Account
|
||||
private let log: OSLog
|
||||
|
||||
|
@ -21,7 +22,6 @@ final class FeedlyFetchIdsForMissingArticlesOperation: FeedlyOperation, FeedlyEn
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
account.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate { result in
|
||||
switch result {
|
||||
case .success(let articleIds):
|
||||
|
@ -29,7 +29,7 @@ final class FeedlyFetchIdsForMissingArticlesOperation: FeedlyOperation, FeedlyEn
|
|||
self.didFinish()
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,22 +13,20 @@ protocol FeedlyCollectionProviding: class {
|
|||
var collections: [FeedlyCollection] { get }
|
||||
}
|
||||
|
||||
/// Single responsibility is to get Collections from Feedly.
|
||||
/// Get Collections from Feedly.
|
||||
final class FeedlyGetCollectionsOperation: FeedlyOperation, FeedlyCollectionProviding {
|
||||
|
||||
let service: FeedlyGetCollectionsService
|
||||
let log: OSLog
|
||||
|
||||
private(set) var collections = [FeedlyCollection]()
|
||||
|
||||
|
||||
init(service: FeedlyGetCollectionsService, log: OSLog) {
|
||||
self.service = service
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
os_log(.debug, log: log, "Requesting collections.")
|
||||
|
||||
service.getCollections { result in
|
||||
|
@ -40,7 +38,7 @@ final class FeedlyGetCollectionsOperation: FeedlyOperation, FeedlyCollectionProv
|
|||
|
||||
case .failure(let error):
|
||||
os_log(.debug, log: self.log, "Unable to request collections: %{public}@.", error as NSError)
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import Foundation
|
|||
import os.log
|
||||
import RSParser
|
||||
|
||||
/// Single responsibility is to get full entries for the entry identifiers.
|
||||
/// Get full entries for the entry identifiers.
|
||||
final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, FeedlyParsedItemProviding {
|
||||
|
||||
let account: Account
|
||||
let service: FeedlyGetEntriesService
|
||||
let provider: FeedlyEntryIdentifierProviding
|
||||
let log: OSLog
|
||||
|
||||
|
||||
init(account: Account, service: FeedlyGetEntriesService, provider: FeedlyEntryIdentifierProviding, log: OSLog) {
|
||||
self.account = account
|
||||
self.service = service
|
||||
|
@ -55,8 +56,6 @@ final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, Fe
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.getEntries(for: provider.entryIds) { result in
|
||||
switch result {
|
||||
case .success(let entries):
|
||||
|
@ -65,7 +64,7 @@ final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, Fe
|
|||
|
||||
case .failure(let error):
|
||||
os_log(.debug, log: self.log, "Unable to get entries: %{public}@.", error as NSError)
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ protocol FeedlyGetStreamContentsOperationDelegate: class {
|
|||
func feedlyGetStreamContentsOperation(_ operation: FeedlyGetStreamContentsOperation, didGetContentsOf stream: FeedlyStream)
|
||||
}
|
||||
|
||||
/// Single responsibility is to get the stream content of a Collection from Feedly.
|
||||
/// Get the stream content of a Collection from Feedly.
|
||||
final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProviding, FeedlyParsedItemProviding {
|
||||
|
||||
struct ResourceProvider: FeedlyResourceProviding {
|
||||
|
@ -38,7 +38,7 @@ final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProvid
|
|||
|
||||
var entries: [FeedlyEntry] {
|
||||
guard let entries = stream?.items else {
|
||||
assert(isFinished, "This should only be called when the operation finishes without error.")
|
||||
// assert(isFinished, "This should only be called when the operation finishes without error.")
|
||||
assertionFailure("Has this operation been addeded as a dependency on the caller?")
|
||||
return []
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProvid
|
|||
let log: OSLog
|
||||
|
||||
weak var streamDelegate: FeedlyGetStreamContentsOperationDelegate?
|
||||
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamContentsService, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool? = nil, log: OSLog) {
|
||||
self.account = account
|
||||
self.resourceProvider = ResourceProvider(resource: resource)
|
||||
|
@ -98,8 +98,6 @@ final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProvid
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.getStreamContents(for: resourceProvider.resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
case .success(let stream):
|
||||
|
@ -111,7 +109,7 @@ final class FeedlyGetStreamContentsOperation: FeedlyOperation, FeedlyEntryProvid
|
|||
|
||||
case .failure(let error):
|
||||
os_log(.debug, log: self.log, "Unable to get stream contents: %{public}@.", error as NSError)
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
|||
|
||||
var entryIds: Set<String> {
|
||||
guard let ids = streamIds?.ids else {
|
||||
assert(isFinished, "This should only be called when the operation finishes without error.")
|
||||
assertionFailure("Has this operation been addeded as a dependency on the caller?")
|
||||
return []
|
||||
}
|
||||
|
@ -34,7 +33,7 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
|||
let unreadOnly: Bool?
|
||||
let newerThan: Date?
|
||||
let log: OSLog
|
||||
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, continuation: String? = nil, newerThan: Date? = nil, unreadOnly: Bool?, log: OSLog) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
|
@ -48,8 +47,6 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
|||
weak var streamIdsDelegate: FeedlyGetStreamIdsOperationDelegate?
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
case .success(let stream):
|
||||
|
@ -61,7 +58,7 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
|||
|
||||
case .failure(let error):
|
||||
os_log(.debug, log: self.log, "Unable to get stream ids: %{public}@.", error as NSError)
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import os.log
|
|||
/// Typically, it pages through the article ids of the global.all stream.
|
||||
/// When all the article ids are collected, it is the responsibility of another operation to download them when appropriate.
|
||||
class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifierProviding {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
|
@ -40,7 +41,6 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
|||
private var storedUpdatedArticleIds = Set<String>()
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
|||
getStreamIds(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import Foundation
|
|||
import os.log
|
||||
import SyncDatabase
|
||||
|
||||
/// Single responsibility is to clone locally the remote starred article state.
|
||||
/// Clone locally the remote starred article state.
|
||||
///
|
||||
/// Typically, it pages through the article ids of the global.saved stream.
|
||||
/// When all the article ids are collected, a status is created for each.
|
||||
/// The article ids previously marked as starred but not collected become unstarred.
|
||||
/// So this operation has side effects *for the entire account* it operates on.
|
||||
final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
|
@ -38,7 +39,6 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
getStreamIds(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
self.updateStarredStatuses()
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
self.processStarredArticleIDs(localStarredArticleIDs)
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
self.didFinish()
|
||||
return
|
||||
}
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
import Foundation
|
||||
import os.log
|
||||
|
||||
/// Single responsibility is to ensure a status exists for every article id the user might be interested in.
|
||||
/// Ensure a status exists for every article id the user might be interested in.
|
||||
///
|
||||
/// Typically, it pages through the article ids of the global.all stream.
|
||||
/// As the article ids are collected, a default read status is created for each.
|
||||
/// So this operation has side effects *for the entire account* it operates on.
|
||||
class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
|
@ -33,7 +34,6 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
|||
account.createStatusesIfNeeded(articleIDs: Set(streamIds.ids)) { databaseError in
|
||||
|
||||
if let error = databaseError {
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
|||
self.getStreamIds(continuation)
|
||||
}
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,14 @@ import os.log
|
|||
import RSParser
|
||||
import SyncDatabase
|
||||
|
||||
/// Single responsibility is to clone locally the remote unread article state.
|
||||
/// Clone locally the remote unread article state.
|
||||
///
|
||||
/// Typically, it pages through the unread article ids of the global.all stream.
|
||||
/// When all the unread article ids are collected, a status is created for each.
|
||||
/// The article ids previously marked as unread but not collected become read.
|
||||
/// So this operation has side effects *for the entire account* it operates on.
|
||||
final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
|
@ -39,7 +40,6 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
getStreamIds(nil)
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
getStreamIds(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
self.updateUnreadStatuses()
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
self.processUnreadArticleIDs(localUnreadArticleIDs)
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
self.didFinish()
|
||||
return
|
||||
}
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ protocol FeedlyLogoutService {
|
|||
}
|
||||
|
||||
final class FeedlyLogoutOperation: FeedlyOperation {
|
||||
|
||||
let service: FeedlyLogoutService
|
||||
let account: Account
|
||||
let log: OSLog
|
||||
|
@ -25,7 +26,6 @@ final class FeedlyLogoutOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
os_log("Requesting logout of %{public}@ account.", "\(account.type)")
|
||||
service.logout(completion: didCompleteLogout(_:))
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ final class FeedlyLogoutOperation: FeedlyOperation {
|
|||
|
||||
case .failure(let error):
|
||||
os_log("Logout failed because %{public}@.", error as NSError)
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ protocol FeedlyFeedsAndFoldersProviding {
|
|||
var feedsAndFolders: [([FeedlyFeed], Folder)] { get }
|
||||
}
|
||||
|
||||
/// Single responsibility is accurately reflect Collections from Feedly as Folders.
|
||||
/// Reflect Collections from Feedly as Folders.
|
||||
final class FeedlyMirrorCollectionsAsFoldersOperation: FeedlyOperation, FeedlyCollectionsAndFoldersProviding, FeedlyFeedsAndFoldersProviding {
|
||||
|
||||
let account: Account
|
||||
|
@ -26,7 +26,7 @@ final class FeedlyMirrorCollectionsAsFoldersOperation: FeedlyOperation, FeedlyCo
|
|||
|
||||
private(set) var collectionsAndFolders = [(FeedlyCollection, Folder)]()
|
||||
private(set) var feedsAndFolders = [([FeedlyFeed], Folder)]()
|
||||
|
||||
|
||||
init(account: Account, collectionsProvider: FeedlyCollectionProviding, log: OSLog) {
|
||||
self.collectionsProvider = collectionsProvider
|
||||
self.account = account
|
||||
|
@ -34,7 +34,6 @@ final class FeedlyMirrorCollectionsAsFoldersOperation: FeedlyOperation, FeedlyCo
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
|
|
@ -14,60 +14,47 @@ protocol FeedlyOperationDelegate: class {
|
|||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Abstract base class for Feedly sync operations.
|
||||
///
|
||||
/// Normally we don’t do inheritance — but in this case
|
||||
/// it’s the best option.
|
||||
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 {
|
||||
fatalError("\(\FeedlyOperation.downloadProgress) was set to late. Set before operation starts executing.")
|
||||
}
|
||||
oldValue?.completeTask()
|
||||
downloadProgress?.addToNumberOfTasksAndRemaining(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Override this. Call super.run() first in the overridden method.
|
||||
func run() {
|
||||
isExecuting = true
|
||||
// MainThreadOperation
|
||||
var isCanceled = false {
|
||||
didSet {
|
||||
if isCanceled {
|
||||
didCancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
var id: Int?
|
||||
weak var operationDelegate: MainThreadOperationDelegate?
|
||||
var name: String?
|
||||
var completionBlock: MainThreadOperation.MainThreadOperationCompletionBlock?
|
||||
|
||||
// Called when isCanceled is set to true. Useful to override.
|
||||
func cancel() {
|
||||
didFinish()
|
||||
func run() {
|
||||
}
|
||||
|
||||
func didFinish() {
|
||||
precondition(Thread.isMainThread)
|
||||
isExecuting = false
|
||||
isFinished = true
|
||||
downloadProgress = nil
|
||||
if !isCanceled {
|
||||
operationDelegate?.operationDidComplete(self)
|
||||
}
|
||||
}
|
||||
|
||||
func didFinish(_ error: Error) {
|
||||
|
||||
func didFinish(with error: Error) {
|
||||
delegate?.feedlyOperation(self, didFailWith: error)
|
||||
didFinish()
|
||||
}
|
||||
|
||||
func didCancel() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@ protocol FeedlyParsedItemsByFeedProviding {
|
|||
var parsedItemsKeyedByFeedId: [String: Set<ParsedItem>] { get }
|
||||
}
|
||||
|
||||
/// Single responsibility is to group articles by their feeds.
|
||||
/// Group articles by their feeds.
|
||||
final class FeedlyOrganiseParsedItemsByFeedOperation: FeedlyOperation, FeedlyParsedItemsByFeedProviding {
|
||||
|
||||
private let account: Account
|
||||
private let parsedItemProvider: FeedlyParsedItemProviding
|
||||
private let log: OSLog
|
||||
|
@ -42,8 +43,7 @@ final class FeedlyOrganiseParsedItemsByFeedOperation: FeedlyOperation, FeedlyPar
|
|||
defer {
|
||||
didFinish()
|
||||
}
|
||||
super.run()
|
||||
|
||||
|
||||
let items = parsedItemProvider.parsedEntries
|
||||
var dict = [String: Set<ParsedItem>](minimumCapacity: items.count)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import os.log
|
|||
import RSWeb
|
||||
|
||||
final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
||||
|
||||
let service: OAuthAccessTokenRefreshing
|
||||
let oauthClient: OAuthAuthorizationClient
|
||||
let account: Account
|
||||
|
@ -24,7 +25,6 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
let refreshToken: Credentials
|
||||
|
||||
do {
|
||||
|
@ -36,7 +36,7 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
|||
refreshToken = credentials
|
||||
|
||||
} catch {
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -66,11 +66,11 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
|||
|
||||
didFinish()
|
||||
} catch {
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ protocol FeedlyRequestStreamsOperationDelegate: class {
|
|||
func feedlyRequestStreamsOperation(_ operation: FeedlyRequestStreamsOperation, enqueue collectionStreamOperation: FeedlyGetStreamContentsOperation)
|
||||
}
|
||||
|
||||
/// Single responsibility is to create one stream request operation for one Feedly collection.
|
||||
/// Create one stream request operation for one Feedly collection.
|
||||
/// This is the start of the process of refreshing the entire contents of a Folder.
|
||||
final class FeedlyRequestStreamsOperation: FeedlyOperation {
|
||||
|
||||
|
@ -25,7 +25,7 @@ final class FeedlyRequestStreamsOperation: FeedlyOperation {
|
|||
let log: OSLog
|
||||
let newerThan: Date?
|
||||
let unreadOnly: Bool?
|
||||
|
||||
|
||||
init(account: Account, collectionsProvider: FeedlyCollectionProviding, newerThan: Date?, unreadOnly: Bool?, service: FeedlyGetStreamContentsService, log: OSLog) {
|
||||
self.account = account
|
||||
self.service = service
|
||||
|
@ -36,7 +36,6 @@ final class FeedlyRequestStreamsOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
defer {
|
||||
didFinish()
|
||||
}
|
||||
|
|
|
@ -16,15 +16,15 @@ protocol FeedlySearchOperationDelegate: class {
|
|||
func feedlySearchOperation(_ operation: FeedlySearchOperation, didGet response: FeedlyFeedsSearchResponse)
|
||||
}
|
||||
|
||||
/// Single responsibility is to find one and only one feed for a given query (usually, a URL).
|
||||
/// Find one and only one feed for a given query (usually, a URL).
|
||||
/// What happens when a feed is found for the URL is delegated to the `searchDelegate`.
|
||||
class FeedlySearchOperation: FeedlyOperation {
|
||||
|
||||
let query: String
|
||||
let locale: Locale
|
||||
let searchService: FeedlySearchService
|
||||
|
||||
weak var searchDelegate: FeedlySearchOperationDelegate?
|
||||
|
||||
|
||||
init(query: String, locale: Locale = .current, service: FeedlySearchService) {
|
||||
self.query = query
|
||||
self.locale = locale
|
||||
|
@ -32,8 +32,6 @@ class FeedlySearchOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
|
||||
searchService.getFeeds(for: query, count: 1, locale: locale.identifier) { result in
|
||||
switch result {
|
||||
case .success(let response):
|
||||
|
@ -42,7 +40,7 @@ class FeedlySearchOperation: FeedlyOperation {
|
|||
self.didFinish()
|
||||
|
||||
case .failure(let error):
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ import Articles
|
|||
import SyncDatabase
|
||||
import os.log
|
||||
|
||||
/// Single responsibility is to take changes to statuses of articles locally and apply them to the corresponding the articles remotely.
|
||||
|
||||
/// Take changes to statuses of articles locally and apply them to the corresponding the articles remotely.
|
||||
final class FeedlySendArticleStatusesOperation: FeedlyOperation {
|
||||
|
||||
private let database: SyncDatabase
|
||||
private let log: OSLog
|
||||
private let service: FeedlyMarkArticlesService
|
||||
|
||||
|
||||
init(database: SyncDatabase, service: FeedlyMarkArticlesService, log: OSLog) {
|
||||
self.database = database
|
||||
self.service = service
|
||||
|
@ -24,7 +26,6 @@ final class FeedlySendArticleStatusesOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
os_log(.debug, log: log, "Sending article statuses...")
|
||||
|
||||
database.selectForProcessing { result in
|
||||
|
|
|
@ -12,8 +12,9 @@ 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.
|
||||
/// 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 = MainThreadOperationQueue()
|
||||
private let log: OSLog
|
||||
let syncUUID: UUID
|
||||
|
@ -51,31 +52,31 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
let getCollections = FeedlyGetCollectionsOperation(service: getCollectionsService, log: log)
|
||||
getCollections.delegate = self
|
||||
getCollections.downloadProgress = downloadProgress
|
||||
self.operationQueue.make(getCollections, dependOn: sendArticleStatuses)
|
||||
self.operationQueue.addOperation(getCollections)
|
||||
getCollections.addDependency(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
|
||||
self.operationQueue.make(mirrorCollectionsAsFolders, dependOn: getCollections)
|
||||
mirrorCollectionsAsFolders.addDependency(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
|
||||
self.operationQueue.make(createFeedsOperation, dependOn: mirrorCollectionsAsFolders)
|
||||
createFeedsOperation.addDependency(mirrorCollectionsAsFolders)
|
||||
self.operationQueue.addOperation(createFeedsOperation)
|
||||
|
||||
let getAllArticleIds = FeedlyIngestStreamArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, log: log)
|
||||
getAllArticleIds.delegate = self
|
||||
getAllArticleIds.downloadProgress = downloadProgress
|
||||
self.operationQueue.make(getAllArticleIds, dependOn: createFeedsOperation)
|
||||
getAllArticleIds.addDependency(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
|
||||
self.operationQueue.make(getUnread, dependOn: getAllArticleIds)
|
||||
getUnread.addDependency(getAllArticleIds)
|
||||
getUnread.downloadProgress = downloadProgress
|
||||
self.operationQueue.addOperation(getUnread)
|
||||
|
||||
|
@ -84,24 +85,24 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
let getUpdated = FeedlyGetUpdatedArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, newerThan: lastSuccessfulFetchStartDate, log: log)
|
||||
getUpdated.delegate = self
|
||||
getUpdated.downloadProgress = downloadProgress
|
||||
self.operationQueue.make(getUpdated, dependOn: createFeedsOperation)
|
||||
getUpdated.addDependency(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
|
||||
self.operationQueue.make(getStarred, dependOn: createFeedsOperation)
|
||||
getStarred.addDependency(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
|
||||
self.operationQueue.make(getMissingIds, dependOn: getAllArticleIds)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getUnread)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getStarred)
|
||||
self.operationQueue.make(getMissingIds, dependOn: getUpdated)
|
||||
getMissingIds.addDependency(getAllArticleIds)
|
||||
getMissingIds.addDependency(getUnread)
|
||||
getMissingIds.addDependency(getStarred)
|
||||
getMissingIds.addDependency(getUpdated)
|
||||
self.operationQueue.addOperation(getMissingIds)
|
||||
|
||||
// Download all the missing and updated articles
|
||||
|
@ -112,15 +113,15 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
log: log)
|
||||
downloadMissingArticles.delegate = self
|
||||
downloadMissingArticles.downloadProgress = downloadProgress
|
||||
self.operationQueue.make(downloadMissingArticles, dependOn: getMissingIds)
|
||||
self.operationQueue.make(downloadMissingArticles, dependOn: getUpdated)
|
||||
downloadMissingArticles.addDependency(getMissingIds)
|
||||
downloadMissingArticles.addDependency(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
|
||||
self.operationQueue.make(finishOperation, dependOn: downloadMissingArticles)
|
||||
finishOperation.addDependency(downloadMissingArticles)
|
||||
self.operationQueue.addOperation(finishOperation)
|
||||
}
|
||||
|
||||
|
@ -128,23 +129,16 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
self.init(account: account, credentials: credentials, lastSuccessfulFetchStartDate: lastSuccessfulFetchStartDate, markArticlesService: caller, getUnreadService: caller, getCollectionsService: caller, getStreamContentsService: caller, getStarredService: caller, getStreamIdsService: caller, getEntriesService: caller, database: database, downloadProgress: downloadProgress, log: log)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
os_log(.debug, log: log, "Cancelling sync %{public}@", syncUUID.uuidString)
|
||||
self.operationQueue.cancelAllOperations()
|
||||
|
||||
super.cancel()
|
||||
|
||||
didFinish()
|
||||
|
||||
// Operation should silently cancel.
|
||||
syncCompletionHandler = nil
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
os_log(.debug, log: log, "Starting sync %{public}@", syncUUID.uuidString)
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
override func didCancel() {
|
||||
os_log(.debug, log: log, "Cancelling sync %{public}@", syncUUID.uuidString)
|
||||
self.operationQueue.cancelAllOperations()
|
||||
syncCompletionHandler = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension FeedlySyncAllOperation: FeedlyCheckpointOperationDelegate {
|
||||
|
|
|
@ -10,8 +10,10 @@ import Foundation
|
|||
import os.log
|
||||
import RSParser
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationDelegate, FeedlyGetStreamContentsOperationDelegate, FeedlyCheckpointOperationDelegate {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let operationQueue = MainThreadOperationQueue()
|
||||
|
@ -43,18 +45,15 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
|||
self.init(account: account, resource: all, service: service, isPagingEnabled: true, newerThan: newerThan, log: log)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
os_log(.debug, log: log, "Canceling sync stream contents")
|
||||
operationQueue.cancelAllOperations()
|
||||
super.cancel()
|
||||
didFinish()
|
||||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
operationQueue.resume()
|
||||
}
|
||||
|
||||
|
||||
override func didCancel() {
|
||||
os_log(.debug, log: log, "Canceling sync stream contents")
|
||||
operationQueue.cancelAllOperations()
|
||||
}
|
||||
|
||||
func enqueueOperations(for continuation: String?) {
|
||||
os_log(.debug, log: log, "Requesting page for %@", resource.id)
|
||||
let operations = pageOperations(for: continuation)
|
||||
|
@ -70,24 +69,20 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
|||
log: log)
|
||||
|
||||
|
||||
let organiseByFeed = FeedlyOrganiseParsedItemsByFeedOperation(account: account,
|
||||
parsedItemProvider: getPage,
|
||||
log: log)
|
||||
let organiseByFeed = FeedlyOrganiseParsedItemsByFeedOperation(account: account, parsedItemProvider: getPage, log: log)
|
||||
|
||||
let updateAccount = FeedlyUpdateAccountFeedsWithItemsOperation(account: account,
|
||||
organisedItemsProvider: organiseByFeed,
|
||||
log: log)
|
||||
let updateAccount = FeedlyUpdateAccountFeedsWithItemsOperation(account: account, organisedItemsProvider: organiseByFeed, log: log)
|
||||
|
||||
getPage.delegate = self
|
||||
getPage.streamDelegate = self
|
||||
|
||||
operationQueue.make(organiseByFeed, dependOn: getPage)
|
||||
organiseByFeed.addDependency(getPage)
|
||||
organiseByFeed.delegate = self
|
||||
|
||||
operationQueue.make(updateAccount, dependOn: organiseByFeed)
|
||||
updateAccount.addDependency(organiseByFeed)
|
||||
updateAccount.delegate = self
|
||||
|
||||
operationQueue.make(finishOperation, dependOn: updateAccount)
|
||||
finishOperation.addDependency(updateAccount)
|
||||
|
||||
return [getPage, organiseByFeed, updateAccount]
|
||||
}
|
||||
|
@ -115,6 +110,6 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
|||
|
||||
func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) {
|
||||
operationQueue.cancelAllOperations()
|
||||
didFinish(error)
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,13 @@ import Foundation
|
|||
import RSParser
|
||||
import os.log
|
||||
|
||||
/// Single responsibility is to combine the articles with their feeds for a specific account.
|
||||
/// Combine the articles with their feeds for a specific account.
|
||||
final class FeedlyUpdateAccountFeedsWithItemsOperation: FeedlyOperation {
|
||||
|
||||
private let account: Account
|
||||
private let organisedItemsProvider: FeedlyParsedItemsByFeedProviding
|
||||
private let log: OSLog
|
||||
|
||||
|
||||
init(account: Account, organisedItemsProvider: FeedlyParsedItemsByFeedProviding, log: OSLog) {
|
||||
self.account = account
|
||||
self.organisedItemsProvider = organisedItemsProvider
|
||||
|
@ -23,12 +24,11 @@ final class FeedlyUpdateAccountFeedsWithItemsOperation: FeedlyOperation {
|
|||
}
|
||||
|
||||
override func run() {
|
||||
super.run()
|
||||
let webFeedIDsAndItems = organisedItemsProvider.parsedItemsKeyedByFeedId
|
||||
|
||||
account.update(webFeedIDsAndItems: webFeedIDsAndItems, defaultRead: true) { databaseError in
|
||||
if let error = databaseError {
|
||||
self.didFinish(error)
|
||||
self.didFinish(with: error)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue