Make status marking asynchronous.
This commit is contained in:
parent
fa08b7d2e0
commit
ec66c08f9a
@ -520,8 +520,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
addOPMLItems(OPMLNormalizer.normalize(items))
|
||||
}
|
||||
|
||||
public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
return delegate.markArticles(for: self, articles: articles, statusKey: statusKey, flag: flag)
|
||||
public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
delegate.markArticles(for: self, articles: articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
func existingContainer(withExternalID externalID: String) -> Container? {
|
||||
@ -794,18 +794,23 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func update(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) throws -> Set<Article>? {
|
||||
func update(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleSetResultBlock) {
|
||||
// Returns set of Articles whose statuses did change.
|
||||
guard !articles.isEmpty, let updatedStatuses = try database.mark(articles, statusKey: statusKey, flag: flag) else {
|
||||
return nil
|
||||
guard !articles.isEmpty else {
|
||||
completion(.success(Set<Article>()))
|
||||
return
|
||||
}
|
||||
|
||||
let updatedArticleIDs = updatedStatuses.articleIDs()
|
||||
let updatedArticles = Set(articles.filter{ updatedArticleIDs.contains($0.articleID) })
|
||||
|
||||
noteStatusesForArticlesDidChange(updatedArticles)
|
||||
return updatedArticles
|
||||
database.mark(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let updatedStatuses):
|
||||
let updatedArticleIDs = updatedStatuses.articleIDs()
|
||||
let updatedArticles = Set(articles.filter{ updatedArticleIDs.contains($0.articleID) })
|
||||
self.noteStatusesForArticlesDidChange(updatedArticles)
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Make sure statuses exist. Any existing statuses won’t be touched.
|
||||
|
@ -44,7 +44,7 @@ protocol AccountDelegate {
|
||||
func restoreWebFeed(for account: Account, feed: WebFeed, container: Container, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func restoreFolder(for account: Account, folder: Folder, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>?
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool)
|
||||
|
||||
// Called at the end of account’s init method.
|
||||
func accountDidInitialize(_ account: Account)
|
||||
|
@ -399,21 +399,25 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
let articles = try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account, showProgress: false) { _ in }
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account, showProgress: false) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return articles
|
||||
}
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
|
@ -435,19 +435,27 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
let syncStatuses = articles.map { SyncStatus(articleID: $0.articleID, key: SyncStatus.Key(statusKey), flag: flag)}
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 0 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
credentials = try? account.retrieveCredentials(type: .feedWranglerToken)
|
||||
}
|
||||
|
@ -534,22 +534,27 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
credentials = try? account.retrieveCredentials(type: .basic)
|
||||
}
|
||||
|
@ -487,24 +487,27 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
os_log(.debug, log: log, "Marking %@ as %@.", articles.map { $0.title }, syncStatuses)
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
initializedAccount = account
|
||||
credentials = try? account.retrieveCredentials(type: .oauthAccessToken)
|
||||
|
@ -203,8 +203,8 @@ final class LocalAccountDelegate: AccountDelegate {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { _ in }
|
||||
}
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
|
@ -573,19 +573,25 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
|
@ -471,24 +471,27 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
try? database.insertStatuses(syncStatuses)
|
||||
|
||||
database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
account.update(articles, statusKey: statusKey, flag: flag) { result in
|
||||
switch result {
|
||||
case .success(let articles):
|
||||
let syncStatuses = articles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: SyncStatus.Key(statusKey), flag: flag)
|
||||
}
|
||||
|
||||
try? self.database.insertStatuses(syncStatuses)
|
||||
|
||||
self.database.selectPendingCount { result in
|
||||
if let count = try? result.get(), count > 100 {
|
||||
self.sendArticleStatus(for: account) { _ in }
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error marking article status: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
credentials = try? account.retrieveCredentials(type: .readerAPIKey)
|
||||
}
|
||||
|
@ -237,8 +237,8 @@ public final class ArticlesDatabase {
|
||||
articlesTable.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate(completion)
|
||||
}
|
||||
|
||||
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) throws -> Set<ArticleStatus>? {
|
||||
return try articlesTable.mark(articles, statusKey, flag)
|
||||
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleStatusesResultBlock) {
|
||||
return articlesTable.mark(articles, statusKey, flag, completion)
|
||||
}
|
||||
|
||||
public func markAndFetchNew(articleIDs: Set<String>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleIDsCompletionBlock) {
|
||||
|
@ -434,22 +434,20 @@ final class ArticlesTable: DatabaseTable {
|
||||
statusesTable.fetchArticleIDsForStatusesWithoutArticlesNewerThan(articleCutoffDate, completion)
|
||||
}
|
||||
|
||||
func mark(_ articles: Set<Article>, _ statusKey: ArticleStatus.Key, _ flag: Bool) throws -> Set<ArticleStatus>? {
|
||||
var statuses: Set<ArticleStatus>?
|
||||
var error: DatabaseError?
|
||||
self.queue.runInTransactionSync { databaseResult in
|
||||
func mark(_ articles: Set<Article>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ completion: @escaping ArticleStatusesResultBlock) {
|
||||
self.queue.runInTransaction { databaseResult in
|
||||
switch databaseResult {
|
||||
case .success(let database):
|
||||
statuses = self.statusesTable.mark(articles.statuses(), statusKey, flag, database)
|
||||
let statuses = self.statusesTable.mark(articles.statuses(), statusKey, flag, database)
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(statuses ?? Set<ArticleStatus>()))
|
||||
}
|
||||
case .failure(let databaseError):
|
||||
error = databaseError
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(databaseError))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
return statuses
|
||||
}
|
||||
|
||||
func markAndFetchNew(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ completion: @escaping ArticleIDsCompletionBlock) {
|
||||
|
@ -13,25 +13,16 @@ import Account
|
||||
|
||||
// These handle multiple accounts.
|
||||
|
||||
@discardableResult
|
||||
func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) {
|
||||
|
||||
let d: [String: Set<Article>] = accountAndArticlesDictionary(articles)
|
||||
var updatedArticles = Set<Article>()
|
||||
|
||||
for (accountID, accountArticles) in d {
|
||||
|
||||
guard let account = AccountManager.shared.existingAccount(with: accountID) else {
|
||||
continue
|
||||
}
|
||||
|
||||
if let accountUpdatedArticles = account.markArticles(accountArticles, statusKey: statusKey, flag: flag) {
|
||||
updatedArticles.formUnion(accountUpdatedArticles)
|
||||
}
|
||||
|
||||
account.markArticles(accountArticles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
return updatedArticles
|
||||
}
|
||||
|
||||
private func accountAndArticlesDictionary(_ articles: Set<Article>) -> [String: Set<Article>] {
|
||||
|
Loading…
x
Reference in New Issue
Block a user