Fix one of the causes of watchdog crashes in WidgetDataEncoder by fetching just the count of starred articles — instead of fetching all the starred articles and counting them, which can take a long time.
This commit is contained in:
parent
fdadb80863
commit
a0e8ca00ee
|
@ -718,6 +718,10 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
database.fetchStarredAndUnreadCount(for: flattenedWebFeeds().webFeedIDs(), completion: completion)
|
||||
}
|
||||
|
||||
public func fetchCountForStarredArticles() throws -> Int {
|
||||
return try database.fetchStarredArticlesCount(flattenedWebFeeds().webFeedIDs())
|
||||
}
|
||||
|
||||
public func fetchUnreadArticleIDs(_ completion: @escaping ArticleIDsCompletionBlock) {
|
||||
database.fetchUnreadArticleIDsAsync(completion: completion)
|
||||
}
|
||||
|
|
|
@ -393,6 +393,17 @@ public final class AccountManager: UnreadCountProvider {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Fetching Article Counts
|
||||
|
||||
public func fetchCountForStarredArticles() throws -> Int {
|
||||
precondition(Thread.isMainThread)
|
||||
var count = 0
|
||||
for account in activeAccounts {
|
||||
count += try account.fetchCountForStarredArticles()
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// MARK: - Caches
|
||||
|
||||
|
|
|
@ -114,6 +114,10 @@ public final class ArticlesDatabase {
|
|||
return try articlesTable.fetchStarredArticles(webFeedIDs, limit)
|
||||
}
|
||||
|
||||
public func fetchStarredArticlesCount(_ webFeedIDs: Set<String>) throws -> Int {
|
||||
return try articlesTable.fetchStarredArticlesCount(webFeedIDs)
|
||||
}
|
||||
|
||||
public func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try articlesTable.fetchArticlesMatching(searchString, webFeedIDs)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ final class ArticlesTable: DatabaseTable {
|
|||
let articleCutoffDate = Date().bySubtracting(days: 90)
|
||||
|
||||
private typealias ArticlesFetchMethod = (FMDatabase) -> Set<Article>
|
||||
|
||||
private typealias ArticlesCountFetchMethod = (FMDatabase) -> Int
|
||||
|
||||
init(name: String, accountID: String, queue: DatabaseQueue, retentionStyle: ArticlesDatabase.RetentionStyle) {
|
||||
|
||||
self.name = name
|
||||
|
@ -103,6 +104,10 @@ final class ArticlesTable: DatabaseTable {
|
|||
fetchArticlesAsync({ self.fetchStarredArticles(webFeedIDs, limit, $0) }, completion)
|
||||
}
|
||||
|
||||
func fetchStarredArticlesCount(_ webFeedIDs: Set<String>) throws -> Int {
|
||||
return try fetchArticlesCount{ self.fetchStarredArticlesCount(webFeedIDs, $0) }
|
||||
}
|
||||
|
||||
// MARK: - Fetching Search Articles
|
||||
|
||||
func fetchArticlesMatching(_ searchString: String) throws -> Set<Article> {
|
||||
|
@ -671,6 +676,23 @@ private extension ArticlesTable {
|
|||
return articles
|
||||
}
|
||||
|
||||
private func fetchArticlesCount(_ fetchMethod: @escaping ArticlesCountFetchMethod) throws -> Int {
|
||||
var articlesCount = 0
|
||||
var error: DatabaseError? = nil
|
||||
queue.runInDatabaseSync { databaseResult in
|
||||
switch databaseResult {
|
||||
case .success(let database):
|
||||
articlesCount = fetchMethod(database)
|
||||
case .failure(let databaseError):
|
||||
error = databaseError
|
||||
}
|
||||
}
|
||||
if let error = error {
|
||||
throw(error)
|
||||
}
|
||||
return articlesCount
|
||||
}
|
||||
|
||||
private func fetchArticlesAsync(_ fetchMethod: @escaping ArticlesFetchMethod, _ completion: @escaping ArticleSetResultBlock) {
|
||||
queue.runInDatabase { databaseResult in
|
||||
|
||||
|
@ -745,6 +767,19 @@ private extension ArticlesTable {
|
|||
return articlesWithSQL(sql, parameters, database)
|
||||
}
|
||||
|
||||
func fetchArticleCountsWithWhereClause(_ database: FMDatabase, whereClause: String, parameters: [AnyObject]) -> Int {
|
||||
let sql = "select count(*) from articles natural join statuses where \(whereClause);"
|
||||
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
|
||||
return 0
|
||||
}
|
||||
var articlesCount = 0
|
||||
if resultSet.next() {
|
||||
articlesCount = resultSet.long(forColumnIndex: 0)
|
||||
}
|
||||
resultSet.close()
|
||||
return articlesCount
|
||||
}
|
||||
|
||||
func fetchArticlesMatching(_ searchString: String, _ database: FMDatabase) -> Set<Article> {
|
||||
let sql = "select rowid from search where search match ?;"
|
||||
let sqlSearchString = sqliteSearchString(with: searchString)
|
||||
|
@ -840,20 +875,31 @@ private extension ArticlesTable {
|
|||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
||||
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and starred=1;
|
||||
if webFeedIDs.isEmpty {
|
||||
return Set<Article>()
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
var whereClause = "feedID in \(placeholders) and starred=1"
|
||||
if let limit = limit {
|
||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||
}
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
||||
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and starred=1;
|
||||
if webFeedIDs.isEmpty {
|
||||
return Set<Article>()
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
var whereClause = "feedID in \(placeholders) and starred=1"
|
||||
if let limit = limit {
|
||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||
}
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchStarredArticlesCount(_ webFeedIDs: Set<String>, _ database: FMDatabase) -> Int {
|
||||
// select count from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and starred=1;
|
||||
if webFeedIDs.isEmpty {
|
||||
return 0
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
let whereClause = "feedID in \(placeholders) and starred=1"
|
||||
return fetchArticleCountsWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set<String>, _ database: FMDatabase) -> Set<Article> {
|
||||
let articles = fetchArticlesMatching(searchString, database)
|
||||
// TODO: include the feedIDs in the SQL rather than filtering here.
|
||||
|
|
|
@ -73,7 +73,7 @@ public final class WidgetDataEncoder {
|
|||
|
||||
let latestData = WidgetData(currentUnreadCount: SmartFeedsController.shared.unreadFeed.unreadCount,
|
||||
currentTodayCount: SmartFeedsController.shared.todayFeed.unreadCount,
|
||||
currentStarredCount: try! SmartFeedsController.shared.starredFeed.fetchArticles().count,
|
||||
currentStarredCount: try AccountManager.shared.fetchCountForStarredArticles(),
|
||||
unreadArticles: unread,
|
||||
starredArticles: starred,
|
||||
todayArticles:today,
|
||||
|
|
Loading…
Reference in New Issue