Convert methods to async await.

This commit is contained in:
Brent Simmons 2024-04-23 20:48:06 -07:00
parent a56ffa9405
commit c2197ac854
7 changed files with 133 additions and 239 deletions

View File

@ -422,18 +422,9 @@ 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))
}
}
@MainActor func getStreamIDs(for resource: FeedlyResourceID, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?) async throws -> FeedlyStreamIDs {
guard let accessToken = credentials?.secret else {
return DispatchQueue.main.async {
completion(.failure(CredentialsError.incompleteCredentials))
}
}
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)
addJSONHeaders(&request)
try addOAuthAccessToken(&request)
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))
}
let (_, collections) = try await send(request: request, resultType: FeedlyStreamIDs.self)
guard let collections else {
throw URLError(.cannotDecodeContentData)
}
return collections
}
}

View File

@ -45,78 +45,44 @@ 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):
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 {
removeEntryIDsWithPendingStatus()
try await removeEntryIDsWithPendingStatus()
didFinish()
return
}
getStreamIDs(continuation)
case .failure(let error):
} catch {
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
private func removeEntryIDsWithPendingStatus() async throws {
if let pendingArticleIDs = try await database.selectPendingStarredStatusArticleIDs() {
remoteEntryIDs.subtract(pendingArticleIDs)
}
try await updateStarredStatuses()
}
Task { @MainActor in
private func updateStarredStatuses() async throws {
do {
if let pendingArticleIDs = try await self.database.selectPendingStarredStatusArticleIDs() {
self.remoteEntryIDs.subtract(pendingArticleIDs)
}
self.updateStarredStatuses()
} catch {
self.didFinish(with: error)
}
}
}
private func updateStarredStatuses() {
guard !isCanceled else {
didFinish()
return
}
Task { @MainActor in
do {
if let localStarredArticleIDs = try await account.fetchStarredArticleIDs() {
self.processStarredArticleIDs(localStarredArticleIDs)
}
} catch {
self.didFinish(with: error)
}
try await processStarredArticleIDs(localStarredArticleIDs)
}
}
func processStarredArticleIDs(_ localStarredArticleIDs: Set<String>) {
guard !isCanceled else {
didFinish()
return
}
Task { @MainActor in
func processStarredArticleIDs(_ localStarredArticleIDs: Set<String>) async throws {
var markAsStarredError: Error?
var markAsUnstarredError: Error?
@ -136,10 +102,7 @@ final class FeedlyIngestStarredArticleIDsOperation: FeedlyOperation {
}
if let markingError = markAsStarredError ?? markAsUnstarredError {
self.didFinish(with: markingError)
}
self.didFinish()
throw markingError
}
}
}

View File

@ -41,20 +41,12 @@ 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
do {
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil)
try await account.createStatusesIfNeeded(articleIDs: Set(streamIDs.ids))
guard let continuation = streamIDs.continuation else {
@ -62,15 +54,11 @@ class FeedlyIngestStreamArticleIDsOperation: FeedlyOperation {
self.didFinish()
return
}
self.getStreamIDs(continuation)
} catch {
self.didFinish(with: error)
return
}
}
case .failure(let error):
didFinish(with: error)
}
}
}
}

View File

@ -46,81 +46,47 @@ 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):
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 {
removeEntryIDsWithPendingStatus()
try await removeEntryIDsWithPendingStatus()
didFinish()
return
}
getStreamIDs(continuation)
case .failure(let error):
} catch {
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
private func removeEntryIDsWithPendingStatus() async throws {
if let pendingArticleIDs = try await database.selectPendingReadStatusArticleIDs() {
remoteEntryIDs.subtract(pendingArticleIDs)
}
try await updateUnreadStatuses()
}
Task { @MainActor in
private func updateUnreadStatuses() async throws {
do {
if let pendingArticleIDs = try await self.database.selectPendingReadStatusArticleIDs() {
self.remoteEntryIDs.subtract(pendingArticleIDs)
}
self.updateUnreadStatuses()
} catch {
self.didFinish(with: error)
}
}
}
private func updateUnreadStatuses() {
guard !isCanceled else {
didFinish()
return
}
Task { @MainActor in
do {
if let localUnreadArticleIDs = try await account.fetchUnreadArticleIDs() {
self.processUnreadArticleIDs(localUnreadArticleIDs)
}
} catch {
self.didFinish(with: error)
}
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?
@ -138,10 +104,7 @@ final class FeedlyIngestUnreadArticleIDsOperation: FeedlyOperation {
}
if let markingError = markAsReadError ?? markAsUnreadError {
self.didFinish(with: markingError)
}
self.didFinish()
throw markingError
}
}
}

View File

@ -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)
}

View File

@ -45,25 +45,18 @@ public final class FeedlyGetUpdatedArticleIDsOperation: FeedlyOperation, FeedlyE
}
private func getStreamIDs(_ continuation: String?) {
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
}
service.getStreamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIDs(_:))
}
do {
let streamIDs = try await service.getStreamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil)
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)
didFinish()
@ -72,8 +65,9 @@ public final class FeedlyGetUpdatedArticleIDsOperation: FeedlyOperation, FeedlyE
getStreamIDs(continuation)
case .failure(let error):
} catch {
didFinish(with: error)
}
}
}
}

View File

@ -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
}