mirror of
https://github.com/hyperoslo/Cache.git
synced 2026-04-07 19:17:36 +00:00
Implement store observations
This commit is contained in:
@@ -135,6 +135,12 @@
|
||||
D5A138C11EB29BFA00881A20 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */; };
|
||||
D5A138C21EB29BFA00881A20 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */; };
|
||||
D5A138C41EB29C2100881A20 /* NSImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C31EB29C2100881A20 /* NSImage+Extensions.swift */; };
|
||||
D5A9D1B721134547005DBD3F /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; };
|
||||
D5A9D1B821134547005DBD3F /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; };
|
||||
D5A9D1B921134547005DBD3F /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; };
|
||||
D5A9D1BB211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1BA211345D4005DBD3F /* Dictionary+Extensions.swift */; };
|
||||
D5A9D1BC211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1BA211345D4005DBD3F /* Dictionary+Extensions.swift */; };
|
||||
D5A9D1BD211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1BA211345D4005DBD3F /* Dictionary+Extensions.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -222,6 +228,8 @@
|
||||
D5643E361C43F2CC00582E17 /* Storage.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Storage.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D5A138C31EB29C2100881A20 /* NSImage+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSImage+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D5A9D1B621134547005DBD3F /* ObservationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservationToken.swift; sourceTree = "<group>"; };
|
||||
D5A9D1BA211345D4005DBD3F /* Dictionary+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D5DC59E01C20593E003BD79B /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
EBAACA991FBC369300FA206E /* SimpleStorage.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SimpleStorage.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -310,6 +318,7 @@
|
||||
children = (
|
||||
D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */,
|
||||
D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */,
|
||||
D5A9D1BA211345D4005DBD3F /* Dictionary+Extensions.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@@ -333,6 +342,7 @@
|
||||
D270148F20D1251E003B45C7 /* TypeWrapper.swift */,
|
||||
D270149320D125AC003B45C7 /* MemoryCapsule.swift */,
|
||||
D27014A420D129EB003B45C7 /* TransformerFactory.swift */,
|
||||
D5A9D1B621134547005DBD3F /* ObservationToken.swift */,
|
||||
);
|
||||
path = Library;
|
||||
sourceTree = "<group>";
|
||||
@@ -806,12 +816,14 @@
|
||||
D270147220D1018A003B45C7 /* Transformer.swift in Sources */,
|
||||
D21B668C1F6A723C00125DE1 /* Types.swift in Sources */,
|
||||
D2D4CC261FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */,
|
||||
D5A9D1BD211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */,
|
||||
D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */,
|
||||
D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */,
|
||||
D292DAFF1F6A970B0060F614 /* Result.swift in Sources */,
|
||||
D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */,
|
||||
D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */,
|
||||
D21B668B1F6A723C00125DE1 /* StorageError.swift in Sources */,
|
||||
D5A9D1B921134547005DBD3F /* ObservationToken.swift in Sources */,
|
||||
D270148A20D11040003B45C7 /* Storage+Transform.swift in Sources */,
|
||||
D5A138C21EB29BFA00881A20 /* UIImage+Extensions.swift in Sources */,
|
||||
D21B66851F6A723C00125DE1 /* DataSerializer.swift in Sources */,
|
||||
@@ -887,12 +899,14 @@
|
||||
D270147120D1018A003B45C7 /* Transformer.swift in Sources */,
|
||||
D21B66831F6A723C00125DE1 /* Types.swift in Sources */,
|
||||
D2D4CC251FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */,
|
||||
D5A9D1BC211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */,
|
||||
D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */,
|
||||
D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */,
|
||||
D292DAFE1F6A970B0060F614 /* Result.swift in Sources */,
|
||||
D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */,
|
||||
D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */,
|
||||
D21B66821F6A723C00125DE1 /* StorageError.swift in Sources */,
|
||||
D5A9D1B821134547005DBD3F /* ObservationToken.swift in Sources */,
|
||||
D270148920D11040003B45C7 /* Storage+Transform.swift in Sources */,
|
||||
D5A138C41EB29C2100881A20 /* NSImage+Extensions.swift in Sources */,
|
||||
D21B667C1F6A723C00125DE1 /* DataSerializer.swift in Sources */,
|
||||
@@ -937,12 +951,14 @@
|
||||
D2CF98601F694FFA00CE8F68 /* DiskConfig.swift in Sources */,
|
||||
D270147020D1018A003B45C7 /* Transformer.swift in Sources */,
|
||||
D292DAFD1F6A970B0060F614 /* Result.swift in Sources */,
|
||||
D5A9D1BB211345D4005DBD3F /* Dictionary+Extensions.swift in Sources */,
|
||||
D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */,
|
||||
D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */,
|
||||
D270147C20D107DA003B45C7 /* SyncStorage.swift in Sources */,
|
||||
D2CF98671F694FFA00CE8F68 /* Expiry.swift in Sources */,
|
||||
D270148820D11040003B45C7 /* Storage+Transform.swift in Sources */,
|
||||
D2CF986A1F694FFA00CE8F68 /* StorageError.swift in Sources */,
|
||||
D5A9D1B721134547005DBD3F /* ObservationToken.swift in Sources */,
|
||||
D5A138C11EB29BFA00881A20 /* UIImage+Extensions.swift in Sources */,
|
||||
D270147820D1046A003B45C7 /* HybridStorage.swift in Sources */,
|
||||
D270148420D10E76003B45C7 /* AsyncStorage.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import Foundation
|
||||
|
||||
extension Dictionary where Key == UUID {
|
||||
mutating func insert(_ value: Value) -> UUID {
|
||||
let id = UUID()
|
||||
self[id] = value
|
||||
return id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
final class ObservationToken {
|
||||
private let cancellationClosure: () -> Void
|
||||
|
||||
init(cancellationClosure: @escaping () -> Void) {
|
||||
self.cancellationClosure = cancellationClosure
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
cancellationClosure()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
import Foundation
|
||||
import Dispatch
|
||||
|
||||
enum StoreChange {
|
||||
case addition
|
||||
case singleDeletion
|
||||
case allDeletion
|
||||
case expiredDeletion
|
||||
}
|
||||
|
||||
/// Manage storage. Use memory storage if specified.
|
||||
/// Synchronous by default. Use `async` for asynchronous operations.
|
||||
public class Storage<T> {
|
||||
@@ -8,6 +15,17 @@ public class Storage<T> {
|
||||
let syncStorage: SyncStorage<T>
|
||||
let asyncStorage: AsyncStorage<T>
|
||||
|
||||
private var observations = [UUID : (Storage, StoreChange) -> Void]()
|
||||
|
||||
@discardableResult
|
||||
func observeChanges(using closure: @escaping (Storage, StoreChange) -> Void) -> ObservationToken {
|
||||
let id = observations.insert(closure)
|
||||
|
||||
return ObservationToken { [weak self] in
|
||||
self?.observations.removeValue(forKey: id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize storage with configuration options.
|
||||
///
|
||||
/// - Parameters:
|
||||
@@ -56,14 +74,26 @@ extension Storage: StorageAware {
|
||||
|
||||
public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws {
|
||||
try self.syncStorage.setObject(object, forKey: key, expiry: expiry)
|
||||
notifyObservers(of: .addition)
|
||||
}
|
||||
|
||||
public func removeAll() throws {
|
||||
try self.syncStorage.removeAll()
|
||||
notifyObservers(of: .allDeletion)
|
||||
}
|
||||
|
||||
public func removeExpiredObjects() throws {
|
||||
try self.syncStorage.removeExpiredObjects()
|
||||
notifyObservers(of: .expiredDeletion)
|
||||
}
|
||||
|
||||
private func notifyObservers(of change: StoreChange) {
|
||||
observations.values.forEach { [weak self] closure in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
closure(strongSelf, change)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user