From c30e7eeb99d36d72c66aac36d2964e50ed66157f Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 5 Aug 2017 11:12:45 -0700 Subject: [PATCH] Get StatusesTable compiling. --- Frameworks/Database/StatusesTable.swift | 153 +++++++++++++--------- Frameworks/RSDatabase/DatabaseTable.swift | 9 +- 2 files changed, 94 insertions(+), 68 deletions(-) diff --git a/Frameworks/Database/StatusesTable.swift b/Frameworks/Database/StatusesTable.swift index 8f9b1ebf1..6dab3c4db 100644 --- a/Frameworks/Database/StatusesTable.swift +++ b/Frameworks/Database/StatusesTable.swift @@ -9,7 +9,6 @@ import Foundation import RSCore import RSDatabase -import RSParser import Data final class StatusesTable: DatabaseTable { @@ -25,7 +24,9 @@ final class StatusesTable: DatabaseTable { } func markArticles(_ articles: Set
, statusKey: String, flag: Bool) { - + + // Main thread. + assertNoMissingStatuses(articles) let statuses = Set(articles.flatMap { $0.status }) markArticleStatuses(statuses, statusKey: statusKey, flag: flag) @@ -33,70 +34,75 @@ final class StatusesTable: DatabaseTable { func attachStatuses(_ articles: Set
, _ database: FMDatabase) { + // Look in cache first. attachCachedStatuses(articles) let articlesNeedingStatuses = articlesMissingStatuses(articles) if articlesNeedingStatuses.isEmpty { return } - fetchAndCacheStatusesForArticles(Set(articlesNeedingStatuses)) + // Fetch from database. + fetchAndCacheStatusesForArticles(articlesNeedingStatuses, database) attachCachedStatuses(articlesNeedingStatuses) + // Create new statuses, and cache and save them in the database. // It shouldn’t happen that an Article in the database has no corresponding ArticleStatus, // but the case should be handled anyway. - - - - } - - func attachCachedStatuses(_ articles: Set
) { - - articles.forEach { (oneArticle) in - - if let cachedStatus = cache[oneArticle.databaseID] { - oneArticle.status = cachedStatus - } - else if let oneArticleStatus = oneArticle.status { - cache.add(oneArticleStatus) - } - } - } - - func ensureStatusesForParsedArticles(_ parsedArticles: [ParsedItem], _ callback: @escaping RSVoidCompletionBlock) { - - // 1. Check cache for statuses - // 2. Fetch statuses not found in cache - // 3. Create, save, and cache statuses not found in database - - var articleIDs = Set(parsedArticles.map { $0.articleID }) - articleIDs = articleIDsMissingStatuses(articleIDs) - if articleIDs.isEmpty { - callback() + let articlesNeedingStatusesCreated = articlesMissingStatuses(articlesNeedingStatuses) + if articlesNeedingStatusesCreated.isEmpty { return } - - queue.fetch { (database: FMDatabase!) -> Void in - - let statuses = self.fetchStatusesForArticleIDs(articleIDs, database: database) - - DispatchQueue.main.async { + createAndSaveStatusesForArticles(articlesNeedingStatusesCreated, database) - self.cache.addObjectsNotCached(Array(statuses)) - - let newArticleIDs = self.articleIDsMissingStatuses(articleIDs) - if !newArticleIDs.isEmpty { - self.createAndSaveStatusesForArticleIDs(newArticleIDs) - } - - callback() - } - } + assertNoMissingStatuses(articles) } + + +// func ensureStatusesForParsedArticles(_ parsedArticles: [ParsedItem], _ callback: @escaping RSVoidCompletionBlock) { +// +// // 1. Check cache for statuses +// // 2. Fetch statuses not found in cache +// // 3. Create, save, and cache statuses not found in database +// +// var articleIDs = Set(parsedArticles.map { $0.articleID }) +// articleIDs = articleIDsMissingStatuses(articleIDs) +// if articleIDs.isEmpty { +// callback() +// return +// } +// +// queue.fetch { (database: FMDatabase!) -> Void in +// +// let statuses = self.fetchStatusesForArticleIDs(articleIDs, database: database) +// +// DispatchQueue.main.async { +// +// self.cache.addObjectsNotCached(Array(statuses)) +// +// let newArticleIDs = self.articleIDsMissingStatuses(articleIDs) +// if !newArticleIDs.isEmpty { +// self.createAndSaveStatusesForArticleIDs(newArticleIDs) +// } +// +// callback() +// } +// } +// } } private extension StatusesTable { + func attachCachedStatuses(_ articles: Set
) { + + articles.forEach { (oneArticle) in + + if let cachedStatus = cache[oneArticle.databaseID] { + oneArticle.status = cachedStatus + } + } + } + func assertNoMissingStatuses(_ articles: Set
) { for oneArticle in articles { @@ -108,7 +114,18 @@ private extension StatusesTable { } // MARK: Fetching - + + func fetchAndCacheStatusesForArticles(_ articles: Set
, _ database: FMDatabase) { + + fetchAndCacheStatusesForArticleIDs(articleIDsFromArticles(articles), database) + } + + func fetchAndCacheStatusesForArticleIDs(_ articleIDs: Set, _ database: FMDatabase) { + + let statuses = fetchStatusesForArticleIDs(articleIDs, database) + cache.addObjectsNotCached(Array(statuses)) + } + func fetchStatusesForArticleIDs(_ articleIDs: Set, _ database: FMDatabase) -> Set { if !articleIDs.isEmpty, let resultSet = selectRowsWhere(key: DatabaseKey.articleID, inValues: Array(articleIDs), in: database) { @@ -161,26 +178,37 @@ private extension StatusesTable { // MARK: Creating - func saveStatuses(_ statuses: Set) { + func saveStatuses(_ statuses: Set, _ database: FMDatabase) { let statusArray = statuses.map { $0.databaseDictionary() } - insertRows(statusArray, insertType: .orIgnore) + insertRows(statusArray, insertType: .orIgnore, in: database) } - func createAndSaveStatusesForArticleIDs(_ articleIDs: Set) { + func createAndSaveStatusesForArticles(_ articles: Set
, _ database: FMDatabase) { + + let articleIDs = Set(articles.map { $0.databaseID }) + createAndSaveStatusesForArticleIDs(articleIDs, database) + } + + func createAndSaveStatusesForArticleIDs(_ articleIDs: Set, _ database: FMDatabase) { let now = Date() let statuses = articleIDs.map { ArticleStatus(articleID: $0, dateArrived: now) } cache.addObjectsNotCached(statuses) - saveStatuses(Set(statuses)) + saveStatuses(Set(statuses), database) } // MARK: Utilities - - func articleIDsMissingStatuses(_ articleIDs: Set) -> Set { + + func articleIDsFromArticles(_ articles: Set
) -> Set { + + return Set(articles.map { $0.databaseID }) + } + + func articleIDsMissingCachedStatuses(_ articleIDs: Set) -> Set { - return Set(articleIDs.filter { !cache.objectWithIDIsCached[$0] }) + return Set(articleIDs.filter { !cache.objectWithIDIsCached($0) }) } func articlesMissingStatuses(_ articles: Set
) -> Set
{ @@ -195,11 +223,12 @@ private extension StatusesTable { } } -extension ParsedItem { +//extension ParsedItem { +// +// var articleID: String { +// get { +// return "\(feedURL) \(uniqueID)" //Must be same as Article.articleID +// } +// } +//} - var articleID: String { - get { - return "\(feedURL) \(uniqueID)" //Must be same as Article.articleID - } - } -} diff --git a/Frameworks/RSDatabase/DatabaseTable.swift b/Frameworks/RSDatabase/DatabaseTable.swift index 47e201ab5..c4f50fe1d 100644 --- a/Frameworks/RSDatabase/DatabaseTable.swift +++ b/Frameworks/RSDatabase/DatabaseTable.swift @@ -53,13 +53,10 @@ public extension DatabaseTable { // MARK: Saving - public func insertRows(_ dictionaries: [NSDictionary], insertType: RSDatabaseInsertType) { + public func insertRows(_ dictionaries: [NSDictionary], insertType: RSDatabaseInsertType, in database: FMDatabase) { - queue.update { (database: FMDatabase!) -> Void in - - dictionaries.forEach { (oneDictionary) in - let _ = database.rs_insertRow(with: oneDictionary as [NSObject: AnyObject], insertType: insertType, tableName: self.name) - } + dictionaries.forEach { (oneDictionary) in + let _ = database.rs_insertRow(with: oneDictionary as [NSObject: AnyObject], insertType: insertType, tableName: self.name) } }