From a10f8c78c4f465749725dc77ef57aaa2fd785fe3 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 6 Nov 2025 10:22:53 +0100 Subject: [PATCH] add cache system --- LeStorage/StoredCollection.swift | 41 +++++++++++++++++++++++++++----- LeStorage/SyncedCollection.swift | 9 +++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index 2247ff5..3f3c08e 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -212,7 +212,7 @@ public class StoredCollection: SomeCollection { /// Sets a collection of items and indexes them func setItems(_ items: [T]) { - self.items.removeAll() + self.clear() for item in items { self._addItem(instance: item) } @@ -277,7 +277,7 @@ public class StoredCollection: SomeCollection { defer { self.requestWriteIfNecessary() } - self.items.removeAll() + self.clear() self._addItem(instance: instance) } @@ -333,7 +333,8 @@ public class StoredCollection: SomeCollection { self.addPendingOperation(method: .add, instance: instance, actionOption: actionOption) return false } - + self.invalidateCache() + self._affectStoreIdIfNecessary(instance: instance) self.items.append(instance) instance.store = self.store @@ -359,6 +360,7 @@ public class StoredCollection: SomeCollection { self.addPendingOperation(method: .update, instance: instance, actionOption: actionOption) return false } + self.invalidateCache() let item = self.items[index] if item !== instance { @@ -408,6 +410,7 @@ public class StoredCollection: SomeCollection { } func localDeleteOnly(instance: T) { + self.invalidateCache() self.items.removeAll { $0.id == instance.id } self._indexes?.removeValue(forKey: instance.id) } @@ -437,12 +440,12 @@ public class StoredCollection: SomeCollection { return self.items.first(where: { $0.id == id }) } - /// Proceeds to "hard" delete the items without synchronizing them - /// Also removes related API calls + /// Deletes a list of items public func deleteDependencies(_ items: any Sequence) { defer { self.requestWriteIfNecessary() } + self.invalidateCache() let itemsArray = Array(items) // fix error if items is self.items for item in itemsArray { if let index = self.items.firstIndex(where: { $0.id == item.id }) { @@ -534,12 +537,13 @@ public class StoredCollection: SomeCollection { /// Simply clears the items of the collection public func clear() { + self.invalidateCache() self.items.removeAll() } /// Removes the items of the collection and deletes the corresponding file public func reset() { - self.items.removeAll() + self.clear() self.store.removeFile(type: T.self) } @@ -572,6 +576,31 @@ public class StoredCollection: SomeCollection { } } + // MARK: - Cached queries + + fileprivate var _cacheVersion = 0 + fileprivate var _queryCache: [AnyHashable: (version: Int, result: Any)] = [:] + + // Generic query method with caching + public func cached( + key: AnyHashable, + compute: ([T]) -> Result + ) -> Result { + if let cached = self._queryCache[key], + cached.version == self._cacheVersion, + let result = cached.result as? Result { + return result + } + + let result = compute(items) + self._queryCache[key] = (self._cacheVersion, result) + return result + } + + private func invalidateCache() { + self._cacheVersion += 1 + } + } extension StoredCollection: RandomAccessCollection { diff --git a/LeStorage/SyncedCollection.swift b/LeStorage/SyncedCollection.swift index da047d0..c1dbc2c 100644 --- a/LeStorage/SyncedCollection.swift +++ b/LeStorage/SyncedCollection.swift @@ -417,6 +417,15 @@ public class SyncedCollection: SomeSyncedCollection, Collect self.collection.requestWriteIfNecessary() } + // MARK: - Cached queries + + public func cached( + key: AnyHashable, + compute: ([T]) -> Result + ) -> Result { + return self.collection.cached(key: key, compute: compute) + } + } class OperationBatch {