Convert account.update to async await.
This commit is contained in:
parent
a88d57952e
commit
9f67b3f498
@ -809,56 +809,34 @@ public enum FetchType {
|
||||
return articleChanges
|
||||
}
|
||||
|
||||
func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping DatabaseCompletionBlock) {
|
||||
func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool) async throws {
|
||||
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type != .onMyMac && type != .cloudKit)
|
||||
|
||||
guard !feedIDsAndItems.isEmpty else {
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
|
||||
database.update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead) { updateArticlesResult in
|
||||
|
||||
MainActor.assumeIsolated {
|
||||
switch updateArticlesResult {
|
||||
case .success(let newAndUpdatedArticles):
|
||||
self.sendNotificationAbout(newAndUpdatedArticles)
|
||||
completion(nil)
|
||||
case .failure(let databaseError):
|
||||
completion(databaseError)
|
||||
}
|
||||
}
|
||||
}
|
||||
let articleChanges = try await database.update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead)
|
||||
sendNotificationAbout(articleChanges)
|
||||
}
|
||||
|
||||
func update(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleSetResultBlock) {
|
||||
func update(articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) async throws -> Set<Article> {
|
||||
|
||||
// Returns set of Articles whose statuses did change.
|
||||
// Return set of Articles whose statuses did change.
|
||||
|
||||
guard !articles.isEmpty else {
|
||||
completion(.success(Set<Article>()))
|
||||
return
|
||||
if articles.isEmpty {
|
||||
return Set<Article>()
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
let updatedStatuses = try await database.mark(articles: articles, statusKey: statusKey, flag: flag) ?? Set<ArticleStatus>()
|
||||
|
||||
do {
|
||||
var updatedArticles = Set<Article>()
|
||||
let updatedArticleIDs = updatedStatuses.articleIDs()
|
||||
let updatedArticles = Set(articles.filter{ updatedArticleIDs.contains($0.articleID) })
|
||||
self.noteStatusesForArticlesDidChange(updatedArticles)
|
||||
|
||||
if let updatedStatuses = try await database.mark(articles: articles, statusKey: statusKey, flag: flag) {
|
||||
let updatedArticleIDs = updatedStatuses.articleIDs()
|
||||
updatedArticles = Set(articles.filter{ updatedArticleIDs.contains($0.articleID) })
|
||||
self.noteStatusesForArticlesDidChange(updatedArticles)
|
||||
}
|
||||
|
||||
completion(.success(updatedArticles))
|
||||
|
||||
} catch {
|
||||
completion(.failure(.suspended))
|
||||
}
|
||||
}
|
||||
return updatedArticles
|
||||
}
|
||||
|
||||
/// Make sure statuses exist. Any existing statuses won’t be touched.
|
||||
|
@ -616,21 +616,25 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||
}
|
||||
|
||||
private func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
|
||||
let articles = try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account, showProgress: false) { _ in }
|
||||
}
|
||||
completion(.success(()))
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account, showProgress: false) { _ in }
|
||||
}
|
||||
case .failure(let error):
|
||||
|
||||
completion(.success(()))
|
||||
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
@ -751,23 +751,25 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||
}
|
||||
|
||||
private func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
|
||||
let articles = try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
completion(.success(()))
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
completion(.success(()))
|
||||
|
||||
case .failure(let error):
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
@ -1467,13 +1469,22 @@ private extension FeedbinAccountDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func processEntries(account: Account, entries: [FeedbinEntry]?, completion: @escaping DatabaseCompletionBlock) {
|
||||
|
||||
let parsedItems = mapEntriesToParsedItems(entries: entries)
|
||||
let feedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) }
|
||||
account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true, completion: completion)
|
||||
|
||||
Task { @MainActor in
|
||||
do {
|
||||
try await account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true)
|
||||
completion(nil)
|
||||
} catch {
|
||||
completion(.suspended)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func mapEntriesToParsedItems(entries: [FeedbinEntry]?) -> Set<ParsedItem> {
|
||||
guard let entries = entries else {
|
||||
return Set<ParsedItem>()
|
||||
|
@ -730,23 +730,25 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
}
|
||||
|
||||
private func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
|
||||
let articles = try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
completion(.success(()))
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.success(()))
|
||||
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
@ -19,23 +19,25 @@ final class FeedlyUpdateAccountFeedsWithItemsOperation: FeedlyOperation {
|
||||
private let log: OSLog
|
||||
|
||||
init(account: Account, organisedItemsProvider: FeedlyParsedItemsByFeedProviding, log: OSLog) {
|
||||
|
||||
self.account = account
|
||||
self.organisedItemsProvider = organisedItemsProvider
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func run() {
|
||||
|
||||
let feedIDsAndItems = organisedItemsProvider.parsedItemsKeyedByFeedId
|
||||
|
||||
account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true) { databaseError in
|
||||
MainActor.assumeIsolated {
|
||||
if let error = databaseError {
|
||||
self.didFinish(with: error)
|
||||
return
|
||||
}
|
||||
Task { @MainActor in
|
||||
do {
|
||||
|
||||
try await account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true)
|
||||
os_log(.debug, log: self.log, "Updated %i feeds for \"%@\"", feedIDsAndItems.count, self.organisedItemsProvider.parsedItemsByFeedProviderName)
|
||||
self.didFinish()
|
||||
|
||||
} catch {
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,16 +142,7 @@ final class LocalAccountDelegate: AccountDelegate {
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) async throws {
|
||||
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
continuation.resume()
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
|
@ -368,6 +368,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
||||
}
|
||||
|
||||
func processStories(account: Account, stories: [NewsBlurStory]?, since: Date? = nil, completion: @escaping (Result<Bool, DatabaseError>) -> Void) {
|
||||
|
||||
let parsedItems = mapStoriesToParsedItems(stories: stories).filter {
|
||||
guard let datePublished = $0.datePublished, let since = since else {
|
||||
return true
|
||||
@ -379,13 +380,13 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
||||
Set($0)
|
||||
}
|
||||
|
||||
account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true) { error in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
return
|
||||
Task { @MainActor in
|
||||
do {
|
||||
try await account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true)
|
||||
completion(.success(!feedIDsAndItems.isEmpty))
|
||||
} catch {
|
||||
completion(.failure(.suspended))
|
||||
}
|
||||
|
||||
completion(.success(!feedIDsAndItems.isEmpty))
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,23 +789,25 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
||||
}
|
||||
|
||||
private func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
|
||||
let articles = try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
completion(.success(()))
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.success(()))
|
||||
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
@ -803,25 +803,25 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
||||
}
|
||||
|
||||
private func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
|
||||
Task { @MainActor in
|
||||
|
||||
do {
|
||||
let articles = try await account.update(articles: articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
try? await self.database.insertStatuses(syncStatuses)
|
||||
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
|
||||
completion(.success(()))
|
||||
if let count = try? await self.database.selectPendingCount(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
completion(.success(()))
|
||||
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
@ -1246,9 +1246,12 @@ private extension ReaderAPIAccountDelegate {
|
||||
}
|
||||
|
||||
func processEntries(account: Account, entries: [ReaderAPIEntry]?, completion: @escaping VoidCompletionBlock) {
|
||||
|
||||
let parsedItems = mapEntriesToParsedItems(account: account, entries: entries)
|
||||
let feedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) }
|
||||
account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true) { _ in
|
||||
|
||||
Task { @MainActor in
|
||||
try? await account.update(feedIDsAndItems: feedIDsAndItems, defaultRead: true)
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
@ -38,17 +38,17 @@ public extension ArticlesDatabase {
|
||||
// }
|
||||
|
||||
/// Update articles and save new ones — for sync systems (Feedbin, Feedly, etc.).
|
||||
nonisolated func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
|
||||
Task {
|
||||
do {
|
||||
let articleChanges = try await update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead)
|
||||
callUpdateArticlesCompletion(completion, .success(articleChanges))
|
||||
} catch {
|
||||
callUpdateArticlesCompletion(completion, .failure(.suspended))
|
||||
}
|
||||
}
|
||||
}
|
||||
// nonisolated func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
//
|
||||
// Task {
|
||||
// do {
|
||||
// let articleChanges = try await update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead)
|
||||
// callUpdateArticlesCompletion(completion, .success(articleChanges))
|
||||
// } catch {
|
||||
// callUpdateArticlesCompletion(completion, .failure(.suspended))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
nonisolated private func callUpdateArticlesCompletion(_ completion: @escaping UpdateArticlesCompletionBlock, _ result: UpdateArticlesResult) {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user