Get StatusesTable compiling.

This commit is contained in:
Brent Simmons 2017-08-05 11:12:45 -07:00
parent 9d37d88c2f
commit c30e7eeb99
2 changed files with 94 additions and 68 deletions

View File

@ -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<Article>, 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<Article>, _ 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 shouldnt happen that an Article in the database has no corresponding ArticleStatus,
// but the case should be handled anyway.
}
func attachCachedStatuses(_ articles: Set<Article>) {
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<Article>) {
articles.forEach { (oneArticle) in
if let cachedStatus = cache[oneArticle.databaseID] {
oneArticle.status = cachedStatus
}
}
}
func assertNoMissingStatuses(_ articles: Set<Article>) {
for oneArticle in articles {
@ -108,7 +114,18 @@ private extension StatusesTable {
}
// MARK: Fetching
func fetchAndCacheStatusesForArticles(_ articles: Set<Article>, _ database: FMDatabase) {
fetchAndCacheStatusesForArticleIDs(articleIDsFromArticles(articles), database)
}
func fetchAndCacheStatusesForArticleIDs(_ articleIDs: Set<String>, _ database: FMDatabase) {
let statuses = fetchStatusesForArticleIDs(articleIDs, database)
cache.addObjectsNotCached(Array(statuses))
}
func fetchStatusesForArticleIDs(_ articleIDs: Set<String>, _ database: FMDatabase) -> Set<ArticleStatus> {
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<ArticleStatus>) {
func saveStatuses(_ statuses: Set<ArticleStatus>, _ database: FMDatabase) {
let statusArray = statuses.map { $0.databaseDictionary() }
insertRows(statusArray, insertType: .orIgnore)
insertRows(statusArray, insertType: .orIgnore, in: database)
}
func createAndSaveStatusesForArticleIDs(_ articleIDs: Set<String>) {
func createAndSaveStatusesForArticles(_ articles: Set<Article>, _ database: FMDatabase) {
let articleIDs = Set(articles.map { $0.databaseID })
createAndSaveStatusesForArticleIDs(articleIDs, database)
}
func createAndSaveStatusesForArticleIDs(_ articleIDs: Set<String>, _ 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<String>) -> Set<String> {
func articleIDsFromArticles(_ articles: Set<Article>) -> Set<String> {
return Set(articles.map { $0.databaseID })
}
func articleIDsMissingCachedStatuses(_ articleIDs: Set<String>) -> Set<String> {
return Set(articleIDs.filter { !cache.objectWithIDIsCached[$0] })
return Set(articleIDs.filter { !cache.objectWithIDIsCached($0) })
}
func articlesMissingStatuses(_ articles: Set<Article>) -> Set<Article> {
@ -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
}
}
}

View File

@ -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)
}
}