Save articles from multiple web feeds at once — rather than doing it feed-by-feed — when syncing. (This makes syncing faster.) Fix #1794.
This commit is contained in:
parent
9f516caa35
commit
fb4f72ad18
|
@ -689,55 +689,48 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let group = DispatchGroup()
|
database.update(webFeedIDsAndItems: webFeedIDsAndItems, defaultRead: defaultRead) { updateArticlesResult in
|
||||||
var possibleError: DatabaseError? = nil
|
|
||||||
var newArticles = Set<Article>()
|
|
||||||
var updatedArticles = Set<Article>()
|
|
||||||
|
|
||||||
for (webFeedID, items) in webFeedIDsAndItems {
|
func sendNotificationAbout(newArticles: Set<Article>?, updatedArticles: Set<Article>?) {
|
||||||
|
var webFeeds = Set<WebFeed>()
|
||||||
|
|
||||||
group.enter()
|
if let newArticles = newArticles {
|
||||||
database.update(webFeedID: webFeedID, items: items, defaultRead: defaultRead) { updateArticlesResult in
|
webFeeds.formUnion(Set(newArticles.compactMap { $0.webFeed }))
|
||||||
|
}
|
||||||
switch updateArticlesResult {
|
if let updatedArticles = updatedArticles {
|
||||||
case .success(let newAndUpdatedArticles):
|
webFeeds.formUnion(Set(updatedArticles.compactMap { $0.webFeed }))
|
||||||
if let articles = newAndUpdatedArticles.newArticles {
|
|
||||||
newArticles.formUnion(articles)
|
|
||||||
}
|
|
||||||
if let articles = newAndUpdatedArticles.updatedArticles {
|
|
||||||
updatedArticles.formUnion(articles)
|
|
||||||
}
|
|
||||||
case .failure(let databaseError):
|
|
||||||
possibleError = databaseError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group.leave()
|
var shouldSendNotification = false
|
||||||
}
|
var userInfo = [String: Any]()
|
||||||
|
|
||||||
}
|
if let newArticles = newArticles, !newArticles.isEmpty {
|
||||||
|
shouldSendNotification = true
|
||||||
group.notify(queue: DispatchQueue.main) {
|
userInfo[UserInfoKey.newArticles] = newArticles
|
||||||
var userInfo = [String: Any]()
|
self.updateUnreadCounts(for: webFeeds) {
|
||||||
var webFeeds = Set(newArticles.compactMap { $0.webFeed })
|
NotificationCenter.default.post(name: .DownloadArticlesDidUpdateUnreadCounts, object: self, userInfo: nil)
|
||||||
webFeeds.formUnion(Set(updatedArticles.compactMap { $0.webFeed }))
|
}
|
||||||
|
}
|
||||||
if !newArticles.isEmpty {
|
|
||||||
self.updateUnreadCounts(for: webFeeds) {
|
if let updatedArticles = updatedArticles, !updatedArticles.isEmpty {
|
||||||
NotificationCenter.default.post(name: .DownloadArticlesDidUpdateUnreadCounts, object: self, userInfo: nil)
|
shouldSendNotification = true
|
||||||
|
userInfo[UserInfoKey.updatedArticles] = updatedArticles
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldSendNotification {
|
||||||
|
userInfo[UserInfoKey.webFeeds] = webFeeds
|
||||||
|
NotificationCenter.default.post(name: .AccountDidDownloadArticles, object: self, userInfo: userInfo)
|
||||||
}
|
}
|
||||||
userInfo[UserInfoKey.newArticles] = newArticles
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !updatedArticles.isEmpty {
|
switch updateArticlesResult {
|
||||||
userInfo[UserInfoKey.updatedArticles] = updatedArticles
|
case .success(let newAndUpdatedArticles):
|
||||||
|
sendNotificationAbout(newArticles: newAndUpdatedArticles.newArticles, updatedArticles: newAndUpdatedArticles.updatedArticles)
|
||||||
|
completion(nil)
|
||||||
|
case .failure(let databaseError):
|
||||||
|
completion(databaseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo[UserInfoKey.webFeeds] = webFeeds
|
|
||||||
NotificationCenter.default.post(name: .AccountDidDownloadArticles, object: self, userInfo: userInfo)
|
|
||||||
|
|
||||||
completion(possibleError)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
|
|
|
@ -184,8 +184,8 @@ public final class ArticlesDatabase {
|
||||||
// MARK: - Saving and Updating Articles
|
// MARK: - Saving and Updating Articles
|
||||||
|
|
||||||
/// Update articles and save new ones.
|
/// Update articles and save new ones.
|
||||||
public func update(webFeedID: String, items: Set<ParsedItem>, defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
public func update(webFeedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||||
articlesTable.update(webFeedID, items, defaultRead, completion)
|
articlesTable.update(webFeedIDsAndItems, defaultRead, completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Status
|
// MARK: - Status
|
||||||
|
|
|
@ -169,8 +169,8 @@ final class ArticlesTable: DatabaseTable {
|
||||||
|
|
||||||
// MARK: - Updating
|
// MARK: - Updating
|
||||||
|
|
||||||
func update(_ webFeedID: String, _ items: Set<ParsedItem>, _ read: Bool, _ completion: @escaping UpdateArticlesCompletionBlock) {
|
func update(_ webFeedIDsAndItems: [String: Set<ParsedItem>], _ read: Bool, _ completion: @escaping UpdateArticlesCompletionBlock) {
|
||||||
if items.isEmpty {
|
if webFeedIDsAndItems.isEmpty {
|
||||||
callUpdateArticlesCompletionBlock(nil, nil, completion)
|
callUpdateArticlesCompletionBlock(nil, nil, completion)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -187,11 +187,15 @@ final class ArticlesTable: DatabaseTable {
|
||||||
self.queue.runInTransaction { (databaseResult) in
|
self.queue.runInTransaction { (databaseResult) in
|
||||||
|
|
||||||
func makeDatabaseCalls(_ database: FMDatabase) {
|
func makeDatabaseCalls(_ database: FMDatabase) {
|
||||||
let articleIDs = items.articleIDs()
|
var articleIDs = Set<String>()
|
||||||
|
for (_, parsedItems) in webFeedIDsAndItems {
|
||||||
|
articleIDs.formUnion(parsedItems.articleIDs())
|
||||||
|
}
|
||||||
|
|
||||||
let statusesDictionary = self.statusesTable.ensureStatusesForArticleIDs(articleIDs, read, database) //1
|
let statusesDictionary = self.statusesTable.ensureStatusesForArticleIDs(articleIDs, read, database) //1
|
||||||
assert(statusesDictionary.count == articleIDs.count)
|
assert(statusesDictionary.count == articleIDs.count)
|
||||||
|
|
||||||
let allIncomingArticles = Article.articlesWithWebFeedIDsAndItems(webFeedID, items, self.accountID, statusesDictionary) //2
|
let allIncomingArticles = Article.articlesWithWebFeedIDsAndItems(webFeedIDsAndItems, self.accountID, statusesDictionary) //2
|
||||||
if allIncomingArticles.isEmpty {
|
if allIncomingArticles.isEmpty {
|
||||||
self.callUpdateArticlesCompletionBlock(nil, nil, completion)
|
self.callUpdateArticlesCompletionBlock(nil, nil, completion)
|
||||||
return
|
return
|
||||||
|
|
|
@ -112,9 +112,16 @@ extension Article {
|
||||||
// return Set(parsedItems.map{ Article(parsedItem: $0, maximumDateAllowed: maximumDateAllowed, accountID: accountID, feedID: feedID, status: statusesDictionary[$0.articleID]!) })
|
// return Set(parsedItems.map{ Article(parsedItem: $0, maximumDateAllowed: maximumDateAllowed, accountID: accountID, feedID: feedID, status: statusesDictionary[$0.articleID]!) })
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static func articlesWithWebFeedIDsAndItems(_ webFeedID: String, _ items: Set<ParsedItem>, _ accountID: String, _ statusesDictionary: [String: ArticleStatus]) -> Set<Article> {
|
static func articlesWithWebFeedIDsAndItems(_ webFeedIDsAndItems: [String: Set<ParsedItem>], _ accountID: String, _ statusesDictionary: [String: ArticleStatus]) -> Set<Article> {
|
||||||
let maximumDateAllowed = Date().addingTimeInterval(60 * 60 * 24) // Allow dates up to about 24 hours ahead of now
|
let maximumDateAllowed = Date().addingTimeInterval(60 * 60 * 24) // Allow dates up to about 24 hours ahead of now
|
||||||
let feedArticles = Set(items.map{ Article(parsedItem: $0, maximumDateAllowed: maximumDateAllowed, accountID: accountID, webFeedID: webFeedID, status: statusesDictionary[$0.articleID]!) })
|
var feedArticles = Set<Article>()
|
||||||
|
for (webFeedID, parsedItems) in webFeedIDsAndItems {
|
||||||
|
for parsedItem in parsedItems {
|
||||||
|
let status = statusesDictionary[parsedItem.articleID]!
|
||||||
|
let article = Article(parsedItem: parsedItem, maximumDateAllowed: maximumDateAllowed, accountID: accountID, webFeedID: webFeedID, status: status)
|
||||||
|
feedArticles.insert(article)
|
||||||
|
}
|
||||||
|
}
|
||||||
return feedArticles
|
return feedArticles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue