11import Foundation
22
3- protocol StorageChangeNotifier {
4- func notifyObservers( about change: StorageChange )
5- }
6-
7- struct KeyChangeNotifier < T> {
8-
9-
10- func notifyObserver( about change: KeyChange < T > , where closure: ( ( String ) -> Bool ) ) {
11-
12- }
13- }
14-
15-
163/// Use both memory and disk storage. Try on memory first.
174public final class HybridStorage < T> {
185 public let memoryStorage : MemoryStorage < T >
196 public let diskStorage : DiskStorage < T >
20- let storageObservationRegistry = ObservationRegistry < StorageChange > ( )
21- let keyObservationRegistry = ObservationRegistry < KeyChange < T > > ( )
227
23- var onKeyChange : ( ( KeyChange < T > , ( ( String ) -> Bool ) ) -> Void ) ?
8+ private var observations = (
9+ storage: [ UUID : ( HybridStorage , StorageChange ) -> Void ] ( ) ,
10+ key: [ String : ( HybridStorage , KeyChange < T > ) -> Void ] ( )
11+ )
2412
2513 public init ( memoryStorage: MemoryStorage < T > , diskStorage: DiskStorage < T > ) {
2614 self . memoryStorage = memoryStorage
@@ -32,7 +20,7 @@ public final class HybridStorage<T> {
3220 }
3321
3422 private func handleRemovedObject( at path: String ) {
35- keyObservationRegistry . notifyObserver ( about: . remove) { key in
23+ notifyObserver ( about: . remove) { key in
3624 let fileName = diskStorage. makeFileName ( for: key)
3725 return path. contains ( fileName)
3826 }
@@ -55,13 +43,13 @@ extension HybridStorage: StorageAware {
5543 memoryStorage. removeObject ( forKey: key)
5644 try diskStorage. removeObject ( forKey: key)
5745
58- storageObservationRegistry . notifyAllObservers ( about: . remove( key: key) )
46+ notifyStorageObservers ( about: . remove( key: key) )
5947 }
6048
6149 public func setObject( _ object: T , forKey key: String , expiry: Expiry ? = nil ) throws {
6250 var keyChange : KeyChange < T > ?
6351
64- if !keyObservationRegistry . isEmpty {
52+ if observations . key [ key ] != nil {
6553 keyChange = . edit( before: try ? self . object ( forKey: key) , after: object)
6654 }
6755
@@ -70,25 +58,25 @@ extension HybridStorage: StorageAware {
7058
7159
7260 if let change = keyChange {
73- keyObservationRegistry . notifyObserver ( forKey: key, about: change)
61+ notifyObserver ( forKey: key, about: change)
7462 }
7563
76- storageObservationRegistry . notifyAllObservers ( about: . add( key: key) )
64+ notifyStorageObservers ( about: . add( key: key) )
7765 }
7866
7967 public func removeAll( ) throws {
8068 memoryStorage. removeAll ( )
8169 try diskStorage. removeAll ( )
8270
83- storageObservationRegistry . notifyAllObservers ( about: . removeAll)
84- keyObservationRegistry . notifyAllObservers ( about: . remove)
71+ notifyStorageObservers ( about: . removeAll)
72+ notifyKeyObservers ( about: . remove)
8573 }
8674
8775 public func removeExpiredObjects( ) throws {
8876 memoryStorage. removeExpiredObjects ( )
8977 try diskStorage. removeExpiredObjects ( )
9078
91- storageObservationRegistry . notifyAllObservers ( about: . removeExpired)
79+ notifyStorageObservers ( about: . removeExpired)
9280 }
9381}
9482
@@ -102,3 +90,59 @@ public extension HybridStorage {
10290 return storage
10391 }
10492}
93+
94+ extension HybridStorage : StorageObservationRegistry {
95+ @discardableResult
96+ public func observeStorage( using closure: @escaping ( HybridStorage , StorageChange ) -> Void ) -> ObservationToken {
97+ let id = UUID ( )
98+ observations. storage [ id] = closure
99+
100+ return ObservationToken { [ weak self] in
101+ self ? . observations. storage. removeValue ( forKey: id)
102+ }
103+ }
104+
105+ public func removeAllStorageObservations( ) {
106+ observations. storage. removeAll ( )
107+ }
108+
109+ private func notifyStorageObservers( about change: StorageChange ) {
110+ observations. storage. values. forEach { closure in
111+ closure ( self , change)
112+ }
113+ }
114+ }
115+
116+ extension HybridStorage : KeyObservationRegistry {
117+ @discardableResult
118+ public func observeKey( _ key: String , using closure: @escaping ( HybridStorage , KeyChange < T > ) -> Void ) -> ObservationToken {
119+ observations. key [ key] = closure
120+
121+ return ObservationToken { [ weak self] in
122+ self ? . observations. key. removeValue ( forKey: key)
123+ }
124+ }
125+
126+ public func removeObservation( forKey key: String ) {
127+ observations. key. removeValue ( forKey: key)
128+ }
129+
130+ public func removeAllKeyObservations( ) {
131+ observations. key. removeAll ( )
132+ }
133+
134+ private func notifyObserver( forKey key: String , about change: KeyChange < T > ) {
135+ observations. key [ key] ? ( self , change)
136+ }
137+
138+ private func notifyObserver( about change: KeyChange < T > , whereKey closure: ( ( String ) -> Bool ) ) {
139+ let observation = observations. key. first { key, value in closure ( key) } ? . value
140+ observation ? ( self , change)
141+ }
142+
143+ private func notifyKeyObservers( about change: KeyChange < T > ) {
144+ observations. key. values. forEach { closure in
145+ closure ( self , change)
146+ }
147+ }
148+ }
0 commit comments