Fetch unread article IDs async. Also: fetch only for feeds currently subscribed-to. Fix #1218.

This commit is contained in:
Brent Simmons 2019-12-07 20:57:23 -08:00
parent 2d69fdf98a
commit a561ea9484
7 changed files with 125 additions and 106 deletions

View File

@ -673,8 +673,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
database.fetchStarredAndUnreadCount(for: flattenedWebFeeds().webFeedIDs(), callback: callback) database.fetchStarredAndUnreadCount(for: flattenedWebFeeds().webFeedIDs(), callback: callback)
} }
public func fetchUnreadArticleIDs() -> Set<String> { public func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
return database.fetchUnreadArticleIDs() return database.fetchUnreadArticleIDsAsync(webFeedIDs: flattenedWebFeeds().webFeedIDs(), callback: callback)
} }
public func fetchStarredArticleIDs() -> Set<String> { public func fetchStarredArticleIDs() -> Set<String> {

View File

@ -500,8 +500,7 @@ private extension FeedWranglerAccountDelegate {
func syncArticleReadState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) { func syncArticleReadState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) {
let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) }) let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) })
let unreadLocalItemIDs = account.fetchUnreadArticleIDs() account.fetchUnreadArticleIDs { unreadLocalItemIDs in
// unread if unread on server // unread if unread on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs) let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs)) let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
@ -519,11 +518,11 @@ private extension FeedWranglerAccountDelegate {
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs) let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .read, true) account.ensureStatuses(readMissingIDs, true, .read, true)
} }
}
func syncArticleStarredState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) { func syncArticleStarredState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) {
let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) }) let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) })
let unreadLocalItemIDs = account.fetchUnreadArticleIDs() account.fetchUnreadArticleIDs { unreadLocalItemIDs in
// starred if start on server // starred if start on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs) let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs)) let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
@ -541,6 +540,7 @@ private extension FeedWranglerAccountDelegate {
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs) let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .starred, false) account.ensureStatuses(readMissingIDs, true, .starred, false)
} }
}
func syncArticleState(_ account: Account, key: ArticleStatus.Key, flag: Bool, serverFeedItems: [FeedWranglerFeedItem]) { func syncArticleState(_ account: Account, key: ArticleStatus.Key, flag: Bool, serverFeedItems: [FeedWranglerFeedItem]) {
let _ /*serverFeedItemIDs*/ = serverFeedItems.map { String($0.feedID) } let _ /*serverFeedItemIDs*/ = serverFeedItems.map { String($0.feedID) }

View File

@ -1195,8 +1195,7 @@ private extension FeedbinAccountDelegate {
} }
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } ) let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
let currentUnreadArticleIDs = account.fetchUnreadArticleIDs() account.fetchUnreadArticleIDs { currentUnreadArticleIDs in
// Mark articles as unread // Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs) let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs)) let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
@ -1216,7 +1215,7 @@ private extension FeedbinAccountDelegate {
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID }) let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs) let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true) account.ensureStatuses(missingReadArticleIDs, true, .read, true)
}
} }
func syncArticleStarredState(account: Account, articleIDs: [Int]?) { func syncArticleStarredState(account: Account, articleIDs: [Int]?) {

View File

@ -36,32 +36,31 @@ final class FeedlySetUnreadArticlesOperation: FeedlyOperation {
let remoteUnreadArticleIds = allUnreadIdsProvider.entryIds let remoteUnreadArticleIds = allUnreadIdsProvider.entryIds
//Set(entries.filter { $0.unread }.map { $0.id }) //Set(entries.filter { $0.unread }.map { $0.id })
let localUnreadArticleIds = account.fetchUnreadArticleIDs() account.fetchUnreadArticleIDs { localUnreadArticleIds in
// Mark articles as unread // Mark articles as unread
let deltaUnreadArticleIds = remoteUnreadArticleIds.subtracting(localUnreadArticleIds) let deltaUnreadArticleIds = remoteUnreadArticleIds.subtracting(localUnreadArticleIds)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIds)) let markUnreadArticles = self.account.fetchArticles(.articleIDs(deltaUnreadArticleIds))
account.update(markUnreadArticles, statusKey: .read, flag: false) self.account.update(markUnreadArticles, statusKey: .read, flag: false)
// Save any unread statuses for articles we haven't yet received // Save any unread statuses for articles we haven't yet received
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID }) let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
let missingUnreadArticleIDs = deltaUnreadArticleIds.subtracting(markUnreadArticleIDs) let missingUnreadArticleIDs = deltaUnreadArticleIds.subtracting(markUnreadArticleIDs)
group.enter() group.enter()
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false) { self.account.ensureStatuses(missingUnreadArticleIDs, true, .read, false) {
group.leave() group.leave()
} }
// Mark articles as read // Mark articles as read
let deltaReadArticleIds = localUnreadArticleIds.subtracting(remoteUnreadArticleIds) let deltaReadArticleIds = localUnreadArticleIds.subtracting(remoteUnreadArticleIds)
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIds)) let markReadArticles = self.account.fetchArticles(.articleIDs(deltaReadArticleIds))
account.update(markReadArticles, statusKey: .read, flag: true) self.account.update(markReadArticles, statusKey: .read, flag: true)
// Save any read statuses for articles we haven't yet received // Save any read statuses for articles we haven't yet received
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID }) let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIds.subtracting(markReadArticleIDs) let missingReadArticleIDs = deltaReadArticleIds.subtracting(markReadArticleIDs)
group.enter() group.enter()
account.ensureStatuses(missingReadArticleIDs, true, .read, true) { self.account.ensureStatuses(missingReadArticleIDs, true, .read, true) {
group.leave() group.leave()
} }
@ -69,4 +68,5 @@ final class FeedlySetUnreadArticlesOperation: FeedlyOperation {
self.didFinish() self.didFinish()
} }
} }
}
} }

