From 37c9818cad8511b9c507bbdafdca87a7e1bcafeb Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 28 Sep 2019 13:51:33 -0700 Subject: [PATCH] =?UTF-8?q?Create=20and=20use=20a=20cache=20for=20Database?= =?UTF-8?q?Article=20=E2=80=94=20this=20will=20make=20fetches=20faster,=20?= =?UTF-8?q?since=20we=20can=20skip=20pulling=20the=20same=20data=20from=20?= =?UTF-8?q?the=20database=20over=20and=20over.=20Articles=20in=20the=20cac?= =?UTF-8?q?he=20are=20removed=20when=20articles=20are=20updated,=20so=20th?= =?UTF-8?q?e=20cache=20is=20never=20stale.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArticlesDatabase/ArticlesTable.swift | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Frameworks/ArticlesDatabase/ArticlesTable.swift b/Frameworks/ArticlesDatabase/ArticlesTable.swift index a92354045..8f06afdc8 100644 --- a/Frameworks/ArticlesDatabase/ArticlesTable.swift +++ b/Frameworks/ArticlesDatabase/ArticlesTable.swift @@ -20,6 +20,7 @@ final class ArticlesTable: DatabaseTable { private let statusesTable: StatusesTable private let authorsLookupTable: DatabaseLookupTable private let attachmentsLookupTable: DatabaseLookupTable + private var databaseArticlesCache = [String: DatabaseArticle]() private lazy var searchTable: SearchTable = { return SearchTable(queue: queue, articlesTable: self) @@ -480,6 +481,12 @@ private extension ArticlesTable { return nil } + // Articles are removed from the cache when they’re updated. + // See saveUpdatedArticles. + if let databaseArticle = databaseArticlesCache[articleID] { + return databaseArticle + } + // The resultSet is a result of a JOIN query with the statuses table, // so we can get the statuses at the same time and avoid additional database lookups. guard let status = statusesTable.statusWithRow(resultSet, articleID: articleID) else { @@ -506,7 +513,9 @@ private extension ArticlesTable { let datePublished = row.date(forColumn: DatabaseKey.datePublished) let dateModified = row.date(forColumn: DatabaseKey.dateModified) - return DatabaseArticle(articleID: articleID, feedID: feedID, uniqueID: uniqueID, title: title, contentHTML: contentHTML, contentText: contentText, url: url, externalURL: externalURL, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, status: status) + let databaseArticle = DatabaseArticle(articleID: articleID, feedID: feedID, uniqueID: uniqueID, title: title, contentHTML: contentHTML, contentText: contentText, url: url, externalURL: externalURL, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, status: status) + databaseArticlesCache[articleID] = databaseArticle + return databaseArticle } return articles @@ -662,6 +671,7 @@ private extension ArticlesTable { func saveUpdatedArticles(_ updatedArticles: Set
, _ fetchedArticles: [String: Article], _ database: FMDatabase) { + removeArticlesFromDatabaseArticlesCache(updatedArticles) saveUpdatedRelatedObjects(updatedArticles, fetchedArticles, database) for updatedArticle in updatedArticles { @@ -682,10 +692,17 @@ private extension ArticlesTable { // Not unexpected. There may be no changes. return } - + updateRowsWithDictionary(changesDictionary, whereKey: DatabaseKey.articleID, matches: updatedArticle.articleID, database: database) } - + + func removeArticlesFromDatabaseArticlesCache(_ updatedArticles: Set
) { + let articleIDs = updatedArticles.articleIDs() + for articleID in articleIDs { + databaseArticlesCache[articleID] = nil + } + } + func statusIndicatesArticleIsIgnorable(_ status: ArticleStatus) -> Bool { // Ignorable articles: either userDeleted==1 or (not starred and arrival date > 4 months). if status.userDeleted {