From b2b000dd2e581b6417be23c811c297987e562cc9 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 18 Apr 2020 20:18:32 -0700 Subject: [PATCH] Implement updated retention policy. --- .../ArticlesDatabase/ArticlesDatabase.swift | 12 +++-- .../ArticlesDatabase/ArticlesTable.swift | 48 ++++++------------- .../FetchAllUnreadCountsOperation.swift | 8 ++-- .../FetchFeedUnreadCountOperation.swift | 4 +- .../FetchUnreadCountsForFeedsOperation.swift | 10 ++-- 5 files changed, 30 insertions(+), 52 deletions(-) diff --git a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift index 4b16049d8..d0f3c424c 100644 --- a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift +++ b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift @@ -146,7 +146,7 @@ public final class ArticlesDatabase { /// Fetch all non-zero unread counts. public func fetchAllUnreadCounts(_ completion: @escaping UnreadCountDictionaryCompletionBlock) { - let operation = FetchAllUnreadCountsOperation(databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate) + let operation = FetchAllUnreadCountsOperation(databaseQueue: queue) operationQueue.cancelOperations(named: operation.name!) operation.completionBlock = { operation in let fetchOperation = operation as! FetchAllUnreadCountsOperation @@ -167,7 +167,7 @@ public final class ArticlesDatabase { /// Fetch non-zero unread counts for given webFeedIDs. public func fetchUnreadCounts(for webFeedIDs: Set, _ completion: @escaping UnreadCountDictionaryCompletionBlock) { - let operation = FetchUnreadCountsForFeedsOperation(webFeedIDs: webFeedIDs, databaseQueue: queue, cutoffDate: articlesTable.articleCutoffDate) + let operation = FetchUnreadCountsForFeedsOperation(webFeedIDs: webFeedIDs, databaseQueue: queue) operation.completionBlock = { operation in let fetchOperation = operation as! FetchUnreadCountsForFeedsOperation completion(fetchOperation.result) @@ -265,9 +265,11 @@ public final class ArticlesDatabase { // MARK: - Cleanup - // These are to be used only at startup. These are to prevent the database from growing forever. - - /// Calls the various clean-up functions. + /// Calls the various clean-up functions. To be used only at startup. + /// + /// This prevents the database from growing forever. If we didn’t do this: + /// 1) The database would grow to an inordinate size, and + /// 2) the app would become very slow. public func cleanupDatabaseAtStartup(subscribedToWebFeedIDs: Set) { if retentionStyle == .syncSystem { articlesTable.deleteOldArticles() diff --git a/Frameworks/ArticlesDatabase/ArticlesTable.swift b/Frameworks/ArticlesDatabase/ArticlesTable.swift index 68a31189f..635d1d9b3 100644 --- a/Frameworks/ArticlesDatabase/ArticlesTable.swift +++ b/Frameworks/ArticlesDatabase/ArticlesTable.swift @@ -181,7 +181,7 @@ final class ArticlesTable: DatabaseTable { // 1. Ensure statuses for all the incoming articles. // 2. Create incoming articles with parsedItems. - // 3. [Deleted - no longer needed] + // 3. [Deleted - this step is no longer needed] // 4. Fetch all articles for the feed. // 5. Create array of Articles not in database and save them. // 6. Create array of updated Articles and save what’s changed. @@ -494,6 +494,8 @@ final class ArticlesTable: DatabaseTable { /// we do this in a careful way: delete articles older than a year, /// check to see how much time has passed, then decide whether or not to continue. /// Repeat for successively more-recent dates. + /// + /// Returns `true` if it deleted old articles all the way up to the 90 day cutoff date. func deleteOldArticles() { precondition(retentionStyle == .syncSystem) @@ -537,10 +539,10 @@ final class ArticlesTable: DatabaseTable { switch self.retentionStyle { case .syncSystem: - sql = "select articleID from statuses where dateArrived Set
{ - // Don’t fetch articles that shouldn’t appear in the UI. The rules: - // * Must not be deleted. - // * Must be either 1) starred or 2) dateArrived must be newer than cutoff date. - - if withLimits { - let sql = "select * from articles natural join statuses where \(whereClause) and (starred=1 or dateArrived>?);" - return articlesWithSQL(sql, parameters + [articleCutoffDate as AnyObject], database) - } - else { - let sql = "select * from articles natural join statuses where \(whereClause);" - return articlesWithSQL(sql, parameters, database) - } + func fetchArticlesWithWhereClause(_ database: FMDatabase, whereClause: String, parameters: [AnyObject]) -> Set
{ + let sql = "select * from articles natural join statuses where \(whereClause);" + return articlesWithSQL(sql, parameters, database) } -// func fetchUnreadCount(_ webFeedID: String, _ database: FMDatabase) -> Int { -// // Count only the articles that would appear in the UI. -// // * Must be unread. -// // * Must not be deleted. -// // * Must be either 1) starred or 2) dateArrived must be newer than cutoff date. -// -// let sql = "select count(*) from articles natural join statuses where feedID=? and read=0 and (starred=1 or dateArrived>?);" -// return numberWithSQLAndParameters(sql, [webFeedID, articleCutoffDate], in: database) -// } - func fetchArticlesMatching(_ searchString: String, _ database: FMDatabase) -> Set
{ let sql = "select rowid from search where search match ?;" let sqlSearchString = sqliteSearchString(with: searchString) @@ -712,7 +694,7 @@ private extension ArticlesTable { let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(searchRowIDs.count))! let whereClause = "searchRowID in \(placeholders)" let parameters: [AnyObject] = Array(searchRowIDs) as [AnyObject] - return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: true) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func sqliteSearchString(with searchString: String) -> String { @@ -785,7 +767,7 @@ private extension ArticlesTable { let parameters = webFeedIDs.map { $0 as AnyObject } let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))! let whereClause = "feedID in \(placeholders)" - return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: true) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func fetchUnreadArticles(_ webFeedIDs: Set, _ database: FMDatabase) -> Set
{ @@ -796,11 +778,11 @@ private extension ArticlesTable { let parameters = webFeedIDs.map { $0 as AnyObject } let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))! let whereClause = "feedID in \(placeholders) and read=0" - return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: true) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func fetchArticlesForFeedID(_ webFeedID: String, withLimits: Bool, _ database: FMDatabase) -> Set
{ - return fetchArticlesWithWhereClause(database, whereClause: "articles.feedID = ?", parameters: [webFeedID as AnyObject], withLimits: withLimits) + return fetchArticlesWithWhereClause(database, whereClause: "articles.feedID = ?", parameters: [webFeedID as AnyObject]) } func fetchArticles(articleIDs: Set, _ database: FMDatabase) -> Set
{ @@ -810,7 +792,7 @@ private extension ArticlesTable { let parameters = articleIDs.map { $0 as AnyObject } let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(articleIDs.count))! let whereClause = "articleID in \(placeholders)" - return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: false) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func fetchArticlesSince(_ webFeedIDs: Set, _ cutoffDate: Date, _ database: FMDatabase) -> Set
{ @@ -823,7 +805,7 @@ private extension ArticlesTable { let parameters = webFeedIDs.map { $0 as AnyObject } + [cutoffDate as AnyObject, cutoffDate as AnyObject] let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))! let whereClause = "feedID in \(placeholders) and (datePublished > ? or (datePublished is null and dateArrived > ?))" - return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: false) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func fetchStarredArticles(_ webFeedIDs: Set, _ database: FMDatabase) -> Set
{ @@ -834,7 +816,7 @@ private extension ArticlesTable { 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 fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: false) + return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters) } func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set, _ database: FMDatabase) -> Set
{ diff --git a/Frameworks/ArticlesDatabase/Operations/FetchAllUnreadCountsOperation.swift b/Frameworks/ArticlesDatabase/Operations/FetchAllUnreadCountsOperation.swift index 2f82d2549..04c77d955 100644 --- a/Frameworks/ArticlesDatabase/Operations/FetchAllUnreadCountsOperation.swift +++ b/Frameworks/ArticlesDatabase/Operations/FetchAllUnreadCountsOperation.swift @@ -22,11 +22,9 @@ public final class FetchAllUnreadCountsOperation: MainThreadOperation { public var completionBlock: MainThreadOperation.MainThreadOperationCompletionBlock? private let queue: DatabaseQueue - private let cutoffDate: Date - init(databaseQueue: DatabaseQueue, cutoffDate: Date) { + init(databaseQueue: DatabaseQueue) { self.queue = databaseQueue - self.cutoffDate = cutoffDate } public func run() { @@ -49,9 +47,9 @@ public final class FetchAllUnreadCountsOperation: MainThreadOperation { private extension FetchAllUnreadCountsOperation { func fetchUnreadCounts(_ database: FMDatabase) { - let sql = "select distinct feedID, count(*) from articles natural join statuses where read=0 and (starred=1 or dateArrived>?) group by feedID;" + let sql = "select distinct feedID, count(*) from articles natural join statuses where read=0 group by feedID;" - guard let resultSet = database.executeQuery(sql, withArgumentsIn: [cutoffDate]) else { + guard let resultSet = database.executeQuery(sql, withArgumentsIn: nil) else { informOperationDelegateOfCompletion() return } diff --git a/Frameworks/ArticlesDatabase/Operations/FetchFeedUnreadCountOperation.swift b/Frameworks/ArticlesDatabase/Operations/FetchFeedUnreadCountOperation.swift index 4f8c99504..289bb73e6 100644 --- a/Frameworks/ArticlesDatabase/Operations/FetchFeedUnreadCountOperation.swift +++ b/Frameworks/ArticlesDatabase/Operations/FetchFeedUnreadCountOperation.swift @@ -52,9 +52,9 @@ public final class FetchFeedUnreadCountOperation: MainThreadOperation { private extension FetchFeedUnreadCountOperation { func fetchUnreadCount(_ database: FMDatabase) { - let sql = "select count(*) from articles natural join statuses where feedID=? and read=0 and (starred=1 or dateArrived>?);" + let sql = "select count(*) from articles natural join statuses where feedID=? and read=0;" - guard let resultSet = database.executeQuery(sql, withArgumentsIn: [webFeedID, cutoffDate]) else { + guard let resultSet = database.executeQuery(sql, withArgumentsIn: [webFeedID]) else { informOperationDelegateOfCompletion() return } diff --git a/Frameworks/ArticlesDatabase/Operations/FetchUnreadCountsForFeedsOperation.swift b/Frameworks/ArticlesDatabase/Operations/FetchUnreadCountsForFeedsOperation.swift index b323f4e4f..7f7533b77 100644 --- a/Frameworks/ArticlesDatabase/Operations/FetchUnreadCountsForFeedsOperation.swift +++ b/Frameworks/ArticlesDatabase/Operations/FetchUnreadCountsForFeedsOperation.swift @@ -23,13 +23,11 @@ public final class FetchUnreadCountsForFeedsOperation: MainThreadOperation { public var completionBlock: MainThreadOperation.MainThreadOperationCompletionBlock? private let queue: DatabaseQueue - private let cutoffDate: Date private let webFeedIDs: Set - init(webFeedIDs: Set, databaseQueue: DatabaseQueue, cutoffDate: Date) { + init(webFeedIDs: Set, databaseQueue: DatabaseQueue) { self.webFeedIDs = webFeedIDs self.queue = databaseQueue - self.cutoffDate = cutoffDate } public func run() { @@ -53,11 +51,9 @@ private extension FetchUnreadCountsForFeedsOperation { func fetchUnreadCounts(_ database: FMDatabase) { let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))! - let sql = "select distinct feedID, count(*) from articles natural join statuses where feedID in \(placeholders) and read=0 and (starred=1 or dateArrived>?) group by feedID;" + let sql = "select distinct feedID, count(*) from articles natural join statuses where feedID in \(placeholders) and read=0 group by feedID;" - var parameters = [Any]() - parameters += Array(webFeedIDs) as [Any] - parameters += [cutoffDate] as [Any] + let parameters = Array(webFeedIDs) as [Any] guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else { informOperationDelegateOfCompletion()