View File

@ -913,8 +913,7 @@ private extension ReaderAPIAccountDelegate {
} }
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } ) let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
let currentUnreadArticleIDs = account.fetchUnreadArticleIDs() account.fetchUnreadArticleIDs { currentUnreadArticleIDs in
// Mark articles as unread // Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs) let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs)) let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
@ -934,7 +933,7 @@ private extension ReaderAPIAccountDelegate {
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID }) let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs) let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true) account.ensureStatuses(missingReadArticleIDs, true, .read, true)
}
} }
func syncArticleStarredState(account: Account, articleIDs: [Int]?) { func syncArticleStarredState(account: Account, articleIDs: [Int]?) {

View File

@ -154,8 +154,9 @@ public final class ArticlesDatabase {
// MARK: - Status // MARK: - Status
public func fetchUnreadArticleIDs() -> Set<String> { /// Fetch the articleIDs of unread articles for feeds specified by webFeedIDs.
return articlesTable.fetchUnreadArticleIDs() public func fetchUnreadArticleIDsAsync(webFeedIDs: Set<String>, callback: @escaping (Set<String>) -> Void) {
articlesTable.fetchUnreadArticleIDsAsync(webFeedIDs, callback)
} }
public func fetchStarredArticleIDs() -> Set<String> { public func fetchStarredArticleIDs() -> Set<String> {

View File

@ -405,6 +405,26 @@ final class ArticlesTable: DatabaseTable {
return statusesTable.fetchUnreadArticleIDs() return statusesTable.fetchUnreadArticleIDs()
} }
func fetchUnreadArticleIDsAsync(_ webFeedIDs: Set<String>, _ callback: @escaping (Set<String>) -> Void) {
queue.runInDatabase { database in
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
let sql = "select articleID from articles natural join statuses where feedID in \(placeholders) and read=0 and userDeleted=0;"
let parameters = Array(webFeedIDs) as [Any]
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
DispatchQueue.main.async {
callback(Set<String>())
}
return
}
let articleIDs = resultSet.mapToSet{ $0.string(forColumnIndex: 0) }
DispatchQueue.main.async {
callback(articleIDs)
}
}
}
func fetchStarredArticleIDs() -> Set<String> { func fetchStarredArticleIDs() -> Set<String> {
return statusesTable.fetchStarredArticleIDs() return statusesTable.fetchStarredArticleIDs()
} }