cachimbo 0.0.1 → 0.0.3
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/README.md +26 -21
- package/dist/index.cjs +149 -38
- package/dist/index.d.cts +88 -16
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +88 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -38
- package/dist/index.js.map +1 -1
- package/package.json +24 -21
package/README.md
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
<
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img width="200" src="https://raw.githubusercontent.com/Guichaguri/cachimbo/main/docs/assets/cachimbo.png">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">Cachimbo</h1>
|
|
4
6
|
|
|
5
|
-
Cachimbo is
|
|
7
|
+
Cachimbo is an advanced caching library that allows you to layer different strategies in order to maximize the performance.
|
|
6
8
|
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
11
|
- Supports external cache stores
|
|
10
12
|
- Redis
|
|
13
|
+
- Valkey
|
|
11
14
|
- Memcached
|
|
12
15
|
- Cloudflare Workers KV
|
|
16
|
+
- Keyv
|
|
13
17
|
- Supports in-memory cache stores
|
|
14
|
-
- Least Recently Used (LRU)
|
|
15
|
-
- Time
|
|
16
|
-
-
|
|
18
|
+
- Least Recently Used (LRU) eviction
|
|
19
|
+
- Time-based (TTL) eviction
|
|
20
|
+
- FIFO eviction
|
|
17
21
|
- Supports intermediary cache strategies
|
|
18
22
|
- Request coalescing (deduplication)
|
|
19
23
|
- Multi-layer caching (tiered cache)
|
|
20
24
|
- Stale-While-Revalidate
|
|
25
|
+
- TTL jittering
|
|
21
26
|
- Metrics collection
|
|
22
27
|
- Easily extendable
|
|
23
28
|
|
|
@@ -65,25 +70,25 @@ In-memory caches offer extremely low latency since data is stored directly in th
|
|
|
65
70
|
|
|
66
71
|
External caches (like Redis, Memcached, etc) provide fast, scalable, shared storage that can be accessed across multiple application instances. They offer high throughput, larger memory capacity, and centralized cache management beyond what in-memory caches can reliably provide.
|
|
67
72
|
|
|
68
|
-
- [In-memory](
|
|
69
|
-
- [Redis](docs/stores/redis-valkey.md) (and Valkey)
|
|
70
|
-
- [Memcached](
|
|
71
|
-
- [Cloudflare Workers KV](
|
|
72
|
-
- [Keyv](
|
|
73
|
+
- [In-memory](/docs/stores/in-memory.md)
|
|
74
|
+
- [Redis](/docs/stores/redis-valkey.md) (and Valkey)
|
|
75
|
+
- [Memcached](/docs/stores/memcached.md)
|
|
76
|
+
- [Cloudflare Workers KV](/docs/stores/cloudflare-workers-kv.md)
|
|
77
|
+
- [Keyv](/docs/stores/keyv.md)
|
|
73
78
|
|
|
74
79
|
## Cache Layers
|
|
75
80
|
|
|
76
81
|
These layers work just like "middlewares" but for caches, they customize how a cache is handled.
|
|
77
82
|
|
|
78
|
-
- [Request Coalescing](
|
|
79
|
-
- [Tiered Caching](
|
|
80
|
-
- [Stale-While-Revalidate](
|
|
81
|
-
- [TTL Jittering](
|
|
82
|
-
- [Async/Lazy Initialization](
|
|
83
|
-
- [Key Transformation](
|
|
84
|
-
- [Metrics Collection](
|
|
83
|
+
- [Request Coalescing](/docs/layers/request-coalescing.md) (deduplication)
|
|
84
|
+
- [Tiered Caching](/docs/layers/tiered.md) (multi-layer caching)
|
|
85
|
+
- [Stale-While-Revalidate](/docs/layers/stale-while-revalidate.md)
|
|
86
|
+
- [TTL Jittering](/docs/layers/jittering.md)
|
|
87
|
+
- [Async/Lazy Initialization](/docs/layers/async-lazy.md)
|
|
88
|
+
- [Key Transformation](/docs/layers/key-transformation.md)
|
|
89
|
+
- [Metrics Collection](/docs/layers/metrics-collection.md)
|
|
85
90
|
|
|
86
91
|
## Guides
|
|
87
|
-
- [Choosing the right combination of layers](
|
|
88
|
-
- [Disabling cache](
|
|
89
|
-
- [Extending](
|
|
92
|
+
- [Choosing the right combination of layers](/docs/guides/choosing-layers.md)
|
|
93
|
+
- [Disabling cache](/docs/guides/disabling.md)
|
|
94
|
+
- [Extending](/docs/guides/extending.md)
|
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,67 @@ var BaseCache = class {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/base/local.ts
|
|
45
|
+
var BaseLocalCache = class extends BaseCache {
|
|
46
|
+
disposeListeners = [];
|
|
47
|
+
/**
|
|
48
|
+
* Reads cached resources by their keys. (synchronous version)
|
|
49
|
+
* @protected
|
|
50
|
+
*/
|
|
51
|
+
_getMany(keys) {
|
|
52
|
+
return Object.fromEntries(keys.map((key) => [key, this._get(key)]));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Writes resources into cache. (synchronous version)
|
|
56
|
+
* @protected
|
|
57
|
+
*/
|
|
58
|
+
_setMany(data, options) {
|
|
59
|
+
for (const [key, value] of Object.entries(data)) this._set(key, value, options);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Deletes many cached resources by their keys. (synchronous version)
|
|
63
|
+
* @protected
|
|
64
|
+
*/
|
|
65
|
+
_deleteMany(keys) {
|
|
66
|
+
for (const key of keys) this._delete(key);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Adds a listener that will be called when a cached item is disposed.
|
|
70
|
+
*
|
|
71
|
+
* @param listener The listener function to add.
|
|
72
|
+
* @protected
|
|
73
|
+
*/
|
|
74
|
+
_addDisposeListener(listener) {
|
|
75
|
+
this.disposeListeners.push(listener);
|
|
76
|
+
}
|
|
77
|
+
get(key) {
|
|
78
|
+
return Promise.resolve(this._get(key));
|
|
79
|
+
}
|
|
80
|
+
set(key, value, options) {
|
|
81
|
+
this._set(key, value, options);
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
delete(key) {
|
|
85
|
+
this._delete(key);
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
}
|
|
88
|
+
getMany(keys) {
|
|
89
|
+
return Promise.resolve(this._getMany(keys));
|
|
90
|
+
}
|
|
91
|
+
setMany(data, options) {
|
|
92
|
+
this._setMany(data, options);
|
|
93
|
+
return Promise.resolve();
|
|
94
|
+
}
|
|
95
|
+
deleteMany(keys) {
|
|
96
|
+
this._deleteMany(keys);
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
}
|
|
99
|
+
onDispose(key, value, reason) {
|
|
100
|
+
for (const listener of this.disposeListeners) listener(key, value, reason);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
43
104
|
//#endregion
|
|
44
105
|
//#region src/local/lru/index.ts
|
|
45
106
|
/**
|
|
@@ -49,7 +110,7 @@ var BaseCache = class {
|
|
|
49
110
|
*
|
|
50
111
|
* Once the limit of items is reached, the least recently used items will be purged.
|
|
51
112
|
*/
|
|
52
|
-
var LocalLRUCache = class extends
|
|
113
|
+
var LocalLRUCache = class extends BaseLocalCache {
|
|
53
114
|
cache;
|
|
54
115
|
shouldUseFetch;
|
|
55
116
|
constructor(options = {}) {
|
|
@@ -62,16 +123,29 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
62
123
|
ttl: options.ttl ? options.ttl * 1e3 : void 0,
|
|
63
124
|
max: options.max || 1e4,
|
|
64
125
|
ttlAutopurge: false,
|
|
65
|
-
fetchMethod: (_key, _staleValue, options$1) => options$1.context()
|
|
126
|
+
fetchMethod: (_key, _staleValue, options$1) => options$1.context(),
|
|
127
|
+
disposeAfter: (value, key, reason) => this.onDispose(key, value, reason)
|
|
66
128
|
});
|
|
67
129
|
this.shouldUseFetch = true;
|
|
68
130
|
}
|
|
69
131
|
}
|
|
70
|
-
|
|
132
|
+
/** @internal */
|
|
133
|
+
_get(key) {
|
|
71
134
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
72
135
|
const data = this.cache.get(key);
|
|
73
136
|
return data === void 0 ? null : data;
|
|
74
137
|
}
|
|
138
|
+
/** @internal */
|
|
139
|
+
_set(key, value, options) {
|
|
140
|
+
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
141
|
+
const ttl = options?.ttl;
|
|
142
|
+
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
143
|
+
}
|
|
144
|
+
/** @internal */
|
|
145
|
+
_delete(key) {
|
|
146
|
+
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
147
|
+
this.cache.delete(key);
|
|
148
|
+
}
|
|
75
149
|
getOrLoad(key, load, options) {
|
|
76
150
|
if (!this.shouldUseFetch) return super.getOrLoad(key, load, options);
|
|
77
151
|
this.logger?.debug(this.name, "[getOrLoad] Running LRUCache's fetch...", "key =", key);
|
|
@@ -81,15 +155,6 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
81
155
|
ttl: ttl ? ttl * 1e3 : void 0
|
|
82
156
|
});
|
|
83
157
|
}
|
|
84
|
-
async set(key, value, options) {
|
|
85
|
-
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
86
|
-
const ttl = options?.ttl;
|
|
87
|
-
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
88
|
-
}
|
|
89
|
-
async delete(key) {
|
|
90
|
-
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
91
|
-
this.cache.delete(key);
|
|
92
|
-
}
|
|
93
158
|
};
|
|
94
159
|
|
|
95
160
|
//#endregion
|
|
@@ -99,27 +164,31 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
99
164
|
*
|
|
100
165
|
* Once the limit of items is reached, the soonest expiring items will be purged.
|
|
101
166
|
*/
|
|
102
|
-
var LocalTTLCache = class extends
|
|
167
|
+
var LocalTTLCache = class extends BaseLocalCache {
|
|
103
168
|
cache;
|
|
104
169
|
constructor(options = {}) {
|
|
105
170
|
super(options);
|
|
106
171
|
if ("cache" in options) this.cache = options.cache;
|
|
107
172
|
else this.cache = new __isaacs_ttlcache.TTLCache({
|
|
108
173
|
max: options.max,
|
|
109
|
-
ttl: options.ttl ? options.ttl * 1e3 : void 0
|
|
174
|
+
ttl: options.ttl ? options.ttl * 1e3 : void 0,
|
|
175
|
+
dispose: (value, key, reason) => this.onDispose(key, value, reason)
|
|
110
176
|
});
|
|
111
177
|
}
|
|
112
|
-
|
|
178
|
+
/** @internal */
|
|
179
|
+
_get(key) {
|
|
113
180
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
114
181
|
const data = this.cache.get(key);
|
|
115
182
|
return data === void 0 ? null : data;
|
|
116
183
|
}
|
|
117
|
-
|
|
184
|
+
/** @internal */
|
|
185
|
+
_set(key, value, options) {
|
|
118
186
|
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
119
187
|
const ttl = options?.ttl;
|
|
120
188
|
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
121
189
|
}
|
|
122
|
-
|
|
190
|
+
/** @internal */
|
|
191
|
+
_delete(key) {
|
|
123
192
|
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
124
193
|
this.cache.delete(key);
|
|
125
194
|
}
|
|
@@ -132,9 +201,10 @@ var LocalTTLCache = class extends BaseCache {
|
|
|
132
201
|
*
|
|
133
202
|
* It ignores expiration times, but a limit of cached items can be set.
|
|
134
203
|
*
|
|
204
|
+
* It implements a simple FIFO eviction policy:
|
|
135
205
|
* Once the limit of items is reached, the first inserted keys will be purged.
|
|
136
206
|
*/
|
|
137
|
-
var LocalMapCache = class extends
|
|
207
|
+
var LocalMapCache = class extends BaseLocalCache {
|
|
138
208
|
cache;
|
|
139
209
|
max;
|
|
140
210
|
constructor(options = {}) {
|
|
@@ -142,38 +212,55 @@ var LocalMapCache = class extends BaseCache {
|
|
|
142
212
|
this.cache = options.cache ?? /* @__PURE__ */ new Map();
|
|
143
213
|
this.max = options.max ?? Infinity;
|
|
144
214
|
}
|
|
145
|
-
|
|
215
|
+
/** @internal */
|
|
216
|
+
_get(key) {
|
|
146
217
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
147
218
|
const data = this.cache.get(key);
|
|
148
219
|
return data === void 0 ? null : data;
|
|
149
220
|
}
|
|
150
|
-
|
|
221
|
+
/** @internal */
|
|
222
|
+
_set(key, value, options) {
|
|
151
223
|
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
152
|
-
|
|
224
|
+
const previousValue = this.cache.get(key);
|
|
225
|
+
if (this.cache.size >= this.max && previousValue === void 0) this.evict(1);
|
|
153
226
|
this.cache.set(key, value);
|
|
227
|
+
this.onDispose(key, previousValue, "set");
|
|
154
228
|
}
|
|
155
|
-
|
|
229
|
+
/** @internal */
|
|
230
|
+
_delete(key) {
|
|
156
231
|
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
232
|
+
const previousValue = this.cache.get(key);
|
|
157
233
|
this.cache.delete(key);
|
|
234
|
+
this.onDispose(key, previousValue, "delete");
|
|
158
235
|
}
|
|
159
236
|
async setMany(data, options) {
|
|
160
237
|
this.logger?.debug(this.name, "[setMany]", "data =", data);
|
|
161
238
|
const entries = Object.entries(data);
|
|
162
239
|
const newEntries = entries.filter(([key]) => !this.cache.has(key)).length;
|
|
163
240
|
if (this.cache.size + newEntries > this.max) this.evict(this.cache.size + newEntries - this.max);
|
|
164
|
-
for (const [key, value] of entries)
|
|
241
|
+
for (const [key, value] of entries) {
|
|
242
|
+
const previousValue = this.cache.get(key);
|
|
243
|
+
this.cache.set(key, value);
|
|
244
|
+
this.onDispose(key, previousValue, "set");
|
|
245
|
+
}
|
|
165
246
|
}
|
|
166
247
|
clear() {
|
|
167
248
|
this.logger?.debug(this.name, "[clear]");
|
|
249
|
+
for (const key of this.cache.keys()) this.onDispose(key, this.cache.get(key), "delete");
|
|
168
250
|
this.cache.clear();
|
|
169
251
|
}
|
|
252
|
+
onDispose(key, value, reason) {
|
|
253
|
+
if (value !== void 0) super.onDispose(key, value, reason);
|
|
254
|
+
}
|
|
170
255
|
evict(length) {
|
|
171
256
|
const keys = this.cache.keys();
|
|
172
257
|
for (let i = 0; i < length; i++) {
|
|
173
258
|
const key = keys.next();
|
|
174
259
|
if (key.done) break;
|
|
175
260
|
this.logger?.debug(this.name, "[evict]", "key = ", key);
|
|
261
|
+
const previousValue = this.cache.get(key.value);
|
|
176
262
|
this.cache.delete(key.value);
|
|
263
|
+
this.onDispose(key.value, previousValue, "evict");
|
|
177
264
|
}
|
|
178
265
|
}
|
|
179
266
|
};
|
|
@@ -182,7 +269,7 @@ var LocalMapCache = class extends BaseCache {
|
|
|
182
269
|
//#region src/local/noop/index.ts
|
|
183
270
|
/**
|
|
184
271
|
* A cache implementation that does nothing.
|
|
185
|
-
* It's useful for disabling cache.
|
|
272
|
+
* It's useful for disabling cache and unit testing.
|
|
186
273
|
*
|
|
187
274
|
* @example
|
|
188
275
|
* ```ts
|
|
@@ -214,12 +301,14 @@ var NoOpCache = class {
|
|
|
214
301
|
var IORedisCache = class extends BaseCache {
|
|
215
302
|
client;
|
|
216
303
|
defaultTTL;
|
|
304
|
+
isUNLINKSupported;
|
|
217
305
|
isMSETEXSupported;
|
|
218
306
|
constructor(options) {
|
|
219
307
|
super(options);
|
|
220
308
|
this.client = options.client;
|
|
221
309
|
this.defaultTTL = options.defaultTTL;
|
|
222
|
-
this.
|
|
310
|
+
this.isUNLINKSupported = options.isUNLINKSupported ?? true;
|
|
311
|
+
this.isMSETEXSupported = options.isMSETEXSupported ?? false;
|
|
223
312
|
}
|
|
224
313
|
async get(key) {
|
|
225
314
|
this.logger?.debug(this.name, "[get] Running \"GET\" command...", "key =", key);
|
|
@@ -234,8 +323,13 @@ var IORedisCache = class extends BaseCache {
|
|
|
234
323
|
else await this.client.set(key, raw);
|
|
235
324
|
}
|
|
236
325
|
async delete(key) {
|
|
237
|
-
|
|
238
|
-
|
|
326
|
+
if (this.isUNLINKSupported) {
|
|
327
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
328
|
+
await this.client.unlink(key);
|
|
329
|
+
} else {
|
|
330
|
+
this.logger?.debug(this.name, "[delete] Running \"DEL\" command...", "key =", key);
|
|
331
|
+
await this.client.del(key);
|
|
332
|
+
}
|
|
239
333
|
}
|
|
240
334
|
async getMany(keys) {
|
|
241
335
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -256,8 +350,13 @@ var IORedisCache = class extends BaseCache {
|
|
|
256
350
|
await this.client.call("MSETEX", entries.length, ...raw, ...ttl ? ["EX", ttl] : []);
|
|
257
351
|
}
|
|
258
352
|
async deleteMany(keys) {
|
|
259
|
-
|
|
260
|
-
|
|
353
|
+
if (this.isUNLINKSupported) {
|
|
354
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
355
|
+
await this.client.unlink(keys);
|
|
356
|
+
} else {
|
|
357
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"DEL\" command...", "keys =", keys);
|
|
358
|
+
await this.client.del(keys);
|
|
359
|
+
}
|
|
261
360
|
}
|
|
262
361
|
};
|
|
263
362
|
|
|
@@ -269,12 +368,14 @@ var IORedisCache = class extends BaseCache {
|
|
|
269
368
|
var RedisCache = class extends BaseCache {
|
|
270
369
|
client;
|
|
271
370
|
defaultTTL;
|
|
371
|
+
isUNLINKSupported;
|
|
272
372
|
isMSETEXSupported;
|
|
273
373
|
constructor(options) {
|
|
274
374
|
super(options);
|
|
275
375
|
this.client = options.client;
|
|
276
376
|
this.defaultTTL = options.defaultTTL;
|
|
277
|
-
this.
|
|
377
|
+
this.isUNLINKSupported = options.isUNLINKSupported ?? true;
|
|
378
|
+
this.isMSETEXSupported = options.isMSETEXSupported ?? false;
|
|
278
379
|
}
|
|
279
380
|
async get(key) {
|
|
280
381
|
this.logger?.debug(this.name, "[get] Running \"GET\" command...", "key =", key);
|
|
@@ -290,8 +391,13 @@ var RedisCache = class extends BaseCache {
|
|
|
290
391
|
} : void 0 });
|
|
291
392
|
}
|
|
292
393
|
async delete(key) {
|
|
293
|
-
|
|
294
|
-
|
|
394
|
+
if (this.isUNLINKSupported) {
|
|
395
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
396
|
+
await this.client.unlink(key);
|
|
397
|
+
} else {
|
|
398
|
+
this.logger?.debug(this.name, "[delete] Running \"DEL\" command...", "key =", key);
|
|
399
|
+
await this.client.del(key);
|
|
400
|
+
}
|
|
295
401
|
}
|
|
296
402
|
async getMany(keys) {
|
|
297
403
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -315,8 +421,13 @@ var RedisCache = class extends BaseCache {
|
|
|
315
421
|
} : void 0 });
|
|
316
422
|
}
|
|
317
423
|
async deleteMany(keys) {
|
|
318
|
-
|
|
319
|
-
|
|
424
|
+
if (this.isUNLINKSupported) {
|
|
425
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
426
|
+
await this.client.unlink(keys);
|
|
427
|
+
} else {
|
|
428
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"DEL\" command...", "keys =", keys);
|
|
429
|
+
await this.client.del(keys);
|
|
430
|
+
}
|
|
320
431
|
}
|
|
321
432
|
};
|
|
322
433
|
|
|
@@ -347,8 +458,8 @@ var ValkeyGlideCache = class extends BaseCache {
|
|
|
347
458
|
} : void 0 });
|
|
348
459
|
}
|
|
349
460
|
async delete(key) {
|
|
350
|
-
this.logger?.debug(this.name, "[delete] Running \"
|
|
351
|
-
await this.client.
|
|
461
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
462
|
+
await this.client.unlink([key]);
|
|
352
463
|
}
|
|
353
464
|
async getMany(keys) {
|
|
354
465
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -361,8 +472,8 @@ var ValkeyGlideCache = class extends BaseCache {
|
|
|
361
472
|
return data;
|
|
362
473
|
}
|
|
363
474
|
async deleteMany(keys) {
|
|
364
|
-
this.logger?.debug(this.name, "[deleteMany] Running \"
|
|
365
|
-
await this.client.
|
|
475
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
476
|
+
await this.client.unlink(keys);
|
|
366
477
|
}
|
|
367
478
|
};
|
|
368
479
|
|
package/dist/index.d.cts
CHANGED
|
@@ -119,6 +119,56 @@ declare abstract class BaseCache implements ICache {
|
|
|
119
119
|
deleteMany(keys: string[]): Promise<void>;
|
|
120
120
|
}
|
|
121
121
|
//#endregion
|
|
122
|
+
//#region src/base/local.d.ts
|
|
123
|
+
type LocalCacheDisposeListener<T = any> = (key: string, value: T, reason?: string) => void;
|
|
124
|
+
declare abstract class BaseLocalCache extends BaseCache {
|
|
125
|
+
protected disposeListeners: LocalCacheDisposeListener[];
|
|
126
|
+
/**
|
|
127
|
+
* Reads the cached resource from a key (synchronous version)
|
|
128
|
+
* @protected
|
|
129
|
+
*/
|
|
130
|
+
abstract _get<T>(key: string): T | null;
|
|
131
|
+
/**
|
|
132
|
+
* Writes a resource into cache (synchronous version)
|
|
133
|
+
* @protected
|
|
134
|
+
*/
|
|
135
|
+
abstract _set<T>(key: string, value: T, options?: SetCacheOptions): void;
|
|
136
|
+
/**
|
|
137
|
+
* Deletes a cached resource by a key. (synchronous version)
|
|
138
|
+
* @protected
|
|
139
|
+
*/
|
|
140
|
+
abstract _delete(key: string): void;
|
|
141
|
+
/**
|
|
142
|
+
* Reads cached resources by their keys. (synchronous version)
|
|
143
|
+
* @protected
|
|
144
|
+
*/
|
|
145
|
+
_getMany<T>(keys: string[]): Record<string, T | null>;
|
|
146
|
+
/**
|
|
147
|
+
* Writes resources into cache. (synchronous version)
|
|
148
|
+
* @protected
|
|
149
|
+
*/
|
|
150
|
+
_setMany<T>(data: Record<string, T>, options?: SetCacheOptions): void;
|
|
151
|
+
/**
|
|
152
|
+
* Deletes many cached resources by their keys. (synchronous version)
|
|
153
|
+
* @protected
|
|
154
|
+
*/
|
|
155
|
+
_deleteMany(keys: string[]): void;
|
|
156
|
+
/**
|
|
157
|
+
* Adds a listener that will be called when a cached item is disposed.
|
|
158
|
+
*
|
|
159
|
+
* @param listener The listener function to add.
|
|
160
|
+
* @protected
|
|
161
|
+
*/
|
|
162
|
+
_addDisposeListener(listener: LocalCacheDisposeListener): void;
|
|
163
|
+
get<T>(key: string): Promise<T | null>;
|
|
164
|
+
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|
|
165
|
+
delete(key: string): Promise<void>;
|
|
166
|
+
getMany<T>(keys: string[]): Promise<Record<string, T | null>>;
|
|
167
|
+
setMany<T>(data: Record<string, T>, options?: SetCacheOptions): Promise<void>;
|
|
168
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
169
|
+
protected onDispose(key: string, value: any, reason?: string): void;
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
122
172
|
//#region src/local/lru/index.d.ts
|
|
123
173
|
interface ExistingLRUCacheOptions extends BaseCacheOptions {
|
|
124
174
|
/**
|
|
@@ -154,14 +204,11 @@ interface LocalLRUCacheOptions extends BaseCacheOptions {
|
|
|
154
204
|
*
|
|
155
205
|
* Once the limit of items is reached, the least recently used items will be purged.
|
|
156
206
|
*/
|
|
157
|
-
declare class LocalLRUCache extends
|
|
207
|
+
declare class LocalLRUCache extends BaseLocalCache {
|
|
158
208
|
protected readonly cache: LRUCache<string, any, () => Promise<any>>;
|
|
159
209
|
protected shouldUseFetch?: boolean;
|
|
160
210
|
constructor(options?: LocalLRUCacheOptions | ExistingLRUCacheOptions);
|
|
161
|
-
get<T>(key: string): Promise<T | null>;
|
|
162
211
|
getOrLoad<T>(key: string, load: () => Promise<T>, options?: SetCacheOptions): Promise<T>;
|
|
163
|
-
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|
|
164
|
-
delete(key: string): Promise<void>;
|
|
165
212
|
}
|
|
166
213
|
//#endregion
|
|
167
214
|
//#region src/local/ttl/index.d.ts
|
|
@@ -186,12 +233,9 @@ interface LocalTTLCacheOptions extends BaseCacheOptions {
|
|
|
186
233
|
*
|
|
187
234
|
* Once the limit of items is reached, the soonest expiring items will be purged.
|
|
188
235
|
*/
|
|
189
|
-
declare class LocalTTLCache extends
|
|
236
|
+
declare class LocalTTLCache extends BaseLocalCache {
|
|
190
237
|
protected readonly cache: TTLCache<string, any>;
|
|
191
238
|
constructor(options?: LocalTTLCacheOptions | ExistingTTLCacheOptions);
|
|
192
|
-
get<T>(key: string): Promise<T | null>;
|
|
193
|
-
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|
|
194
|
-
delete(key: string): Promise<void>;
|
|
195
239
|
}
|
|
196
240
|
//#endregion
|
|
197
241
|
//#region src/local/map/index.d.ts
|
|
@@ -220,24 +264,23 @@ interface MapLike<K, V> {
|
|
|
220
264
|
*
|
|
221
265
|
* It ignores expiration times, but a limit of cached items can be set.
|
|
222
266
|
*
|
|
267
|
+
* It implements a simple FIFO eviction policy:
|
|
223
268
|
* Once the limit of items is reached, the first inserted keys will be purged.
|
|
224
269
|
*/
|
|
225
|
-
declare class LocalMapCache extends
|
|
270
|
+
declare class LocalMapCache extends BaseLocalCache {
|
|
226
271
|
protected readonly cache: MapLike<string, any>;
|
|
227
272
|
protected max: number;
|
|
228
273
|
constructor(options?: LocalMapCacheOptions);
|
|
229
|
-
get<T>(key: string): Promise<T | null>;
|
|
230
|
-
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|
|
231
|
-
delete(key: string): Promise<void>;
|
|
232
274
|
setMany(data: Record<string, any>, options?: SetCacheOptions): Promise<void>;
|
|
233
275
|
clear(): void;
|
|
276
|
+
protected onDispose(key: string, value: any, reason?: string): void;
|
|
234
277
|
protected evict(length: number): void;
|
|
235
278
|
}
|
|
236
279
|
//#endregion
|
|
237
280
|
//#region src/local/noop/index.d.ts
|
|
238
281
|
/**
|
|
239
282
|
* A cache implementation that does nothing.
|
|
240
|
-
* It's useful for disabling cache.
|
|
283
|
+
* It's useful for disabling cache and unit testing.
|
|
241
284
|
*
|
|
242
285
|
* @example
|
|
243
286
|
* ```ts
|
|
@@ -265,6 +308,17 @@ interface IORedisCacheOptions extends BaseCacheOptions {
|
|
|
265
308
|
* The default Time To Live in seconds
|
|
266
309
|
*/
|
|
267
310
|
defaultTTL?: number;
|
|
311
|
+
/**
|
|
312
|
+
* Indicates whether the Redis server supports the UNLINK command.
|
|
313
|
+
*
|
|
314
|
+
* {@link IORedisCache#delete} and {@link IORedisCache#deleteMany} will use UNLINK instead of DEL if this
|
|
315
|
+
* option is set to `true`. This is recommended to improve the deletion performance.
|
|
316
|
+
*
|
|
317
|
+
* This option should be set to `true` if the server runs Redis OSS 4.0.0 or above.
|
|
318
|
+
*
|
|
319
|
+
* @defaultValue true
|
|
320
|
+
*/
|
|
321
|
+
isUNLINKSupported?: boolean;
|
|
268
322
|
/**
|
|
269
323
|
* Indicates whether the Redis server supports the MSETEX command.
|
|
270
324
|
*
|
|
@@ -272,6 +326,8 @@ interface IORedisCacheOptions extends BaseCacheOptions {
|
|
|
272
326
|
*
|
|
273
327
|
* This option should be set to `true` if the server runs Redis OSS 8.4.0 or above.
|
|
274
328
|
* Valkey does not support this yet. (see https://github.com/valkey-io/valkey/issues/2592)
|
|
329
|
+
*
|
|
330
|
+
* @defaultValue false
|
|
275
331
|
*/
|
|
276
332
|
isMSETEXSupported?: boolean;
|
|
277
333
|
}
|
|
@@ -281,7 +337,8 @@ interface IORedisCacheOptions extends BaseCacheOptions {
|
|
|
281
337
|
declare class IORedisCache extends BaseCache {
|
|
282
338
|
protected readonly client: Redis | Redis$1;
|
|
283
339
|
protected defaultTTL?: number;
|
|
284
|
-
protected
|
|
340
|
+
protected isUNLINKSupported: boolean;
|
|
341
|
+
protected isMSETEXSupported: boolean;
|
|
285
342
|
constructor(options: IORedisCacheOptions);
|
|
286
343
|
get<T>(key: string): Promise<T | null>;
|
|
287
344
|
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|
|
@@ -303,12 +360,26 @@ interface RedisCacheOptions extends BaseCacheOptions {
|
|
|
303
360
|
*/
|
|
304
361
|
defaultTTL?: number;
|
|
305
362
|
/**
|
|
306
|
-
* Indicates whether the Redis server supports
|
|
363
|
+
* Indicates whether the Redis server supports the UNLINK command.
|
|
364
|
+
*
|
|
365
|
+
* {@link RedisCache#delete} and {@link RedisCache#deleteMany} will use UNLINK instead of DEL if this
|
|
366
|
+
* option is set to `true`. This is recommended to improve the deletion performance.
|
|
367
|
+
*
|
|
368
|
+
* This option should be set to `true` if the server runs Redis OSS 4.0.0 or above.
|
|
369
|
+
*
|
|
370
|
+
* @defaultValue true
|
|
371
|
+
*/
|
|
372
|
+
isUNLINKSupported?: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Indicates whether the Redis server supports the MSETEX command.
|
|
307
375
|
*
|
|
308
376
|
* {@link RedisCache#setMany} will use MSETEX if this option is set to `true`.
|
|
377
|
+
* This is recommended to improve the performance of setting multiple items.
|
|
309
378
|
*
|
|
310
379
|
* This option should be set to `true` if the server runs Redis OSS 8.4.0 or above.
|
|
311
380
|
* Valkey does not support this yet. (see https://github.com/valkey-io/valkey/issues/2592)
|
|
381
|
+
*
|
|
382
|
+
* @defaultValue false
|
|
312
383
|
*/
|
|
313
384
|
isMSETEXSupported?: boolean;
|
|
314
385
|
}
|
|
@@ -318,7 +389,8 @@ interface RedisCacheOptions extends BaseCacheOptions {
|
|
|
318
389
|
declare class RedisCache extends BaseCache {
|
|
319
390
|
protected readonly client: Redis$2;
|
|
320
391
|
protected defaultTTL?: number;
|
|
321
|
-
protected
|
|
392
|
+
protected isUNLINKSupported: boolean;
|
|
393
|
+
protected isMSETEXSupported: boolean;
|
|
322
394
|
constructor(options: RedisCacheOptions);
|
|
323
395
|
get<T>(key: string): Promise<T | null>;
|
|
324
396
|
set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
|