Convert methods to async await.
This commit is contained in:
parent
a56ffa9405
commit
c2197ac854
@ -422,19 +422,10 @@ extension FeedlyAPICaller: FeedlyGetStreamContentsService {
|
||||
|
||||
extension FeedlyAPICaller: FeedlyGetStreamIDsService {
|
||||
|
||||
@MainActor func getStreamIDs(for resource: FeedlyResourceID, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ()) {
|
||||
guard !isSuspended else {
|
||||
return DispatchQueue.main.async {
|
||||
completion(.failure(TransportError.suspended))
|
||||
}
|
||||
}
|
||||
|
||||
guard let accessToken = credentials?.secret else {
|
||||
return DispatchQueue.main.async {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor func getStreamIDs(for resource: FeedlyResourceID, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?) async throws -> FeedlyStreamIDs {
|
||||
|
||||
guard !isSuspended else { throw TransportError.suspended }
|
||||
|
||||
var components = baseURLComponents
|
||||
components.path = "/v3/streams/ids"
|
||||
|
||||
@ -469,22 +460,16 @@ extension FeedlyAPICaller: FeedlyGetStreamIDsService {
|
||||
}
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.addValue("application/json", forHTTPHeaderField: HTTPRequestHeader.contentType)
|
||||
request.addValue("application/json", forHTTPHeaderField: "Accept-Type")
|
||||
request.addValue("OAuth \(accessToken)", forHTTPHeaderField: HTTPRequestHeader.authorization)
|
||||
|
||||
send(request: request, resultType: FeedlyStreamIDs.self, dateDecoding: .millisecondsSince1970, keyDecoding: .convertFromSnakeCase) { result in
|
||||
switch result {
|
||||
case .success(let (_, collections)):
|
||||
if let response = collections {
|
||||
completion(.success(response))
|
||||
} else {
|
||||
completion(.failure(URLError(.cannotDecodeContentData)))
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
addJSONHeaders(&request)
|
||||
try addOAuthAccessToken(&request)
|
||||
|
||||
let (_, collections) = try await send(request: request, resultType: FeedlyStreamIDs.self)
|
||||
|
||||
guard let collections else {
|
||||
throw URLError(.cannotDecodeContentData)
|
||||
}
|
||||
|
||||
return collections
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,101 +45,64 @@ final class FeedlyIngestStarredArticleIDsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func getStreamIDs(_ continuation: String?) {
|
||||
service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIDs(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIDs(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let streamIDs):
|
||||
|
||||
remoteEntryIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
removeEntryIDsWithPendingStatus()
|
||||
return
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil)
|
||||
remoteEntryIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
try await removeEntryIDsWithPendingStatus()
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
} catch {
|
||||
didFinish(with: error)
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled.
|
||||
private func removeEntryIDsWithPendingStatus() {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
private func removeEntryIDsWithPendingStatus() async throws {
|
||||
|
||||
do {
|
||||
if let pendingArticleIDs = try await self.database.selectPendingStarredStatusArticleIDs() {
|
||||
self.remoteEntryIDs.subtract(pendingArticleIDs)
|
||||
}
|
||||
self.updateStarredStatuses()
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
if let pendingArticleIDs = try await database.selectPendingStarredStatusArticleIDs() {
|
||||
remoteEntryIDs.subtract(pendingArticleIDs)
|
||||
}
|
||||
try await updateStarredStatuses()
|
||||
}
|
||||
|
||||
private func updateStarredStatuses() {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
private func updateStarredStatuses() async throws {
|
||||
|
||||
do {
|
||||
if let localStarredArticleIDs = try await account.fetchStarredArticleIDs() {
|
||||
self.processStarredArticleIDs(localStarredArticleIDs)
|
||||
}
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
if let localStarredArticleIDs = try await account.fetchStarredArticleIDs() {
|
||||
try await processStarredArticleIDs(localStarredArticleIDs)
|
||||
}
|
||||
}
|
||||
|
||||
func processStarredArticleIDs(_ localStarredArticleIDs: Set<String>) {
|
||||
func processStarredArticleIDs(_ localStarredArticleIDs: Set<String>) async throws {
|
||||
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
var markAsStarredError: Error?
|
||||
var markAsUnstarredError: Error?
|
||||
|
||||
let remoteStarredArticleIDs = remoteEntryIDs
|
||||
do {
|
||||
try await account.markAsStarred(remoteStarredArticleIDs)
|
||||
} catch {
|
||||
markAsStarredError = error
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
let deltaUnstarredArticleIDs = localStarredArticleIDs.subtracting(remoteStarredArticleIDs)
|
||||
do {
|
||||
try await account.markAsUnstarred(deltaUnstarredArticleIDs)
|
||||
} catch {
|
||||
markAsUnstarredError = error
|
||||
}
|
||||
|
||||
var markAsStarredError: Error?
|
||||
var markAsUnstarredError: Error?
|
||||
|
||||
let remoteStarredArticleIDs = remoteEntryIDs
|
||||
do {
|
||||
try await account.markAsStarred(remoteStarredArticleIDs)
|
||||
} catch {
|
||||
markAsStarredError = error
|
||||
}
|
||||
|
||||
let deltaUnstarredArticleIDs = localStarredArticleIDs.subtracting(remoteStarredArticleIDs)
|
||||
do {
|
||||
try await account.markAsUnstarred(deltaUnstarredArticleIDs)
|
||||
} catch {
|
||||
markAsUnstarredError = error
|
||||
}
|
||||
|
||||
if let markingError = markAsStarredError ?? markAsUnstarredError {
|
||||
self.didFinish(with: markingError)
|
||||
}
|
||||
|
||||
self.didFinish()
|
||||
if let markingError = markAsStarredError ?? markAsUnstarredError {
|
||||
throw markingError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,36 +41,24 @@ class FeedlyIngestStreamArticleIDsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func getStreamIDs(_ continuation: String?) {
|
||||
service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIDs(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIDs(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let streamIDs):
|
||||
Task { @MainActor in
|
||||
|
||||
Task { @MainActor in
|
||||
do {
|
||||
try await account.createStatusesIfNeeded(articleIDs: Set(streamIDs.ids))
|
||||
do {
|
||||
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
os_log(.debug, log: self.log, "Reached end of stream for %@", self.resource.id)
|
||||
self.didFinish()
|
||||
return
|
||||
}
|
||||
try await account.createStatusesIfNeeded(articleIDs: Set(streamIDs.ids))
|
||||
|
||||
self.getStreamIDs(continuation)
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
os_log(.debug, log: self.log, "Reached end of stream for %@", self.resource.id)
|
||||
self.didFinish()
|
||||
return
|
||||
}
|
||||
self.getStreamIDs(continuation)
|
||||
|
||||
} catch {
|
||||
didFinish(with: error)
|
||||
}
|
||||
case .failure(let error):
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,102 +46,65 @@ final class FeedlyIngestUnreadArticleIDsOperation: FeedlyOperation {
|
||||
}
|
||||
|
||||
private func getStreamIDs(_ continuation: String?) {
|
||||
service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true, completion: didGetStreamIDs(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIDs(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let streamIDs):
|
||||
|
||||
remoteEntryIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
removeEntryIDsWithPendingStatus()
|
||||
return
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true)
|
||||
remoteEntryIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
try await removeEntryIDsWithPendingStatus()
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
} catch {
|
||||
didFinish(with: error)
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled.
|
||||
private func removeEntryIDsWithPendingStatus() {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
private func removeEntryIDsWithPendingStatus() async throws {
|
||||
|
||||
do {
|
||||
if let pendingArticleIDs = try await self.database.selectPendingReadStatusArticleIDs() {
|
||||
self.remoteEntryIDs.subtract(pendingArticleIDs)
|
||||
}
|
||||
self.updateUnreadStatuses()
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
if let pendingArticleIDs = try await database.selectPendingReadStatusArticleIDs() {
|
||||
remoteEntryIDs.subtract(pendingArticleIDs)
|
||||
}
|
||||
try await updateUnreadStatuses()
|
||||
}
|
||||
|
||||
private func updateUnreadStatuses() {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
private func updateUnreadStatuses() async throws {
|
||||
|
||||
do {
|
||||
if let localUnreadArticleIDs = try await account.fetchUnreadArticleIDs() {
|
||||
self.processUnreadArticleIDs(localUnreadArticleIDs)
|
||||
}
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
if let localUnreadArticleIDs = try await account.fetchUnreadArticleIDs() {
|
||||
try await processUnreadArticleIDs(localUnreadArticleIDs)
|
||||
}
|
||||
}
|
||||
|
||||
private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set<String>) {
|
||||
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set<String>) async throws {
|
||||
|
||||
let remoteUnreadArticleIDs = remoteEntryIDs
|
||||
|
||||
Task { @MainActor in
|
||||
var markAsUnreadError: Error?
|
||||
var markAsReadError: Error?
|
||||
|
||||
var markAsUnreadError: Error?
|
||||
var markAsReadError: Error?
|
||||
do {
|
||||
try await account.markAsUnread(remoteUnreadArticleIDs)
|
||||
} catch {
|
||||
markAsUnreadError = error
|
||||
}
|
||||
|
||||
do {
|
||||
try await account.markAsUnread(remoteUnreadArticleIDs)
|
||||
} catch {
|
||||
markAsUnreadError = error
|
||||
}
|
||||
let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs)
|
||||
do {
|
||||
try await account.markAsRead(articleIDsToMarkRead)
|
||||
} catch {
|
||||
markAsReadError = error
|
||||
}
|
||||
|
||||
let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs)
|
||||
do {
|
||||
try await account.markAsRead(articleIDsToMarkRead)
|
||||
} catch {
|
||||
markAsReadError = error
|
||||
}
|
||||
|
||||
if let markingError = markAsReadError ?? markAsUnreadError {
|
||||
self.didFinish(with: markingError)
|
||||
}
|
||||
|
||||
self.didFinish()
|
||||
if let markingError = markAsReadError ?? markAsUnreadError {
|
||||
throw markingError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import Foundation
|
||||
import os.log
|
||||
|
||||
public protocol FeedlyGetStreamIDsOperationDelegate: AnyObject {
|
||||
|
||||
func feedlyGetStreamIDsOperation(_ operation: FeedlyGetStreamIDsOperation, didGet streamIDs: FeedlyStreamIDs)
|
||||
}
|
||||
|
||||
@ -46,16 +47,15 @@ public final class FeedlyGetStreamIDsOperation: FeedlyOperation, FeedlyEntryIden
|
||||
weak var streamIDsDelegate: FeedlyGetStreamIDsOperationDelegate?
|
||||
|
||||
public override func run() {
|
||||
service.getStreamIDs(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
case .success(let stream):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
let stream = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly)
|
||||
self.streamIDs = stream
|
||||
|
||||
self.streamIDsDelegate?.feedlyGetStreamIDsOperation(self, didGet: stream)
|
||||
|
||||
self.didFinish()
|
||||
|
||||
case .failure(let error):
|
||||
} catch {
|
||||
os_log(.debug, log: self.log, "Unable to get stream ids: %{public}@.", error as NSError)
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
|
@ -45,35 +45,29 @@ public final class FeedlyGetUpdatedArticleIDsOperation: FeedlyOperation, FeedlyE
|
||||
}
|
||||
|
||||
private func getStreamIDs(_ continuation: String?) {
|
||||
guard let date = newerThan else {
|
||||
os_log(.debug, log: log, "No date provided so everything must be new (nothing is updated).")
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
service.getStreamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIDs(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIDs(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let streamIDs):
|
||||
storedUpdatedArticleIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
os_log(.debug, log: log, "%{public}i articles updated since last successful sync start date.", storedUpdatedArticleIDs.count)
|
||||
|
||||
Task { @MainActor in
|
||||
guard let date = newerThan else {
|
||||
os_log(.debug, log: log, "No date provided so everything must be new (nothing is updated).")
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(with: error)
|
||||
|
||||
do {
|
||||
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil)
|
||||
|
||||
storedUpdatedArticleIDs.formUnion(streamIDs.ids)
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
os_log(.debug, log: log, "%{public}i articles updated since last successful sync start date.", storedUpdatedArticleIDs.count)
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
getStreamIDs(continuation)
|
||||
|
||||
} catch {
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,5 +9,6 @@
|
||||
import Foundation
|
||||
|
||||
public protocol FeedlyGetStreamIDsService: AnyObject {
|
||||
func getStreamIDs(for resource: FeedlyResourceID, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ())
|
||||
|
||||
@MainActor func getStreamIDs(for resource: FeedlyResourceID, continuation: String?, newerThan: Date?, unreadOnly: Bool?) async throws -> FeedlyStreamIDs
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user