Convert update methods to async await.
This commit is contained in:
parent
3f2db0ef12
commit
a88d57952e
@ -784,58 +784,36 @@ public enum FetchType {
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func update(_ feed: Feed, with parsedFeed: ParsedFeed) async throws -> ArticleChanges {
|
||||
func update(feed: Feed, with parsedFeed: ParsedFeed) async throws -> ArticleChanges {
|
||||
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
self.update(feed, with: parsedFeed) { result in
|
||||
switch result {
|
||||
case .success(let articleChanges):
|
||||
continuation.resume(returning: articleChanges)
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func update(_ feed: Feed, with parsedFeed: ParsedFeed, _ completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
// Used only by an On My Mac or iCloud account.
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type == .onMyMac || type == .cloudKit)
|
||||
|
||||
feed.takeSettings(from: parsedFeed)
|
||||
|
||||
let parsedItems = parsedFeed.items
|
||||
guard !parsedItems.isEmpty else {
|
||||
completion(.success(ArticleChanges()))
|
||||
return
|
||||
if parsedItems.isEmpty {
|
||||
return ArticleChanges()
|
||||
}
|
||||
|
||||
update(feed.feedID, with: parsedItems, completion: completion)
|
||||
return try await update(feedID: feed.feedID, with: parsedItems)
|
||||
}
|
||||
|
||||
func update(_ feedID: String, with parsedItems: Set<ParsedItem>, deleteOlder: Bool = true, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
// Used only by an On My Mac or iCloud account.
|
||||
func update(feedID: String, with parsedItems: Set<ParsedItem>, deleteOlder: Bool = true) async throws -> ArticleChanges {
|
||||
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type == .onMyMac || type == .cloudKit)
|
||||
|
||||
database.update(with: parsedItems, feedID: feedID, deleteOlder: deleteOlder) { updateArticlesResult in
|
||||
|
||||
MainActor.assumeIsolated {
|
||||
switch updateArticlesResult {
|
||||
case .success(let articleChanges):
|
||||
let articleChanges = try await database.update(parsedItems: parsedItems, feedID: feedID, deleteOlder: deleteOlder)
|
||||
self.sendNotificationAbout(articleChanges)
|
||||
completion(.success(articleChanges))
|
||||
case .failure(let databaseError):
|
||||
completion(.failure(databaseError))
|
||||
}
|
||||
}
|
||||
}
|
||||
return articleChanges
|
||||
}
|
||||
|
||||
func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping DatabaseCompletionBlock) {
|
||||
// Used only by syncing systems.
|
||||
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type != .onMyMac && type != .cloudKit)
|
||||
|
||||
guard !feedIDsAndItems.isEmpty else {
|
||||
completion(nil)
|
||||
return
|
||||
|
@ -849,11 +849,12 @@ private extension CloudKitAccountDelegate {
|
||||
InitialFeedDownloader.download(url) { parsedFeed in
|
||||
self.refreshProgress.completeTask()
|
||||
|
||||
if let parsedFeed = parsedFeed {
|
||||
account.update(feed, with: parsedFeed) { result in
|
||||
MainActor.assumeIsolated {
|
||||
switch result {
|
||||
case .success:
|
||||
if let parsedFeed {
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
try await account.update(feed: feed, with: parsedFeed)
|
||||
|
||||
self.accountZone.createFeed(url: bestFeedSpecifier.urlString,
|
||||
name: parsedFeed.title,
|
||||
@ -874,20 +875,17 @@ private extension CloudKitAccountDelegate {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
} catch {
|
||||
container.removeFeed(feed)
|
||||
self.refreshProgress.completeTasks(3)
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.refreshProgress.completeTasks(3)
|
||||
container.removeFeed(feed)
|
||||
completion(.failure(AccountError.createErrorNotFound))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case .failure:
|
||||
|
@ -139,14 +139,15 @@ private extension CloudKitArticlesZoneDelegate {
|
||||
let parsedItems = records.compactMap { self.makeParsedItem($0) }
|
||||
let feedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
Task { @MainActor in
|
||||
for (feedID, parsedItems) in feedIDsAndItems {
|
||||
group.enter()
|
||||
self.account?.update(feedID, with: parsedItems, deleteOlder: false) { result in
|
||||
Task { @MainActor in
|
||||
switch result {
|
||||
case .success(let articleChanges):
|
||||
guard let deletes = articleChanges.deletedArticles, !deletes.isEmpty else {
|
||||
|
||||
do {
|
||||
|
||||
let articleChanges = try await self.account?.update(feedID: feedID, with: parsedItems, deleteOlder: false)
|
||||
|
||||
guard let deletes = articleChanges?.deletedArticles, !deletes.isEmpty else {
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
@ -154,16 +155,15 @@ private extension CloudKitArticlesZoneDelegate {
|
||||
let syncStatuses = deletes.map { SyncStatus(articleID: $0.articleID, key: .deleted, flag: true) }
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
group.leave()
|
||||
case .failure(let databaseError):
|
||||
|
||||
} catch {
|
||||
errorOccurred = true
|
||||
os_log(.error, log: self.log, "Error occurred while storing articles: %@", databaseError.localizedDescription)
|
||||
os_log(.error, log: self.log, "Error occurred while storing articles: %@", error.localizedDescription)
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
if errorOccurred {
|
||||
|
@ -227,7 +227,7 @@ private extension LocalAccountDelegate {
|
||||
feed.editedName = editedName
|
||||
container.addFeed(feed)
|
||||
|
||||
try await account.update(feed, with: parsedFeed)
|
||||
try await account.update(feed: feed, with: parsedFeed)
|
||||
|
||||
return feed
|
||||
}
|
||||
|
@ -109,25 +109,27 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
account.update(feed, with: parsedFeed) { result in
|
||||
MainActor.assumeIsolated {
|
||||
if case .success(let articleChanges) = result {
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
let articleChanges = try await account.update(feed: feed, with: parsedFeed)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse {
|
||||
feed.conditionalGetInfo = HTTPConditionalGetInfo(urlResponse: httpResponse)
|
||||
}
|
||||
feed.contentHash = dataHash
|
||||
|
||||
self.delegate?.localAccountRefresher(self, requestCompletedFor: feed)
|
||||
self.delegate?.localAccountRefresher(self, articleChanges: articleChanges) {
|
||||
completion()
|
||||
}
|
||||
} else {
|
||||
|
||||
} catch {
|
||||
completion()
|
||||
self.delegate?.localAccountRefresher(self, requestCompletedFor: feed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData data: Data, representedObject: AnyObject) -> Bool {
|
||||
|
@ -14,7 +14,7 @@ import Parser
|
||||
|
||||
public typealias UnreadCountDictionary = [String: Int] // feedID: unreadCount
|
||||
|
||||
public struct ArticleChanges {
|
||||
public struct ArticleChanges: Sendable {
|
||||
public let newArticles: Set<Article>?
|
||||
public let updatedArticles: Set<Article>?
|
||||
public let deletedArticles: Set<Article>?
|
||||
|
@ -25,17 +25,17 @@ public extension ArticlesDatabase {
|
||||
// MARK: - Saving, Updating, and Deleting Articles
|
||||
|
||||
/// Update articles and save new ones — for feed-based systems (local and iCloud).
|
||||
nonisolated func update(with parsedItems: Set<ParsedItem>, feedID: String, deleteOlder: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
|
||||
Task {
|
||||
do {
|
||||
let articleChanges = try await update(parsedItems: parsedItems, feedID: feedID, deleteOlder: deleteOlder)
|
||||
callUpdateArticlesCompletion(completion, .success(articleChanges))
|
||||
} catch {
|
||||
callUpdateArticlesCompletion(completion, .failure(.suspended))
|
||||
}
|
||||
}
|
||||
}
|
||||
// nonisolated func update(with parsedItems: Set<ParsedItem>, feedID: String, deleteOlder: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
//
|
||||
// Task {
|
||||
// do {
|
||||
// let articleChanges = try await update(parsedItems: parsedItems, feedID: feedID, deleteOlder: deleteOlder)
|
||||
// callUpdateArticlesCompletion(completion, .success(articleChanges))
|
||||
// } catch {
|
||||
// callUpdateArticlesCompletion(completion, .failure(.suspended))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Update articles and save new ones — for sync systems (Feedbin, Feedly, etc.).
|
||||
nonisolated func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user