Make progress on making ArticleStatus a reference type and on making article.status non-optional.

This commit is contained in:
Brent Simmons 2017-09-18 13:17:30 -07:00
parent ab43db7761
commit 6db993075b
5 changed files with 55 additions and 65 deletions

View File

@ -131,19 +131,9 @@ final class ArticlesTable: DatabaseTable {
// MARK: Status
func status(for article: Article) -> ArticleStatus? {
return statusesTable.cachedStatus(for: article.articleID)
}
func mark(_ articles: Set<Article>, _ statusKey: String, _ flag: Bool) {
func statuses(for articles: Set<Article>) -> Set<ArticleStatus> {
return statusesTable.cachedStatuses(for: articles.articleIDs())
}
func mark(_ statuses: Set<ArticleStatus>, _ statusKey: String, _ flag: Bool) {
statusesTable.mark(statuses, statusKey, flag)
statusesTable.mark(articles.statuses(), statusKey, flag)
}
}

View File

@ -70,19 +70,9 @@ public final class Database {
// MARK: - Status
public func status(for article: Article) -> ArticleStatus? {
return articlesTable.status(for: article)
}
public func statuses(for articles: Set<Article>) -> Set<ArticleStatus> {
return articlesTable.statuses(for: articles)
}
public func mark(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
public func mark(_ articles: Set<Article>, statusKey: String, flag: Bool) {
articlesTable.mark(statuses, statusKey, flag)
articlesTable.mark(articles, statusKey, flag)
}
}

View File

@ -156,6 +156,11 @@ extension Set where Element == Article {
return Set<String>(map { $0.databaseID })
}
func statuses() -> Set<ArticleStatus> {
return Set<ArticleStatus>(map { $0.status })
}
func dictionary() -> [String: Article] {
var d = [String: Article]()

View File

@ -12,7 +12,7 @@ import Data
extension ArticleStatus {
init(articleID: String, dateArrived: Date, row: FMResultSet) {
convenience init(articleID: String, dateArrived: Date, row: FMResultSet) {
let read = row.bool(forColumn: DatabaseKey.read)
let starred = row.bool(forColumn: DatabaseKey.starred)

View File

@ -30,42 +30,27 @@ final class StatusesTable: DatabaseTable {
// MARK: Cache
func cachedStatus(for articleID: String) -> ArticleStatus? {
// func cachedStatus(for articleID: String) -> ArticleStatus? {
//
// assert(Thread.isMainThread)
// assert(cache[articleID] != nil)
// return cache[articleID]
// }
//
// func cachedStatuses(for articleIDs: Set<String>) -> Set<ArticleStatus> {
//
// assert(Thread.isMainThread)
//
// var statuses = Set<ArticleStatus>()
// for articleID in articleIDs {
// if let articleStatus = cache[articleID] {
// statuses.insert(articleStatus)
// }
// }
//
// return statuses
// }
assert(Thread.isMainThread)
assert(cache[articleID] != nil)
return cache[articleID]
}
func cachedStatuses(for articleIDs: Set<String>) -> Set<ArticleStatus> {
assert(Thread.isMainThread)
var statuses = Set<ArticleStatus>()
for articleID in articleIDs {
if let articleStatus = cache[articleID] {
statuses.insert(articleStatus)
}
}
return statuses
}
func addIfNotCached(_ statuses: Set<ArticleStatus>) {
if statuses.isEmpty {
return
}
if Thread.isMainThread {
self.cache.addIfNotCached(statuses)
}
else {
DispatchQueue.main.async {
self.cache.addIfNotCached(statuses)
}
}
}
// MARK: Creating/Updating
@ -108,15 +93,13 @@ final class StatusesTable: DatabaseTable {
if status.boolStatus(forKey: statusKey) == flag {
continue
}
var statusCopy = status
statusCopy.setBoolStatus(flag, forKey: statusKey)
updatedStatuses.insert(statusCopy)
status.setBoolStatus(flag, forKey: statusKey)
updatedStatuses.insert(status)
}
if updatedStatuses.isEmpty {
return
}
addToCache(updatedStatuses)
queue.update { (database) in
self.markArticleIDs(updatedStatuses.articleIDs(), statusKey, flag, database)
@ -183,6 +166,22 @@ private extension StatusesTable {
}
}
func addIfNotCached(_ statuses: Set<ArticleStatus>) {
if statuses.isEmpty {
return
}
if Thread.isMainThread {
self.cache.addIfNotCached(statuses)
}
else {
DispatchQueue.main.async {
self.cache.addIfNotCached(statuses)
}
}
}
// MARK: Creating
func saveStatuses(_ statuses: Set<ArticleStatus>) {
@ -231,7 +230,7 @@ private extension StatusesTable {
private final class StatusCache {
// Main thread only.
// Serial database queue only.
var dictionary = [String: ArticleStatus]()
@ -239,6 +238,8 @@ private final class StatusCache {
// Replaces any cached statuses.
assert(!Thread.isMainThread)
for status in statuses {
self[status.articleID] = status
}
@ -248,6 +249,8 @@ private final class StatusCache {
// Does not replace already cached statuses.
assert(!Thread.isMainThread)
for status in statuses {
let articleID = status.articleID
if let _ = self[articleID] {
@ -259,9 +262,11 @@ private final class StatusCache {
subscript(_ articleID: String) -> ArticleStatus? {
get {
assert(!Thread.isMainThread)
return self[articleID]
}
set {
assert(!Thread.isMainThread)
self[articleID] = newValue
}
}