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)
|
database.fetchStarredAndUnreadCount(for: flattenedWebFeeds().webFeedIDs(), completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func fetchCountForStarredArticles() throws -> Int {
|
||||||
|
return try database.fetchStarredArticlesCount(flattenedWebFeeds().webFeedIDs())
|
||||||
|
}
|
||||||
|
|
||||||
public func fetchUnreadArticleIDs(_ completion: @escaping ArticleIDsCompletionBlock) {
|
public func fetchUnreadArticleIDs(_ completion: @escaping ArticleIDsCompletionBlock) {
|
||||||
database.fetchUnreadArticleIDsAsync(completion: completion)
|
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
|
// MARK: - Caches
|
||||||
|
|
||||||
|
@ -114,6 +114,10 @@ public final class ArticlesDatabase {
|
|||||||
return try articlesTable.fetchStarredArticles(webFeedIDs, limit)
|
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> {
|
public func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||||
return try articlesTable.fetchArticlesMatching(searchString, webFeedIDs)
|
return try articlesTable.fetchArticlesMatching(searchString, webFeedIDs)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,8 @@ final class ArticlesTable: DatabaseTable {
|
|||||||
let articleCutoffDate = Date().bySubtracting(days: 90)
|
let articleCutoffDate = Date().bySubtracting(days: 90)
|
||||||
|
|
||||||
private typealias ArticlesFetchMethod = (FMDatabase) -> Set<Article>
|
private typealias ArticlesFetchMethod = (FMDatabase) -> Set<Article>
|
||||||
|
private typealias ArticlesCountFetchMethod = (FMDatabase) -> Int
|
||||||
|
|
||||||
init(name: String, accountID: String, queue: DatabaseQueue, retentionStyle: ArticlesDatabase.RetentionStyle) {
|
init(name: String, accountID: String, queue: DatabaseQueue, retentionStyle: ArticlesDatabase.RetentionStyle) {
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -103,6 +104,10 @@ final class ArticlesTable: DatabaseTable {
|
|||||||
fetchArticlesAsync({ self.fetchStarredArticles(webFeedIDs, limit, $0) }, completion)
|
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
|
// MARK: - Fetching Search Articles
|
||||||
|
|
||||||
func fetchArticlesMatching(_ searchString: String) throws -> Set<Article> {
|
func fetchArticlesMatching(_ searchString: String) throws -> Set<Article> {
|
||||||
@ -671,6 +676,23 @@ private extension ArticlesTable {
|
|||||||
return articles
|
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) {
|
private func fetchArticlesAsync(_ fetchMethod: @escaping ArticlesFetchMethod, _ completion: @escaping ArticleSetResultBlock) {
|
||||||
queue.runInDatabase { databaseResult in
|
queue.runInDatabase { databaseResult in
|
||||||
|
|
||||||
@ -745,6 +767,19 @@ private extension ArticlesTable {
|
|||||||
return articlesWithSQL(sql, parameters, database)
|
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> {
|
func fetchArticlesMatching(_ searchString: String, _ database: FMDatabase) -> Set<Article> {
|
||||||
let sql = "select rowid from search where search match ?;"
|
let sql = "select rowid from search where search match ?;"
|
||||||
let sqlSearchString = sqliteSearchString(with: searchString)
|
let sqlSearchString = sqliteSearchString(with: searchString)
|
||||||
@ -840,20 +875,31 @@ private extension ArticlesTable {
|
|||||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
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;
|
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and starred=1;
|
||||||
if webFeedIDs.isEmpty {
|
if webFeedIDs.isEmpty {
|
||||||
return Set<Article>()
|
return Set<Article>()
|
||||||
}
|
}
|
||||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||||
var whereClause = "feedID in \(placeholders) and starred=1"
|
var whereClause = "feedID in \(placeholders) and starred=1"
|
||||||
if let limit = limit {
|
if let limit = limit {
|
||||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||||
}
|
}
|
||||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
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> {
|
func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set<String>, _ database: FMDatabase) -> Set<Article> {
|
||||||
let articles = fetchArticlesMatching(searchString, database)
|
let articles = fetchArticlesMatching(searchString, database)
|
||||||
// TODO: include the feedIDs in the SQL rather than filtering here.
|
// 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,
|
let latestData = WidgetData(currentUnreadCount: SmartFeedsController.shared.unreadFeed.unreadCount,
|
||||||
currentTodayCount: SmartFeedsController.shared.todayFeed.unreadCount,
|
currentTodayCount: SmartFeedsController.shared.todayFeed.unreadCount,
|
||||||
currentStarredCount: try! SmartFeedsController.shared.starredFeed.fetchArticles().count,
|
currentStarredCount: try AccountManager.shared.fetchCountForStarredArticles(),
|
||||||
unreadArticles: unread,
|
unreadArticles: unread,
|
||||||
starredArticles: starred,
|
starredArticles: starred,
|
||||||
todayArticles:today,
|
todayArticles:today,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user