7
7
*/
8
8
9
9
import SyncPromise from 'core/promise/sync' ;
10
+ import { unimplement } from 'core/functools' ;
10
11
import type { SyncStorageNamespace , AsyncStorageNamespace } from 'core/kv-storage' ;
11
12
12
13
import type Cache from 'core/cache/interface' ;
@@ -44,6 +45,11 @@ export default class PersistentWrapper<T extends Cache<string, V>, V = unknown>
44
45
*/
45
46
protected readonly fetchedItems : Set < string > = new Set ( ) ;
46
47
48
+ /**
49
+ * Object with incom
50
+ */
51
+ protected readonly opts ?: PersistentOptions ;
52
+
47
53
/**
48
54
* @param cache - cache object to wrap
49
55
* @param storage - storage object to save cache items
@@ -54,6 +60,7 @@ export default class PersistentWrapper<T extends Cache<string, V>, V = unknown>
54
60
55
61
this . cache = cache ;
56
62
this . wrappedCache = Object . create ( cache ) ;
63
+ this . opts = opts ;
57
64
58
65
this . engine = new engines [ opts ?. loadFromStorage ?? 'onDemand' ] < V > ( storage ) ;
59
66
}
@@ -82,47 +89,115 @@ export default class PersistentWrapper<T extends Cache<string, V>, V = unknown>
82
89
subscribe
83
90
} = addEmitter < T , string , V > ( this . cache ) ;
84
91
85
- this . wrappedCache . has = this . getDefaultImplementation ( 'has' ) ;
86
- this . wrappedCache . get = this . getDefaultImplementation ( 'get' ) ;
87
-
88
- this . wrappedCache . set = async ( key : string , value : V , opts ?: PersistentTTLDecoratorOptions & Parameters < T [ 'set' ] > [ 2 ] ) => {
89
- const
90
- ttl = opts ?. persistentTTL ?? this . ttl ;
91
-
92
- this . fetchedItems . add ( key ) ;
93
-
94
- const
95
- res = originalSet ( key , value , opts ) ;
92
+ const descriptor = {
93
+ enumerable : false ,
94
+ writable : true ,
95
+ configurable : true
96
+ } ;
96
97
97
- if ( this . cache . has ( key ) ) {
98
- await this . engine . set ( key , value , ttl ) ;
99
- }
98
+ Object . defineProperties ( this . wrappedCache , {
99
+ has : {
100
+ value : this . getDefaultImplementation ( 'has' ) ,
101
+ ...descriptor
102
+ } ,
100
103
101
- return res ;
102
- } ;
104
+ get : {
105
+ value : this . getDefaultImplementation ( 'get' ) ,
106
+ ...descriptor
107
+ } ,
103
108
104
- this . wrappedCache . remove = async ( key : string ) => {
105
- this . fetchedItems . add ( key ) ;
106
- await this . engine . remove ( key ) ;
107
- return originalRemove ( key ) ;
108
- } ;
109
+ set : {
110
+ value : async ( key : string , value : V , opts ?: PersistentTTLDecoratorOptions & Parameters < T [ 'set' ] > [ 2 ] ) => {
111
+ const
112
+ ttl = opts ?. persistentTTL ?? this . ttl ;
109
113
110
- this . wrappedCache . keys = ( ) => SyncPromise . resolve ( this . cache . keys ( ) ) ;
114
+ this . fetchedItems . add ( key ) ;
111
115
112
- this . wrappedCache . clear = async ( filter ?: ClearFilter < V > ) => {
113
- const
114
- removed = originalClear ( filter ) ,
115
- removedKeys : string [ ] = [ ] ;
116
+ const
117
+ res = originalSet ( key , value , opts ) ;
116
118
117
- removed . forEach ( ( _ , key ) => {
118
- removedKeys . push ( key ) ;
119
- } ) ;
119
+ if ( this . cache . has ( key ) ) {
120
+ await this . engine . set ( key , value , ttl ) ;
121
+ }
120
122
121
- await Promise . allSettled ( removedKeys . map ( ( key ) => this . engine . remove ( key ) ) ) ;
122
- return removed ;
123
- } ;
123
+ return res ;
124
+ } ,
125
+ ...descriptor
126
+ } ,
124
127
125
- this . wrappedCache . removePersistentTTLFrom = ( key ) => this . engine . removeTTLFrom ( key ) ;
128
+ remove : {
129
+ value : async ( key : string ) => {
130
+ this . fetchedItems . add ( key ) ;
131
+ await this . engine . remove ( key ) ;
132
+ return originalRemove ( key ) ;
133
+ } ,
134
+ ...descriptor
135
+ } ,
136
+
137
+ keys : {
138
+ value : ( ) => SyncPromise . resolve ( this . cache . keys ( ) ) ,
139
+ ...descriptor
140
+ } ,
141
+
142
+ clear : {
143
+ value : async ( filter ?: ClearFilter < V > ) => {
144
+ const
145
+ removed = originalClear ( filter ) ,
146
+ removedKeys : string [ ] = [ ] ;
147
+
148
+ removed . forEach ( ( _ , key ) => {
149
+ removedKeys . push ( key ) ;
150
+ } ) ;
151
+
152
+ await Promise . allSettled ( removedKeys . map ( ( key ) => this . engine . remove ( key ) ) ) ;
153
+ return removed ;
154
+ } ,
155
+ ...descriptor
156
+ } ,
157
+
158
+ clone : {
159
+ value : ( ) => {
160
+ unimplement ( {
161
+ type : 'function' ,
162
+ alternative : { name : 'cloneTo' }
163
+ } , this . wrappedCache . clone ) ;
164
+ } ,
165
+ ...descriptor
166
+ } ,
167
+
168
+ cloneTo : {
169
+ value : async (
170
+ storage : SyncStorageNamespace | AsyncStorageNamespace
171
+ ) : Promise < PersistentCache < string , V > > => {
172
+ const
173
+ cache = new PersistentWrapper < Cache < string , V > , V > ( this . cache . clone ( ) , storage , { ...this . opts } ) ;
174
+
175
+ Object . defineProperties ( cache , {
176
+ fetchedItems : {
177
+ value : new Set ( this . fetchedItems )
178
+ }
179
+ } ) ;
180
+
181
+ for ( const [ key , value ] of this . cache . entries ( ) ) {
182
+ const
183
+ ttl = this . engine . ttlIndex [ key ] ?? 0 ,
184
+ time = Date . now ( ) ;
185
+
186
+ if ( ttl > time ) {
187
+ await cache . engine . set ( key , value , ttl - time ) ;
188
+ }
189
+ }
190
+
191
+ return cache . getInstance ( ) ;
192
+ } ,
193
+ ...descriptor
194
+ } ,
195
+
196
+ removePersistentTTLFrom : {
197
+ value : ( key ) => this . engine . removeTTLFrom ( key ) ,
198
+ ...descriptor
199
+ }
200
+ } ) ;
126
201
127
202
subscribe ( 'remove' , this . wrappedCache , ( { args} ) =>
128
203
this . engine . remove ( args [ 0 ] ) ) ;
@@ -135,6 +210,8 @@ export default class PersistentWrapper<T extends Cache<string, V>, V = unknown>
135
210
subscribe ( 'clear' , this . wrappedCache , ( { result} ) => {
136
211
result . forEach ( ( _ , key ) => this . engine . remove ( key ) ) ;
137
212
} ) ;
213
+
214
+ subscribe ( 'clone' , this . wrappedCache , ( ) => this . wrappedCache . clone ( ) ) ;
138
215
}
139
216
140
217
/**
0 commit comments