feat: added cache layer to the Store (#2696)

This commit is contained in:
Serhiy Mytrovtsiy
2025-09-18 22:51:07 +02:00
parent 0d48f9f75f
commit 602112d30f

View File

@@ -14,58 +14,90 @@ import Cocoa
public class Store {
public static let shared = Store()
private let defaults = UserDefaults.standard
private var cache: [String: Any] = [:]
private let cacheQueue = DispatchQueue(label: "eu.exelban.Stats.Store.cache", attributes: .concurrent)
public init() {}
public init() {
self.loadCache()
}
private func loadCache() {
guard let bundleId = Bundle.main.bundleIdentifier,
let domain = self.defaults.persistentDomain(forName: bundleId) else { return }
self.cache = domain
}
private func getValue<T>(for key: String, type: T.Type) -> T? {
return self.cacheQueue.sync {
return self.cache[key] as? T
}
}
private func setValue(_ value: Any?, for key: String) {
self.cacheQueue.async(flags: .barrier) {
self.cache[key] = value
}
if let value = value {
self.defaults.set(value, forKey: key)
} else {
self.defaults.removeObject(forKey: key)
}
}
public func exist(key: String) -> Bool {
return self.defaults.object(forKey: key) == nil ? false : true
return self.getValue(for: key, type: Any.self) != nil
}
public func remove(_ key: String) {
self.defaults.removeObject(forKey: key)
self.setValue(nil, for: key)
}
public func bool(key: String, defaultValue value: Bool) -> Bool {
return !self.exist(key: key) ? value : defaults.bool(forKey: key)
return self.getValue(for: key, type: Bool.self) ?? value
}
public func string(key: String, defaultValue value: String) -> String {
return (!self.exist(key: key) ? value : defaults.string(forKey: key))!
return self.getValue(for: key, type: String.self) ?? value
}
public func int(key: String, defaultValue value: Int) -> Int {
return (!self.exist(key: key) ? value : defaults.integer(forKey: key))
return self.getValue(for: key, type: Int.self) ?? value
}
public func array(key: String, defaultValue value: [Any]) -> [Any] {
return (!self.exist(key: key) ? value : defaults.array(forKey: key)!)
return self.getValue(for: key, type: [Any].self) ?? value
}
public func data(key: String) -> Data? {
return defaults.data(forKey: key)
return self.getValue(for: key, type: Data.self)
}
public func set(key: String, value: Bool) {
self.defaults.set(value, forKey: key)
self.setValue(value, for: key)
}
public func set(key: String, value: String) {
self.defaults.set(value, forKey: key)
self.setValue(value, for: key)
}
public func set(key: String, value: Int) {
self.defaults.set(value, forKey: key)
self.setValue(value, for: key)
}
public func set(key: String, value: Data) {
self.defaults.set(value, forKey: key)
self.setValue(value, for: key)
}
public func set(key: String, value: [Any]) {
self.defaults.set(value, forKey: key)
self.setValue(value, for: key)
}
public func reset() {
self.cacheQueue.async(flags: .barrier) {
self.cache.removeAll()
}
self.defaults.dictionaryRepresentation().keys.forEach { key in
self.defaults.removeObject(forKey: key)
}
@@ -81,17 +113,22 @@ public class Store {
}
public func `import`(from url: URL) {
guard let id = Bundle.main.bundleIdentifier, let dict = NSDictionary(contentsOf: url) as? [String: Any] else { return }
guard let id = Bundle.main.bundleIdentifier,
let dict = NSDictionary(contentsOf: url) as? [String: Any] else { return }
var importedDict = dict
let keysToPreserve = ["telemetry_id", "access_token", "refresh_token"]
var importedDict = dict
for key in keysToPreserve {
if let existingValue = self.defaults.string(forKey: key) {
if let existingValue = getValue(for: key, type: String.self) {
importedDict[key] = existingValue
}
}
self.cacheQueue.async(flags: .barrier) {
self.cache = importedDict
}
self.defaults.setPersistentDomain(importedDict, forName: id)
restartApp(self)
}