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)
}
public func fetchUnreadArticleIDs() -> Set<String> {
return database.fetchUnreadArticleIDs()
public func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
return database.fetchUnreadArticleIDsAsync(webFeedIDs: flattenedWebFeeds().webFeedIDs(), callback: callback)
}
public func fetchStarredArticleIDs() -> Set<String> {

View File

@ -500,46 +500,46 @@ private extension FeedWranglerAccountDelegate {
func syncArticleReadState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) {
let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) })
let unreadLocalItemIDs = account.fetchUnreadArticleIDs()
// unread if unread on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
account.update(unreadFoundArticles, statusKey: .read, flag: false)
let unreadFoundItemIDs = Set(unreadFoundArticles.map { $0.articleID })
let missingArticleIDs = unreadDiffItemIDs.subtracting(unreadFoundItemIDs)
account.ensureStatuses(missingArticleIDs, true, .read, false)
account.fetchUnreadArticleIDs { unreadLocalItemIDs in
// unread if unread on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
account.update(unreadFoundArticles, statusKey: .read, flag: false)
let readItemIDs = unreadLocalItemIDs.subtracting(unreadServerItemIDs)
let readArtices = account.fetchArticles(.articleIDs(readItemIDs))
account.update(readArtices, statusKey: .read, flag: true)
let foundReadArticleIDs = Set(readArtices.map { $0.articleID })
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .read, true)
let unreadFoundItemIDs = Set(unreadFoundArticles.map { $0.articleID })
let missingArticleIDs = unreadDiffItemIDs.subtracting(unreadFoundItemIDs)
account.ensureStatuses(missingArticleIDs, true, .read, false)
let readItemIDs = unreadLocalItemIDs.subtracting(unreadServerItemIDs)
let readArtices = account.fetchArticles(.articleIDs(readItemIDs))
account.update(readArtices, statusKey: .read, flag: true)
let foundReadArticleIDs = Set(readArtices.map { $0.articleID })
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .read, true)
}
}
func syncArticleStarredState(_ account: Account, _ unreadFeedItems: [FeedWranglerFeedItem]) {
let unreadServerItemIDs = Set(unreadFeedItems.map { String($0.feedItemID) })
let unreadLocalItemIDs = account.fetchUnreadArticleIDs()
// starred if start on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
account.update(unreadFoundArticles, statusKey: .starred, flag: true)
let unreadFoundItemIDs = Set(unreadFoundArticles.map { $0.articleID })
let missingArticleIDs = unreadDiffItemIDs.subtracting(unreadFoundItemIDs)
account.ensureStatuses(missingArticleIDs, true, .starred, true)
account.fetchUnreadArticleIDs { unreadLocalItemIDs in
// starred if start on server
let unreadDiffItemIDs = unreadServerItemIDs.subtracting(unreadLocalItemIDs)
let unreadFoundArticles = account.fetchArticles(.articleIDs(unreadDiffItemIDs))
account.update(unreadFoundArticles, statusKey: .starred, flag: true)
let readItemIDs = unreadLocalItemIDs.subtracting(unreadServerItemIDs)
let readArtices = account.fetchArticles(.articleIDs(readItemIDs))
account.update(readArtices, statusKey: .starred, flag: false)
let foundReadArticleIDs = Set(readArtices.map { $0.articleID })
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .starred, false)
let unreadFoundItemIDs = Set(unreadFoundArticles.map { $0.articleID })
let missingArticleIDs = unreadDiffItemIDs.subtracting(unreadFoundItemIDs)
account.ensureStatuses(missingArticleIDs, true, .starred, true)
let readItemIDs = unreadLocalItemIDs.subtracting(unreadServerItemIDs)
let readArtices = account.fetchArticles(.articleIDs(readItemIDs))
account.update(readArtices, statusKey: .starred, flag: false)
let foundReadArticleIDs = Set(readArtices.map { $0.articleID })
let readMissingIDs = readItemIDs.subtracting(foundReadArticleIDs)
account.ensureStatuses(readMissingIDs, true, .starred, false)
}
}
func syncArticleState(_ account: Account, key: ArticleStatus.Key, flag: Bool, serverFeedItems: [FeedWranglerFeedItem]) {

View File

@ -1195,28 +1195,27 @@ private extension FeedbinAccountDelegate {
}
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
let currentUnreadArticleIDs = account.fetchUnreadArticleIDs()
// Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
account.update(markUnreadArticles, statusKey: .read, flag: false)
account.fetchUnreadArticleIDs { currentUnreadArticleIDs in
// Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
account.update(markUnreadArticles, statusKey: .read, flag: false)
// Save any unread statuses for articles we haven't yet received
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false)
// Save any unread statuses for articles we haven't yet received
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false)
// Mark articles as read
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs))
account.update(markReadArticles, statusKey: .read, flag: true)
// Save any read statuses for articles we haven't yet received
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true)
// Mark articles as read
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs))
account.update(markReadArticles, statusKey: .read, flag: true)
// Save any read statuses for articles we haven't yet received
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true)
}
}
func syncArticleStarredState(account: Account, articleIDs: [Int]?) {

View File

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

View File

@ -913,28 +913,27 @@ private extension ReaderAPIAccountDelegate {
}
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
let currentUnreadArticleIDs = account.fetchUnreadArticleIDs()
// Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
account.update(markUnreadArticles, statusKey: .read, flag: false)
account.fetchUnreadArticleIDs { currentUnreadArticleIDs in
// Mark articles as unread
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
account.update(markUnreadArticles, statusKey: .read, flag: false)
// Save any unread statuses for articles we haven't yet received
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false)
// Save any unread statuses for articles we haven't yet received
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false)
// Mark articles as read
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs))
account.update(markReadArticles, statusKey: .read, flag: true)
// Save any read statuses for articles we haven't yet received
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true)
// Mark articles as read
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs))
account.update(markReadArticles, statusKey: .read, flag: true)
// Save any read statuses for articles we haven't yet received
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
account.ensureStatuses(missingReadArticleIDs, true, .read, true)
}
}
func syncArticleStarredState(account: Account, articleIDs: [Int]?) {

View File

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

View File

@ -404,7 +404,27 @@ final class ArticlesTable: DatabaseTable {
func fetchUnreadArticleIDs() -> Set<String>{
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> {
return statusesTable.fetchStarredArticleIDs()
}