From 6db993075b7a365d6c0dd9ef2f1794b4d2e90820 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 18 Sep 2017 13:17:30 -0700 Subject: [PATCH] Make progress on making ArticleStatus a reference type and on making article.status non-optional. --- Frameworks/Database/ArticlesTable.swift | 14 +-- Frameworks/Database/Database.swift | 14 +-- .../Extensions/Article+Database.swift | 5 ++ .../Extensions/ArticleStatus+Database.swift | 2 +- Frameworks/Database/StatusesTable.swift | 85 ++++++++++--------- 5 files changed, 55 insertions(+), 65 deletions(-) diff --git a/Frameworks/Database/ArticlesTable.swift b/Frameworks/Database/ArticlesTable.swift index 668ca4f18..0747a3408 100644 --- a/Frameworks/Database/ArticlesTable.swift +++ b/Frameworks/Database/ArticlesTable.swift @@ -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
, _ statusKey: String, _ flag: Bool) { - func statuses(for articles: Set
) -> Set { - - return statusesTable.cachedStatuses(for: articles.articleIDs()) - } - - func mark(_ statuses: Set, _ statusKey: String, _ flag: Bool) { - - statusesTable.mark(statuses, statusKey, flag) + statusesTable.mark(articles.statuses(), statusKey, flag) } } diff --git a/Frameworks/Database/Database.swift b/Frameworks/Database/Database.swift index e100ae07d..10faebb03 100644 --- a/Frameworks/Database/Database.swift +++ b/Frameworks/Database/Database.swift @@ -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
) -> Set { - - return articlesTable.statuses(for: articles) - } - - public func mark(_ statuses: Set, statusKey: String, flag: Bool) { + public func mark(_ articles: Set
, statusKey: String, flag: Bool) { - articlesTable.mark(statuses, statusKey, flag) + articlesTable.mark(articles, statusKey, flag) } } diff --git a/Frameworks/Database/Extensions/Article+Database.swift b/Frameworks/Database/Extensions/Article+Database.swift index e26db7cba..673a93afc 100644 --- a/Frameworks/Database/Extensions/Article+Database.swift +++ b/Frameworks/Database/Extensions/Article+Database.swift @@ -156,6 +156,11 @@ extension Set where Element == Article { return Set(map { $0.databaseID }) } + func statuses() -> Set { + + return Set(map { $0.status }) + } + func dictionary() -> [String: Article] { var d = [String: Article]() diff --git a/Frameworks/Database/Extensions/ArticleStatus+Database.swift b/Frameworks/Database/Extensions/ArticleStatus+Database.swift index fab48ccdc..dc78dbc57 100644 --- a/Frameworks/Database/Extensions/ArticleStatus+Database.swift +++ b/Frameworks/Database/Extensions/ArticleStatus+Database.swift @@ -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) diff --git a/Frameworks/Database/StatusesTable.swift b/Frameworks/Database/StatusesTable.swift index f3d7a911d..54b5f8d46 100644 --- a/Frameworks/Database/StatusesTable.swift +++ b/Frameworks/Database/StatusesTable.swift @@ -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) -> Set { +// +// assert(Thread.isMainThread) +// +// var statuses = Set() +// 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) -> Set { - - assert(Thread.isMainThread) - - var statuses = Set() - for articleID in articleIDs { - if let articleStatus = cache[articleID] { - statuses.insert(articleStatus) - } - } - - return statuses - } - - func addIfNotCached(_ statuses: Set) { - - 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) { + + 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) { @@ -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 } }