Do things. I forget what, since it was yesterday or whatever. Progress, anyway.
This commit is contained in:
parent
c76d42b42f
commit
b756f39cbe
@ -36,6 +36,11 @@ public final class ArticleStatus: Hashable {
|
|||||||
self.hashValue = articleID.hashValue
|
self.hashValue = articleID.hashValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public convenience init(articleID: String, dateArrived: Date) {
|
||||||
|
|
||||||
|
init(articleID: articleID, read: false, starred: false, userDeleted: false, dateArrived: dateArrived, accountInfo: nil)
|
||||||
|
}
|
||||||
|
|
||||||
public func boolStatus(forKey key: String) -> Bool {
|
public func boolStatus(forKey key: String) -> Bool {
|
||||||
|
|
||||||
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
|
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
|
||||||
|
@ -46,6 +46,10 @@ final class StatusesTable: DatabaseTable {
|
|||||||
|
|
||||||
func ensureStatusesForParsedArticles(_ parsedArticles: [ParsedItem], _ callback: @escaping RSVoidCompletionBlock) {
|
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 })
|
var articleIDs = Set(parsedArticles.map { $0.articleID })
|
||||||
articleIDs = articleIDsMissingStatuses(articleIDs)
|
articleIDs = articleIDsMissingStatuses(articleIDs)
|
||||||
if articleIDs.isEmpty {
|
if articleIDs.isEmpty {
|
||||||
@ -62,11 +66,17 @@ final class StatusesTable: DatabaseTable {
|
|||||||
self.cache.addObjectsNotCached(Array(statuses))
|
self.cache.addObjectsNotCached(Array(statuses))
|
||||||
|
|
||||||
let newArticleIDs = self.articleIDsMissingStatuses(articleIDs)
|
let newArticleIDs = self.articleIDsMissingStatuses(articleIDs)
|
||||||
self.createStatusForNewArticleIDs(newArticleIDs)
|
if !newArticleIDs.isEmpty {
|
||||||
|
self.createAndSaveStatusesForArticleIDs(newArticleIDs)
|
||||||
|
}
|
||||||
|
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension StatusesTable {
|
||||||
|
|
||||||
func assertNoMissingStatuses(_ articles: Set<Article>) {
|
func assertNoMissingStatuses(_ articles: Set<Article>) {
|
||||||
|
|
||||||
@ -77,30 +87,6 @@ final class StatusesTable: DatabaseTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private extension StatusesTable {
|
|
||||||
|
|
||||||
// MARK: Marking
|
|
||||||
|
|
||||||
func markArticleStatuses(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
|
|
||||||
|
|
||||||
// Ignore the statuses where status.[statusKey] == flag. Update the remainder and save in database.
|
|
||||||
|
|
||||||
var articleIDs = Set<String>()
|
|
||||||
|
|
||||||
statuses.forEach { (oneStatus) in
|
|
||||||
|
|
||||||
if oneStatus.boolStatus(forKey: statusKey) != flag {
|
|
||||||
oneStatus.setBoolStatus(flag, forKey: statusKey)
|
|
||||||
articleIDs.insert(oneStatus.articleID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !articleIDs.isEmpty {
|
|
||||||
updateArticleStatusesInDatabase(articleIDs, statusKey: statusKey, flag: flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Fetching
|
// MARK: Fetching
|
||||||
|
|
||||||
@ -126,12 +112,27 @@ private extension StatusesTable {
|
|||||||
return statuses
|
return statuses
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Saving
|
// MARK: Updating
|
||||||
|
|
||||||
func saveStatuses(_ statuses: Set<ArticleStatus>) {
|
func markArticleStatuses(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
|
||||||
|
|
||||||
let statusArray = statuses.map { $0.databaseDictionary() }
|
// Ignore the statuses where status.[statusKey] == flag. Update the remainder and save in database.
|
||||||
insertRows(statusArray, insertType: .orIgnore)
|
|
||||||
|
var articleIDsToUpdate = Set<String>()
|
||||||
|
|
||||||
|
statuses.forEach { (oneStatus) in
|
||||||
|
|
||||||
|
if oneStatus.boolStatus(forKey: statusKey) == flag {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
oneStatus.setBoolStatus(flag, forKey: statusKey)
|
||||||
|
articleIDsToUpdate.insert(oneStatus.articleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !articleIDsToUpdate.isEmpty {
|
||||||
|
updateArticleStatusesInDatabase(articleIDsToUpdate, statusKey: statusKey, flag: flag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateArticleStatusesInDatabase(_ articleIDs: Set<String>, statusKey: String, flag: Bool) {
|
private func updateArticleStatusesInDatabase(_ articleIDs: Set<String>, statusKey: String, flag: Bool) {
|
||||||
@ -141,30 +142,26 @@ private extension StatusesTable {
|
|||||||
|
|
||||||
// MARK: Creating
|
// MARK: Creating
|
||||||
|
|
||||||
func createStatusForNewArticleIDs(_ articleIDs: Set<String>) {
|
func saveStatuses(_ statuses: Set<ArticleStatus>) {
|
||||||
|
|
||||||
|
let statusArray = statuses.map { $0.databaseDictionary() }
|
||||||
|
insertRows(statusArray, insertType: .orIgnore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAndSaveStatusesForArticleIDs(_ articleIDs: Set<String>) {
|
||||||
|
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let statuses = articleIDs.map { (oneArticleID) -> ArticleStatus in
|
let statuses = articleIDs.map { ArticleStatus(articleID: $0, dateArrived: now) }
|
||||||
return ArticleStatus(articleID: oneArticleID, read: false, starred: false, userDeleted: false, dateArrived: now)
|
|
||||||
}
|
|
||||||
cache.addObjectsNotCached(statuses)
|
cache.addObjectsNotCached(statuses)
|
||||||
|
|
||||||
queue.update { (database: FMDatabase!) -> Void in
|
saveStatuses(Set(statuses))
|
||||||
|
|
||||||
let falseValue = NSNumber(value: false)
|
|
||||||
|
|
||||||
articleIDs.forEach { (oneArticleID) in
|
|
||||||
|
|
||||||
let _ = database.executeUpdate("insert or ignore into statuses (read, articleID, starred, userDeleted, dateArrived) values (?, ?, ?, ?, ?)", withArgumentsIn:[falseValue, oneArticleID as NSString, falseValue, falseValue, now])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Utilities
|
// MARK: Utilities
|
||||||
|
|
||||||
func articleIDsMissingStatuses(_ articleIDs: Set<String>) -> Set<String> {
|
func articleIDsMissingStatuses(_ articleIDs: Set<String>) -> Set<String> {
|
||||||
|
|
||||||
return Set(articleIDs.filter { cache[$0] == nil })
|
return Set(articleIDs.filter { !objectWithIDIsCached[$0] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// Not thread-safe.
|
||||||
|
|
||||||
public final class ObjectCache<T> {
|
public final class ObjectCache<T> {
|
||||||
|
|
||||||
private let keyPathForID: KeyPath<T,String>
|
private let keyPathForID: KeyPath<T,String>
|
||||||
@ -60,7 +62,7 @@ public final class ObjectCache<T> {
|
|||||||
// When an object is not already cached, cache it,
|
// When an object is not already cached, cache it,
|
||||||
// then consider that version the unique version.
|
// then consider that version the unique version.
|
||||||
|
|
||||||
return objects.map({ (object) -> T in
|
return objects.map { (object) -> T in
|
||||||
|
|
||||||
let identifier = identifierForObject(object)
|
let identifier = identifierForObject(object)
|
||||||
if let cachedObject = self[identifier] {
|
if let cachedObject = self[identifier] {
|
||||||
@ -68,7 +70,15 @@ public final class ObjectCache<T> {
|
|||||||
}
|
}
|
||||||
add(object)
|
add(object)
|
||||||
return object
|
return object
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func objectWithIDIsCached(_ identifier: String) -> Bool {
|
||||||
|
|
||||||
|
if let _ = self[identifier] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscript(_ identifier: String) -> T? {
|
public subscript(_ identifier: String) -> T? {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user