cacheable 0.3.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +108 -142
- package/dist/index.cjs +448 -0
- package/dist/index.d.cts +104 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.js +421 -0
- package/package.json +25 -14
- package/src/index.ts +0 -122
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -109
package/dist/index.js
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Keyv } from "keyv";
|
|
3
|
+
import { Hookified } from "hookified";
|
|
4
|
+
|
|
5
|
+
// src/stats.ts
|
|
6
|
+
var CacheableStats = class {
|
|
7
|
+
_hits = 0;
|
|
8
|
+
_misses = 0;
|
|
9
|
+
_gets = 0;
|
|
10
|
+
_sets = 0;
|
|
11
|
+
_deletes = 0;
|
|
12
|
+
_clears = 0;
|
|
13
|
+
_vsize = 0;
|
|
14
|
+
_ksize = 0;
|
|
15
|
+
_count = 0;
|
|
16
|
+
_enabled = false;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
if (options?.enabled) {
|
|
19
|
+
this._enabled = options.enabled;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
get enabled() {
|
|
23
|
+
return this._enabled;
|
|
24
|
+
}
|
|
25
|
+
set enabled(enabled) {
|
|
26
|
+
this._enabled = enabled;
|
|
27
|
+
}
|
|
28
|
+
get hits() {
|
|
29
|
+
return this._hits;
|
|
30
|
+
}
|
|
31
|
+
get misses() {
|
|
32
|
+
return this._misses;
|
|
33
|
+
}
|
|
34
|
+
get gets() {
|
|
35
|
+
return this._gets;
|
|
36
|
+
}
|
|
37
|
+
get sets() {
|
|
38
|
+
return this._sets;
|
|
39
|
+
}
|
|
40
|
+
get deletes() {
|
|
41
|
+
return this._deletes;
|
|
42
|
+
}
|
|
43
|
+
get clears() {
|
|
44
|
+
return this._clears;
|
|
45
|
+
}
|
|
46
|
+
get vsize() {
|
|
47
|
+
return this._vsize;
|
|
48
|
+
}
|
|
49
|
+
get ksize() {
|
|
50
|
+
return this._ksize;
|
|
51
|
+
}
|
|
52
|
+
get count() {
|
|
53
|
+
return this._count;
|
|
54
|
+
}
|
|
55
|
+
incrementHits() {
|
|
56
|
+
if (!this._enabled) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this._hits++;
|
|
60
|
+
}
|
|
61
|
+
incrementMisses() {
|
|
62
|
+
if (!this._enabled) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this._misses++;
|
|
66
|
+
}
|
|
67
|
+
incrementGets() {
|
|
68
|
+
if (!this._enabled) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this._gets++;
|
|
72
|
+
}
|
|
73
|
+
incrementSets() {
|
|
74
|
+
if (!this._enabled) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this._sets++;
|
|
78
|
+
}
|
|
79
|
+
incrementDeletes() {
|
|
80
|
+
if (!this._enabled) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this._deletes++;
|
|
84
|
+
}
|
|
85
|
+
incrementClears() {
|
|
86
|
+
if (!this._enabled) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this._clears++;
|
|
90
|
+
}
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
92
|
+
incrementVSize(value) {
|
|
93
|
+
if (!this._enabled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this._vsize += this.roughSizeOfObject(value);
|
|
97
|
+
}
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
99
|
+
decreaseVSize(value) {
|
|
100
|
+
if (!this._enabled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this._vsize -= this.roughSizeOfObject(value);
|
|
104
|
+
}
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
106
|
+
incrementKSize(key) {
|
|
107
|
+
if (!this._enabled) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this._ksize += this.roughSizeOfString(key);
|
|
111
|
+
}
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
113
|
+
decreaseKSize(key) {
|
|
114
|
+
if (!this._enabled) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this._ksize -= this.roughSizeOfString(key);
|
|
118
|
+
}
|
|
119
|
+
incrementCount() {
|
|
120
|
+
if (!this._enabled) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this._count++;
|
|
124
|
+
}
|
|
125
|
+
descreaseCount() {
|
|
126
|
+
if (!this._enabled) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this._count--;
|
|
130
|
+
}
|
|
131
|
+
setCount(count) {
|
|
132
|
+
if (!this._enabled) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this._count = count;
|
|
136
|
+
}
|
|
137
|
+
roughSizeOfString(value) {
|
|
138
|
+
return value.length * 2;
|
|
139
|
+
}
|
|
140
|
+
roughSizeOfObject(object) {
|
|
141
|
+
const objectList = [];
|
|
142
|
+
const stack = [object];
|
|
143
|
+
let bytes = 0;
|
|
144
|
+
while (stack.length > 0) {
|
|
145
|
+
const value = stack.pop();
|
|
146
|
+
if (typeof value === "boolean") {
|
|
147
|
+
bytes += 4;
|
|
148
|
+
} else if (typeof value === "string") {
|
|
149
|
+
bytes += value.length * 2;
|
|
150
|
+
} else if (typeof value === "number") {
|
|
151
|
+
bytes += 8;
|
|
152
|
+
} else if (typeof value === "object" && value !== null && !objectList.includes(value)) {
|
|
153
|
+
objectList.push(value);
|
|
154
|
+
for (const key in value) {
|
|
155
|
+
bytes += key.length * 2;
|
|
156
|
+
stack.push(value[key]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return bytes;
|
|
161
|
+
}
|
|
162
|
+
reset() {
|
|
163
|
+
this._hits = 0;
|
|
164
|
+
this._misses = 0;
|
|
165
|
+
this._gets = 0;
|
|
166
|
+
this._sets = 0;
|
|
167
|
+
this._deletes = 0;
|
|
168
|
+
this._clears = 0;
|
|
169
|
+
this._vsize = 0;
|
|
170
|
+
this._ksize = 0;
|
|
171
|
+
this._count = 0;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// src/index.ts
|
|
176
|
+
var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
|
|
177
|
+
CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
|
|
178
|
+
CacheableHooks2["AFTER_SET"] = "AFTER_SET";
|
|
179
|
+
CacheableHooks2["BEFORE_SET_MANY"] = "BEFORE_SET_MANY";
|
|
180
|
+
CacheableHooks2["AFTER_SET_MANY"] = "AFTER_SET_MANY";
|
|
181
|
+
CacheableHooks2["BEFORE_GET"] = "BEFORE_GET";
|
|
182
|
+
CacheableHooks2["AFTER_GET"] = "AFTER_GET";
|
|
183
|
+
CacheableHooks2["BEFORE_GET_MANY"] = "BEFORE_GET_MANY";
|
|
184
|
+
CacheableHooks2["AFTER_GET_MANY"] = "AFTER_GET_MANY";
|
|
185
|
+
return CacheableHooks2;
|
|
186
|
+
})(CacheableHooks || {});
|
|
187
|
+
var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
|
|
188
|
+
CacheableEvents2["ERROR"] = "error";
|
|
189
|
+
return CacheableEvents2;
|
|
190
|
+
})(CacheableEvents || {});
|
|
191
|
+
var Cacheable = class extends Hookified {
|
|
192
|
+
_primary = new Keyv();
|
|
193
|
+
_secondary;
|
|
194
|
+
_nonBlocking = false;
|
|
195
|
+
_stats = new CacheableStats({ enabled: false });
|
|
196
|
+
constructor(options) {
|
|
197
|
+
super();
|
|
198
|
+
if (options?.primary) {
|
|
199
|
+
this.setPrimary(options.primary);
|
|
200
|
+
}
|
|
201
|
+
if (options?.secondary) {
|
|
202
|
+
this.setSecondary(options.secondary);
|
|
203
|
+
}
|
|
204
|
+
if (options?.nonBlocking) {
|
|
205
|
+
this._nonBlocking = options.nonBlocking;
|
|
206
|
+
}
|
|
207
|
+
if (options?.stats) {
|
|
208
|
+
this._stats.enabled = options.stats;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
get stats() {
|
|
212
|
+
return this._stats;
|
|
213
|
+
}
|
|
214
|
+
get primary() {
|
|
215
|
+
return this._primary;
|
|
216
|
+
}
|
|
217
|
+
set primary(primary) {
|
|
218
|
+
this._primary = primary;
|
|
219
|
+
}
|
|
220
|
+
get secondary() {
|
|
221
|
+
return this._secondary;
|
|
222
|
+
}
|
|
223
|
+
set secondary(secondary) {
|
|
224
|
+
this._secondary = secondary;
|
|
225
|
+
}
|
|
226
|
+
get nonBlocking() {
|
|
227
|
+
return this._nonBlocking;
|
|
228
|
+
}
|
|
229
|
+
set nonBlocking(nonBlocking) {
|
|
230
|
+
this._nonBlocking = nonBlocking;
|
|
231
|
+
}
|
|
232
|
+
setPrimary(primary) {
|
|
233
|
+
this._primary = primary instanceof Keyv ? primary : new Keyv(primary);
|
|
234
|
+
}
|
|
235
|
+
setSecondary(secondary) {
|
|
236
|
+
this._secondary = secondary instanceof Keyv ? secondary : new Keyv(secondary);
|
|
237
|
+
}
|
|
238
|
+
async get(key) {
|
|
239
|
+
let result;
|
|
240
|
+
try {
|
|
241
|
+
await this.hook("BEFORE_GET" /* BEFORE_GET */, key);
|
|
242
|
+
result = await this._primary.get(key);
|
|
243
|
+
if (!result && this._secondary) {
|
|
244
|
+
result = await this._secondary.get(key);
|
|
245
|
+
if (result) {
|
|
246
|
+
await this._primary.set(key, result);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
await this.hook("AFTER_GET" /* AFTER_GET */, { key, result });
|
|
250
|
+
} catch (error) {
|
|
251
|
+
await this.emit("error" /* ERROR */, error);
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
async getMany(keys) {
|
|
256
|
+
let result = [];
|
|
257
|
+
try {
|
|
258
|
+
await this.hook("BEFORE_GET_MANY" /* BEFORE_GET_MANY */, keys);
|
|
259
|
+
result = await this._primary.get(keys);
|
|
260
|
+
if (this._secondary) {
|
|
261
|
+
const missingKeys = [];
|
|
262
|
+
for (const [i, key] of keys.entries()) {
|
|
263
|
+
if (!result[i]) {
|
|
264
|
+
missingKeys.push(key);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const secondaryResult = await this._secondary.get(missingKeys);
|
|
268
|
+
for (const [i, key] of keys.entries()) {
|
|
269
|
+
if (!result[i] && secondaryResult[i]) {
|
|
270
|
+
result[i] = secondaryResult[i];
|
|
271
|
+
await this._primary.set(key, secondaryResult[i]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
await this.hook("AFTER_GET_MANY" /* AFTER_GET_MANY */, { keys, result });
|
|
276
|
+
} catch (error) {
|
|
277
|
+
await this.emit("error" /* ERROR */, error);
|
|
278
|
+
}
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
async set(key, value, ttl) {
|
|
282
|
+
let result = false;
|
|
283
|
+
try {
|
|
284
|
+
await this.hook("BEFORE_SET" /* BEFORE_SET */, { key, value, ttl });
|
|
285
|
+
const promises = [];
|
|
286
|
+
promises.push(this._primary.set(key, value, ttl));
|
|
287
|
+
if (this._secondary) {
|
|
288
|
+
promises.push(this._secondary.set(key, value, ttl));
|
|
289
|
+
}
|
|
290
|
+
if (this._nonBlocking) {
|
|
291
|
+
result = await Promise.race(promises);
|
|
292
|
+
} else {
|
|
293
|
+
const results = await Promise.all(promises);
|
|
294
|
+
result = results[0];
|
|
295
|
+
}
|
|
296
|
+
await this.hook("AFTER_SET" /* AFTER_SET */, { key, value, ttl });
|
|
297
|
+
} catch (error) {
|
|
298
|
+
await this.emit("error" /* ERROR */, error);
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
async setMany(items) {
|
|
303
|
+
let result = false;
|
|
304
|
+
try {
|
|
305
|
+
await this.hook("BEFORE_SET_MANY" /* BEFORE_SET_MANY */, items);
|
|
306
|
+
result = await this.setManyKeyv(this._primary, items);
|
|
307
|
+
if (this._secondary) {
|
|
308
|
+
if (this._nonBlocking) {
|
|
309
|
+
this.setManyKeyv(this._secondary, items);
|
|
310
|
+
} else {
|
|
311
|
+
await this.setManyKeyv(this._secondary, items);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
await this.hook("AFTER_SET_MANY" /* AFTER_SET_MANY */, items);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
await this.emit("error" /* ERROR */, error);
|
|
317
|
+
}
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
async take(key) {
|
|
321
|
+
const result = await this.get(key);
|
|
322
|
+
await this.delete(key);
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
async takeMany(keys) {
|
|
326
|
+
const result = await this.getMany(keys);
|
|
327
|
+
await this.deleteMany(keys);
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
async has(key) {
|
|
331
|
+
let result = await this._primary.has(key);
|
|
332
|
+
if (!result && this._secondary) {
|
|
333
|
+
result = await this._secondary.has(key);
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
async hasMany(keys) {
|
|
338
|
+
const result = await this.hasManyKeyv(this._primary, keys);
|
|
339
|
+
const missingKeys = [];
|
|
340
|
+
for (const [i, key] of keys.entries()) {
|
|
341
|
+
if (!result[i] && this._secondary) {
|
|
342
|
+
missingKeys.push(key);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (missingKeys.length > 0 && this._secondary) {
|
|
346
|
+
const secondary = await this.hasManyKeyv(this._secondary, keys);
|
|
347
|
+
for (const [i, key] of keys.entries()) {
|
|
348
|
+
if (!result[i] && secondary[i]) {
|
|
349
|
+
result[i] = secondary[i];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return result;
|
|
354
|
+
}
|
|
355
|
+
async delete(key) {
|
|
356
|
+
const result = await this._primary.delete(key);
|
|
357
|
+
if (this._secondary) {
|
|
358
|
+
if (this._nonBlocking) {
|
|
359
|
+
this._secondary.delete(key);
|
|
360
|
+
} else {
|
|
361
|
+
await this._secondary.delete(key);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
async deleteMany(keys) {
|
|
367
|
+
const result = await this.deleteManyKeyv(this._primary, keys);
|
|
368
|
+
if (this._secondary) {
|
|
369
|
+
if (this._nonBlocking) {
|
|
370
|
+
this.deleteManyKeyv(this._secondary, keys);
|
|
371
|
+
} else {
|
|
372
|
+
await this.deleteManyKeyv(this._secondary, keys);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
async clear() {
|
|
378
|
+
const promises = [];
|
|
379
|
+
promises.push(this._primary.clear());
|
|
380
|
+
if (this._secondary) {
|
|
381
|
+
promises.push(this._secondary.clear());
|
|
382
|
+
}
|
|
383
|
+
await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
|
|
384
|
+
}
|
|
385
|
+
async disconnect() {
|
|
386
|
+
const promises = [];
|
|
387
|
+
promises.push(this._primary.disconnect());
|
|
388
|
+
if (this._secondary) {
|
|
389
|
+
promises.push(this._secondary.disconnect());
|
|
390
|
+
}
|
|
391
|
+
await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
|
|
392
|
+
}
|
|
393
|
+
async deleteManyKeyv(keyv, keys) {
|
|
394
|
+
const promises = [];
|
|
395
|
+
for (const key of keys) {
|
|
396
|
+
promises.push(keyv.delete(key));
|
|
397
|
+
}
|
|
398
|
+
await Promise.all(promises);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
async setManyKeyv(keyv, items) {
|
|
402
|
+
const promises = [];
|
|
403
|
+
for (const item of items) {
|
|
404
|
+
promises.push(keyv.set(item.key, item.value, item.ttl));
|
|
405
|
+
}
|
|
406
|
+
await Promise.all(promises);
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
async hasManyKeyv(keyv, keys) {
|
|
410
|
+
const promises = [];
|
|
411
|
+
for (const key of keys) {
|
|
412
|
+
promises.push(keyv.has(key));
|
|
413
|
+
}
|
|
414
|
+
return Promise.all(promises);
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
export {
|
|
418
|
+
Cacheable,
|
|
419
|
+
CacheableEvents,
|
|
420
|
+
CacheableHooks
|
|
421
|
+
};
|
package/package.json
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacheable",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Simple Caching Engine using Keyv",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
6
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"require": "./dist/index.cjs",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"repository": "https://github.com/jaredwray/cacheable.git",
|
|
8
16
|
"author": "Jared Wray <me@jaredwray.com>",
|
|
9
17
|
"license": "MIT",
|
|
10
18
|
"private": false,
|
|
11
19
|
"devDependencies": {
|
|
12
|
-
"
|
|
20
|
+
"@keyv/redis": "^3.0.1",
|
|
21
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
22
|
+
"lru-cache": "^10.4.3",
|
|
23
|
+
"rimraf": "^6.0.1",
|
|
13
24
|
"ts-node": "^10.9.2",
|
|
25
|
+
"tsup": "^8.2.4",
|
|
14
26
|
"typescript": "^5.5.4",
|
|
27
|
+
"vitest": "^2.1.1",
|
|
15
28
|
"xo": "^0.59.3"
|
|
16
29
|
},
|
|
17
30
|
"dependencies": {
|
|
18
|
-
"
|
|
19
|
-
"hookified": "^0.7.0",
|
|
31
|
+
"hookified": "^0.7.1",
|
|
20
32
|
"keyv": "^5.0.1"
|
|
21
33
|
},
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
27
38
|
"scripts": {
|
|
28
|
-
"build": "
|
|
29
|
-
"test": "xo --fix",
|
|
30
|
-
"test:ci": "xo",
|
|
31
|
-
"clean": "
|
|
39
|
+
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
40
|
+
"test": "xo --fix && vitest run --coverage",
|
|
41
|
+
"test:ci": "xo && vitest run",
|
|
42
|
+
"clean": "rimraf ./dist ./coverage ./node_modules"
|
|
32
43
|
}
|
|
33
44
|
}
|
package/src/index.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import {Keyv} from 'keyv';
|
|
2
|
-
import {Hookified} from 'hookified';
|
|
3
|
-
|
|
4
|
-
type CacheableStatsItem = {
|
|
5
|
-
key: string;
|
|
6
|
-
lastAccessed: number;
|
|
7
|
-
accessCount: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
type CacheableStats = {
|
|
11
|
-
cacheSize: number;
|
|
12
|
-
currentSize: number;
|
|
13
|
-
hits: number;
|
|
14
|
-
misses: number;
|
|
15
|
-
hitRate: number;
|
|
16
|
-
averageLoadPenalty: number;
|
|
17
|
-
loadSuccessCount: number;
|
|
18
|
-
loadExceptionCount: number;
|
|
19
|
-
totalLoadTime: number;
|
|
20
|
-
topHits: CacheableStatsItem[];
|
|
21
|
-
leastUsed: CacheableStatsItem[];
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export enum CacheableHooks {
|
|
25
|
-
BEFORE_SET = 'beforeSet',
|
|
26
|
-
AFTER_SET = 'afterSet',
|
|
27
|
-
BEFORE_SET_MANY = 'beforeSetMany',
|
|
28
|
-
AFTER_SET_MANY = 'afterSetMany',
|
|
29
|
-
BEFORE_GET = 'beforeGet',
|
|
30
|
-
AFTER_GET = 'afterGet',
|
|
31
|
-
BEFORE_GET_MANY = 'beforeGetMany',
|
|
32
|
-
AFTER_GET_MANY = 'afterGetMany',
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export enum CacheableEvents {
|
|
36
|
-
ERROR = 'error',
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export enum CacheableTieringModes {
|
|
40
|
-
PRIMARY_WITH_FAILOVER = 'primarySecondary',
|
|
41
|
-
ACID = 'allPrimary',
|
|
42
|
-
PRIMARY_ALL_FAILOVER = 'primaryAllFailover',
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type CacheableOptions = {
|
|
46
|
-
store?: Keyv;
|
|
47
|
-
enableStats?: boolean;
|
|
48
|
-
enableOffline?: boolean;
|
|
49
|
-
nonBlocking?: boolean;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export class Cacheable extends Hookified {
|
|
53
|
-
private _store: Keyv = new Keyv();
|
|
54
|
-
private readonly _stats: CacheableStats = {
|
|
55
|
-
currentSize: 0, cacheSize: 0, hits: 0, misses: 0, hitRate: 0, averageLoadPenalty: 0, loadSuccessCount: 0, loadExceptionCount: 0, totalLoadTime: 0, topHits: [], leastUsed: [],
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
private _enableStats = false;
|
|
59
|
-
private _enableOffline = false;
|
|
60
|
-
|
|
61
|
-
constructor(keyv?: Keyv) {
|
|
62
|
-
super();
|
|
63
|
-
|
|
64
|
-
if (keyv) {
|
|
65
|
-
this._store = keyv;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public get enableStats(): boolean {
|
|
70
|
-
return this._enableStats;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
public set enableStats(enabled: boolean) {
|
|
74
|
-
this._enableStats = enabled;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
public get enableOffline(): boolean {
|
|
78
|
-
return this._enableOffline;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public set enableOffline(enabled: boolean) {
|
|
82
|
-
this._enableOffline = enabled;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public get store(): Keyv {
|
|
86
|
-
return this._store;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public set store(keyv: Keyv) {
|
|
90
|
-
this._store = keyv;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public get stats(): CacheableStats {
|
|
94
|
-
return this._stats;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public async get<T>(key: string): Promise<T | undefined> {
|
|
98
|
-
let result;
|
|
99
|
-
try {
|
|
100
|
-
await this.hook(CacheableHooks.BEFORE_GET, key);
|
|
101
|
-
result = await this._store.get(key) as T;
|
|
102
|
-
await this.hook(CacheableHooks.AFTER_GET, {key, result});
|
|
103
|
-
} catch (error: unknown) {
|
|
104
|
-
await this.emit(CacheableEvents.ERROR, error);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return result;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
|
|
111
|
-
let result = false;
|
|
112
|
-
try {
|
|
113
|
-
await this.hook(CacheableHooks.BEFORE_SET, {key, value, ttl});
|
|
114
|
-
result = await this._store.set(key, value, ttl);
|
|
115
|
-
await this.hook(CacheableHooks.AFTER_SET, {key, value, ttl});
|
|
116
|
-
} catch (error: unknown) {
|
|
117
|
-
await this.emit(CacheableEvents.ERROR, error);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return result;
|
|
121
|
-
}
|
|
122
|
-
}
|
package/tsconfig.build.json
DELETED