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