cacheable 2.0.3 → 2.1.1
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 +106 -11
- package/dist/index.cjs +142 -26
- package/dist/index.d.cts +81 -3
- package/dist/index.d.ts +81 -3
- package/dist/index.js +141 -26
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/cacheable)
|
|
9
9
|
[](https://github.com/jaredwray/cacheable/blob/main/LICENSE)
|
|
10
10
|
|
|
11
|
-
`cacheable` is a high performance layer 1 / layer 2 caching engine that is focused on distributed caching with enterprise features such as `CacheSync
|
|
11
|
+
`cacheable` is a high performance layer 1 / layer 2 caching engine that is focused on distributed caching with enterprise features such as `CacheSync`. It is built on top of the robust storage engine [Keyv](https://keyv.org) and provides a simple API to cache and retrieve data.
|
|
12
12
|
|
|
13
13
|
* Simple to use with robust API
|
|
14
14
|
* Not bloated with additional modules
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* Hooks and Events to extend functionality
|
|
20
20
|
* Shorthand for ttl in milliseconds `(1m = 60000) (1h = 3600000) (1d = 86400000)`
|
|
21
21
|
* Non-blocking operations for layer 2 caching
|
|
22
|
-
* Distributed Caching Sync via Pub/Sub
|
|
22
|
+
* **Distributed Caching Sync via Pub/Sub with CacheSync**
|
|
23
23
|
* Comprehensive testing and code coverage
|
|
24
24
|
* ESM and CommonJS support with Typescript
|
|
25
25
|
* Maintained and supported regularly
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* [Shorthand for Time to Live (ttl)](#shorthand-for-time-to-live-ttl)
|
|
35
35
|
* [Non-Blocking Operations](#non-blocking-operations)
|
|
36
36
|
* [Non-Blocking with @keyv/redis](#non-blocking-with-keyvredis)
|
|
37
|
-
* [
|
|
37
|
+
* [CacheableSync - Distributed Updates](#cacheablesync---distributed-updates)
|
|
38
38
|
* [Cacheable Options](#cacheable-options)
|
|
39
39
|
* [Cacheable Statistics (Instance Only)](#cacheable-statistics-instance-only)
|
|
40
40
|
* [Cacheable - API](#cacheable---api)
|
|
@@ -359,17 +359,108 @@ const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
|
|
|
359
359
|
const cache = new Cacheable({secondary, nonBlocking: true});
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
-
#
|
|
362
|
+
# CacheableSync - Distributed Updates
|
|
363
363
|
|
|
364
|
-
`cacheable`
|
|
364
|
+
`cacheable` includes `CacheableSync`, a feature that enables distributed cache synchronization across multiple instances using Pub/Sub messaging via [Qified](https://github.com/jaredwray/qified). When a value is set or deleted in one cache instance, all other connected instances automatically receive and apply the update.
|
|
365
365
|
|
|
366
|
-
|
|
367
|
-
* [RabbitMQ](https://www.rabbitmq.com)
|
|
368
|
-
* [Nats](https://nats.io)
|
|
369
|
-
* [Azure Service Bus](https://azure.microsoft.com/en-us/services/service-bus)
|
|
370
|
-
* [Redis Pub/Sub](https://redis.io/topics/pubsub)
|
|
366
|
+
## How It Works
|
|
371
367
|
|
|
372
|
-
|
|
368
|
+
`CacheableSync` uses message providers from Qified to broadcast cache operations (SET and DELETE) to all connected cache instances. Each instance subscribes to these events and automatically updates its `primary` (example: in-memory) storage when receiving updates from other instances.
|
|
369
|
+
|
|
370
|
+
## Supported Message Providers
|
|
371
|
+
|
|
372
|
+
`Qified` supports multiple providers and you can learn more by going to https://qified.org.
|
|
373
|
+
|
|
374
|
+
## Basic Usage
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
import { Cacheable } from 'cacheable';
|
|
378
|
+
import { RedisMessageProvider } from '@qified/redis';
|
|
379
|
+
|
|
380
|
+
// Create a Redis message provider
|
|
381
|
+
const provider = new RedisMessageProvider({
|
|
382
|
+
connection: { host: 'localhost', port: 6379 }
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Create cache instances with sync enabled
|
|
386
|
+
const cache1 = new Cacheable({
|
|
387
|
+
sync: { qified: provider }
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
const cache2 = new Cacheable({
|
|
391
|
+
sync: { qified: provider }
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Set a value in cache1
|
|
395
|
+
await cache1.set('key', 'value');
|
|
396
|
+
|
|
397
|
+
// Note: you might want to sleep for a bit based on the backend.
|
|
398
|
+
|
|
399
|
+
// The value is automatically synced to cache2
|
|
400
|
+
const value = await cache2.get('key'); // Returns 'value'
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Using Multiple Message Providers
|
|
404
|
+
|
|
405
|
+
You can use multiple message providers for redundancy:
|
|
406
|
+
|
|
407
|
+
```javascript
|
|
408
|
+
import { Cacheable } from 'cacheable';
|
|
409
|
+
import { RedisMessageProvider } from '@qified/redis';
|
|
410
|
+
import { NatsMessageProvider } from '@qified/nats';
|
|
411
|
+
|
|
412
|
+
const redisProvider = new RedisMessageProvider({
|
|
413
|
+
connection: { host: 'localhost', port: 6379 }
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
const natsProvider = new NatsMessageProvider({
|
|
417
|
+
servers: ['nats://localhost:4222']
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const cache = new Cacheable({
|
|
421
|
+
sync: { qified: [redisProvider, natsProvider] }
|
|
422
|
+
});
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Using an Existing Qified Instance
|
|
426
|
+
|
|
427
|
+
You can also pass a pre-configured Qified instance:
|
|
428
|
+
|
|
429
|
+
```javascript
|
|
430
|
+
import { Cacheable } from 'cacheable';
|
|
431
|
+
import { Qified } from 'qified';
|
|
432
|
+
import { RedisMessageProvider } from '@qified/redis';
|
|
433
|
+
|
|
434
|
+
const provider = new RedisMessageProvider({
|
|
435
|
+
connection: { host: 'localhost', port: 6379 }
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
const qified = new Qified({ messageProviders: [provider] });
|
|
439
|
+
|
|
440
|
+
const cache = new Cacheable({
|
|
441
|
+
sync: { qified }
|
|
442
|
+
});
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## How Sync Works
|
|
446
|
+
|
|
447
|
+
1. **SET Operations**: When you call `cache.set()` or `cache.setMany()`, the cache:
|
|
448
|
+
- Updates the local primary storage and secondary storage
|
|
449
|
+
- Publishes a `cache:set` event with the key, value, ttl, and cacheId
|
|
450
|
+
- Other cache instances receive the event and update their `primary` storage (excluding the originating instance)
|
|
451
|
+
|
|
452
|
+
2. **DELETE Operations**: When you call `cache.delete()` or `cache.deleteMany()`, the cache:
|
|
453
|
+
- Removes the key from primary and secondary storage
|
|
454
|
+
- Publishes a `cache:delete` event with the key and cacheId
|
|
455
|
+
- Other cache instances receive the event and remove the key from their storage
|
|
456
|
+
|
|
457
|
+
## Important Notes
|
|
458
|
+
|
|
459
|
+
* Cache sync only works with the **primary storage layer**. Secondary storage is usually handled by the instance doing the initial work.
|
|
460
|
+
* Each cache instance should have a unique `cacheId` to properly filter sync events. This is setup by default but you can set it if you want.
|
|
461
|
+
* Sync events are **eventually consistent** - there may be a small delay between when a value is set and when it appears in other instances.
|
|
462
|
+
* The sync feature requires a message provider to be running and accessible by all cache instances.
|
|
463
|
+
* Each cache instance has a unique `cacheId`. Events are only applied if they come from a different instance, preventing infinite loops.
|
|
373
464
|
|
|
374
465
|
# Cacheable Options
|
|
375
466
|
|
|
@@ -381,6 +472,10 @@ The following options are available for you to configure `cacheable`:
|
|
|
381
472
|
* `stats`: To enable statistics for this instance. Default is `false`.
|
|
382
473
|
* `ttl`: The default time to live for the cache in milliseconds. Default is `undefined` which is disabled.
|
|
383
474
|
* `namespace`: The namespace for the cache. Default is `undefined`.
|
|
475
|
+
* `cacheId`: A unique identifier for this cache instance. Used for sync filtering. Default is a random string.
|
|
476
|
+
* `sync`: Enable distributed cache synchronization. Can be:
|
|
477
|
+
- `CacheableSync` instance
|
|
478
|
+
- `CacheableSyncOptions` object with `{ qified: MessageProvider | MessageProvider[] | Qified }`
|
|
384
479
|
|
|
385
480
|
# Cacheable Statistics (Instance Only)
|
|
386
481
|
|
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,8 @@ __export(index_exports, {
|
|
|
25
25
|
CacheableHooks: () => CacheableHooks,
|
|
26
26
|
CacheableMemory: () => import_memory2.CacheableMemory,
|
|
27
27
|
CacheableStats: () => import_utils2.Stats,
|
|
28
|
+
CacheableSync: () => CacheableSync,
|
|
29
|
+
CacheableSyncEvents: () => CacheableSyncEvents,
|
|
28
30
|
HashAlgorithm: () => import_utils2.HashAlgorithm,
|
|
29
31
|
Keyv: () => import_keyv2.Keyv,
|
|
30
32
|
KeyvCacheableMemory: () => import_memory2.KeyvCacheableMemory,
|
|
@@ -43,7 +45,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
43
45
|
var import_memoize = require("@cacheable/memoize");
|
|
44
46
|
var import_memory = require("@cacheable/memory");
|
|
45
47
|
var import_utils = require("@cacheable/utils");
|
|
46
|
-
var
|
|
48
|
+
var import_hookified2 = require("hookified");
|
|
47
49
|
var import_keyv = require("keyv");
|
|
48
50
|
|
|
49
51
|
// src/enums.ts
|
|
@@ -66,12 +68,92 @@ var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
|
|
|
66
68
|
return CacheableEvents2;
|
|
67
69
|
})(CacheableEvents || {});
|
|
68
70
|
|
|
71
|
+
// src/sync.ts
|
|
72
|
+
var import_hookified = require("hookified");
|
|
73
|
+
var import_qified = require("qified");
|
|
74
|
+
var CacheableSyncEvents = /* @__PURE__ */ ((CacheableSyncEvents2) => {
|
|
75
|
+
CacheableSyncEvents2["ERROR"] = "error";
|
|
76
|
+
CacheableSyncEvents2["SET"] = "cache:set";
|
|
77
|
+
CacheableSyncEvents2["DELETE"] = "cache:delete";
|
|
78
|
+
return CacheableSyncEvents2;
|
|
79
|
+
})(CacheableSyncEvents || {});
|
|
80
|
+
var CacheableSync = class extends import_hookified.Hookified {
|
|
81
|
+
_qified = new import_qified.Qified();
|
|
82
|
+
/**
|
|
83
|
+
* Creates an instance of CacheableSync
|
|
84
|
+
* @param options - Configuration options for CacheableSync
|
|
85
|
+
*/
|
|
86
|
+
constructor(options) {
|
|
87
|
+
super(options);
|
|
88
|
+
this._qified = this.createQified(options.qified);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Gets the Qified instance used for synchronization
|
|
92
|
+
* @returns The Qified instance
|
|
93
|
+
*/
|
|
94
|
+
get qified() {
|
|
95
|
+
return this._qified;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Sets the Qified instance used for synchronization
|
|
99
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
100
|
+
*/
|
|
101
|
+
set qified(value) {
|
|
102
|
+
this._qified = this.createQified(value);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Publishes a cache event to all the cache instances
|
|
106
|
+
* @param data - The cache item data containing cacheId, key, value, and optional ttl
|
|
107
|
+
*/
|
|
108
|
+
async publish(event, data) {
|
|
109
|
+
await this._qified.publish(event, {
|
|
110
|
+
id: crypto.randomUUID(),
|
|
111
|
+
data
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Subscribes to sync events and updates the provided storage
|
|
116
|
+
* @param storage - The Keyv storage instance to update
|
|
117
|
+
* @param cacheId - The cache ID to identify this instance
|
|
118
|
+
*/
|
|
119
|
+
subscribe(storage, cacheId) {
|
|
120
|
+
this._qified.subscribe("cache:set" /* SET */, {
|
|
121
|
+
handler: async (message) => {
|
|
122
|
+
const data = message.data;
|
|
123
|
+
if (data.cacheId !== cacheId) {
|
|
124
|
+
await storage.set(data.key, data.value, data.ttl);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
this._qified.subscribe("cache:delete" /* DELETE */, {
|
|
129
|
+
handler: async (message) => {
|
|
130
|
+
const data = message.data;
|
|
131
|
+
if (data.cacheId !== cacheId) {
|
|
132
|
+
await storage.delete(data.key);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Creates or returns a Qified instance from the provided value
|
|
139
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
140
|
+
* @returns A Qified instance configured with the provided message provider(s)
|
|
141
|
+
*/
|
|
142
|
+
createQified(value) {
|
|
143
|
+
if (value instanceof import_qified.Qified) {
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
const providers = Array.isArray(value) ? value : [value];
|
|
147
|
+
return new import_qified.Qified({ messageProviders: providers });
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
69
151
|
// src/index.ts
|
|
70
152
|
var import_memoize2 = require("@cacheable/memoize");
|
|
71
153
|
var import_memory2 = require("@cacheable/memory");
|
|
72
154
|
var import_utils2 = require("@cacheable/utils");
|
|
73
155
|
var import_keyv2 = require("keyv");
|
|
74
|
-
var Cacheable = class extends
|
|
156
|
+
var Cacheable = class extends import_hookified2.Hookified {
|
|
75
157
|
_primary = (0, import_memory.createKeyv)();
|
|
76
158
|
_secondary;
|
|
77
159
|
_nonBlocking = false;
|
|
@@ -79,6 +161,7 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
79
161
|
_stats = new import_utils.Stats({ enabled: false });
|
|
80
162
|
_namespace;
|
|
81
163
|
_cacheId = Math.random().toString(36).slice(2);
|
|
164
|
+
_sync;
|
|
82
165
|
/**
|
|
83
166
|
* Creates a new cacheable instance
|
|
84
167
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -110,6 +193,10 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
110
193
|
this._secondary.namespace = this.getNameSpace();
|
|
111
194
|
}
|
|
112
195
|
}
|
|
196
|
+
if (options?.sync) {
|
|
197
|
+
this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync(options.sync);
|
|
198
|
+
this._sync.subscribe(this._primary, this._cacheId);
|
|
199
|
+
}
|
|
113
200
|
}
|
|
114
201
|
/**
|
|
115
202
|
* The namespace for the cacheable instance
|
|
@@ -245,13 +332,30 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
245
332
|
set cacheId(cacheId) {
|
|
246
333
|
this._cacheId = cacheId;
|
|
247
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* Gets the sync instance for the cacheable instance
|
|
337
|
+
* @returns {CacheableSync | undefined} The sync instance for the cacheable instance
|
|
338
|
+
*/
|
|
339
|
+
get sync() {
|
|
340
|
+
return this._sync;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Sets the sync instance for the cacheable instance
|
|
344
|
+
* @param {CacheableSync | undefined} sync The sync instance for the cacheable instance
|
|
345
|
+
*/
|
|
346
|
+
set sync(sync) {
|
|
347
|
+
this._sync = sync;
|
|
348
|
+
if (this._sync) {
|
|
349
|
+
this._sync.subscribe(this._primary, this._cacheId);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
248
352
|
/**
|
|
249
353
|
* Sets the primary store for the cacheable instance
|
|
250
354
|
* @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
|
|
251
355
|
* @returns {void}
|
|
252
356
|
*/
|
|
253
357
|
setPrimary(primary) {
|
|
254
|
-
if (
|
|
358
|
+
if ((0, import_utils.isKeyvInstance)(primary)) {
|
|
255
359
|
this._primary = primary;
|
|
256
360
|
} else {
|
|
257
361
|
this._primary = new import_keyv.Keyv(primary);
|
|
@@ -266,7 +370,7 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
266
370
|
* @returns {void}
|
|
267
371
|
*/
|
|
268
372
|
setSecondary(secondary) {
|
|
269
|
-
if (
|
|
373
|
+
if ((0, import_utils.isKeyvInstance)(secondary)) {
|
|
270
374
|
this._secondary = secondary;
|
|
271
375
|
} else {
|
|
272
376
|
this._secondary = new import_keyv.Keyv(secondary);
|
|
@@ -275,28 +379,6 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
275
379
|
this.emit("error" /* ERROR */, error);
|
|
276
380
|
});
|
|
277
381
|
}
|
|
278
|
-
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
279
|
-
isKeyvInstance(keyv) {
|
|
280
|
-
if (keyv instanceof import_keyv.Keyv) {
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
const keyvMethods = [
|
|
284
|
-
"generateIterator",
|
|
285
|
-
"get",
|
|
286
|
-
"getMany",
|
|
287
|
-
"set",
|
|
288
|
-
"setMany",
|
|
289
|
-
"delete",
|
|
290
|
-
"deleteMany",
|
|
291
|
-
"has",
|
|
292
|
-
"hasMany",
|
|
293
|
-
"clear",
|
|
294
|
-
"disconnect",
|
|
295
|
-
"serialize",
|
|
296
|
-
"deserialize"
|
|
297
|
-
];
|
|
298
|
-
return keyvMethods.every((method) => typeof keyv[method] === "function");
|
|
299
|
-
}
|
|
300
382
|
getNameSpace() {
|
|
301
383
|
if (typeof this._namespace === "function") {
|
|
302
384
|
return this._namespace();
|
|
@@ -489,6 +571,14 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
489
571
|
result = results[0];
|
|
490
572
|
}
|
|
491
573
|
await this.hook("AFTER_SET" /* AFTER_SET */, item);
|
|
574
|
+
if (this._sync && result) {
|
|
575
|
+
await this._sync.publish("cache:set" /* SET */, {
|
|
576
|
+
cacheId: this._cacheId,
|
|
577
|
+
key: item.key,
|
|
578
|
+
value: item.value,
|
|
579
|
+
ttl: item.ttl
|
|
580
|
+
});
|
|
581
|
+
}
|
|
492
582
|
} catch (error) {
|
|
493
583
|
this.emit("error" /* ERROR */, error);
|
|
494
584
|
}
|
|
@@ -520,6 +610,16 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
520
610
|
}
|
|
521
611
|
}
|
|
522
612
|
await this.hook("AFTER_SET_MANY" /* AFTER_SET_MANY */, items);
|
|
613
|
+
if (this._sync && result) {
|
|
614
|
+
for (const item of items) {
|
|
615
|
+
await this._sync.publish("cache:set" /* SET */, {
|
|
616
|
+
cacheId: this._cacheId,
|
|
617
|
+
key: item.key,
|
|
618
|
+
value: item.value,
|
|
619
|
+
ttl: (0, import_utils.shorthandToMilliseconds)(item.ttl)
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
523
623
|
} catch (error) {
|
|
524
624
|
this.emit("error" /* ERROR */, error);
|
|
525
625
|
}
|
|
@@ -626,6 +726,12 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
626
726
|
const resultAll = await Promise.all(promises);
|
|
627
727
|
result = resultAll[0];
|
|
628
728
|
}
|
|
729
|
+
if (this._sync && result) {
|
|
730
|
+
await this._sync.publish("cache:delete" /* DELETE */, {
|
|
731
|
+
cacheId: this._cacheId,
|
|
732
|
+
key
|
|
733
|
+
});
|
|
734
|
+
}
|
|
629
735
|
return result;
|
|
630
736
|
}
|
|
631
737
|
/**
|
|
@@ -653,6 +759,14 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
653
759
|
await this._secondary.deleteMany(keys);
|
|
654
760
|
}
|
|
655
761
|
}
|
|
762
|
+
if (this._sync && result) {
|
|
763
|
+
for (const key of keys) {
|
|
764
|
+
await this._sync.publish("cache:delete" /* DELETE */, {
|
|
765
|
+
cacheId: this._cacheId,
|
|
766
|
+
key
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
}
|
|
656
770
|
return result;
|
|
657
771
|
}
|
|
658
772
|
/**
|
|
@@ -955,6 +1069,8 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
955
1069
|
CacheableHooks,
|
|
956
1070
|
CacheableMemory,
|
|
957
1071
|
CacheableStats,
|
|
1072
|
+
CacheableSync,
|
|
1073
|
+
CacheableSyncEvents,
|
|
958
1074
|
HashAlgorithm,
|
|
959
1075
|
Keyv,
|
|
960
1076
|
KeyvCacheableMemory,
|
package/dist/index.d.cts
CHANGED
|
@@ -2,11 +2,75 @@ import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cach
|
|
|
2
2
|
export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/memoize';
|
|
3
3
|
import { Stats, CacheableItem, HashAlgorithm } from '@cacheable/utils';
|
|
4
4
|
export { CacheableItem, Stats as CacheableStats, HashAlgorithm, calculateTtlFromExpiration, getCascadingTtl, hash, shorthandToMilliseconds, shorthandToTime } from '@cacheable/utils';
|
|
5
|
-
import { Hookified } from 'hookified';
|
|
5
|
+
import { Hookified, HookifiedOptions } from 'hookified';
|
|
6
6
|
import { Keyv, KeyvStoreAdapter, StoredDataRaw } from 'keyv';
|
|
7
7
|
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
8
|
+
import { Qified, MessageProvider } from 'qified';
|
|
8
9
|
export { CacheableMemory, CacheableMemoryOptions, KeyvCacheableMemory, KeyvCacheableMemoryOptions, createKeyv } from '@cacheable/memory';
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Events emitted by CacheableSync
|
|
13
|
+
*/
|
|
14
|
+
declare enum CacheableSyncEvents {
|
|
15
|
+
ERROR = "error",
|
|
16
|
+
SET = "cache:set",
|
|
17
|
+
DELETE = "cache:delete"
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Configuration options for CacheableSync
|
|
21
|
+
*/
|
|
22
|
+
type CacheableSyncOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* Qified instance or message provider(s) for synchronization
|
|
25
|
+
*/
|
|
26
|
+
qified: Qified | MessageProvider | MessageProvider[];
|
|
27
|
+
} & HookifiedOptions;
|
|
28
|
+
type CacheableSyncItem = {
|
|
29
|
+
cacheId: string;
|
|
30
|
+
key: string;
|
|
31
|
+
value?: unknown;
|
|
32
|
+
ttl?: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* CacheableSync provides synchronization capabilities for cacheable items
|
|
36
|
+
* using message providers from Qified
|
|
37
|
+
*/
|
|
38
|
+
declare class CacheableSync extends Hookified {
|
|
39
|
+
private _qified;
|
|
40
|
+
/**
|
|
41
|
+
* Creates an instance of CacheableSync
|
|
42
|
+
* @param options - Configuration options for CacheableSync
|
|
43
|
+
*/
|
|
44
|
+
constructor(options: CacheableSyncOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Gets the Qified instance used for synchronization
|
|
47
|
+
* @returns The Qified instance
|
|
48
|
+
*/
|
|
49
|
+
get qified(): Qified;
|
|
50
|
+
/**
|
|
51
|
+
* Sets the Qified instance used for synchronization
|
|
52
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
53
|
+
*/
|
|
54
|
+
set qified(value: Qified | MessageProvider | MessageProvider[]);
|
|
55
|
+
/**
|
|
56
|
+
* Publishes a cache event to all the cache instances
|
|
57
|
+
* @param data - The cache item data containing cacheId, key, value, and optional ttl
|
|
58
|
+
*/
|
|
59
|
+
publish(event: CacheableSyncEvents, data: CacheableSyncItem): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Subscribes to sync events and updates the provided storage
|
|
62
|
+
* @param storage - The Keyv storage instance to update
|
|
63
|
+
* @param cacheId - The cache ID to identify this instance
|
|
64
|
+
*/
|
|
65
|
+
subscribe(storage: Keyv, cacheId: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Creates or returns a Qified instance from the provided value
|
|
68
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
69
|
+
* @returns A Qified instance configured with the provided message provider(s)
|
|
70
|
+
*/
|
|
71
|
+
createQified(value: Qified | MessageProvider | MessageProvider[]): Qified;
|
|
72
|
+
}
|
|
73
|
+
|
|
10
74
|
type CacheableOptions = {
|
|
11
75
|
/**
|
|
12
76
|
* The primary store for the cacheable instance
|
|
@@ -40,6 +104,10 @@ type CacheableOptions = {
|
|
|
40
104
|
* If it is not set then it will be a random string that is generated
|
|
41
105
|
*/
|
|
42
106
|
cacheId?: string;
|
|
107
|
+
/**
|
|
108
|
+
* The sync instance for the cacheable instance to enable synchronization across cache instances
|
|
109
|
+
*/
|
|
110
|
+
sync?: CacheableSync | CacheableSyncOptions;
|
|
43
111
|
};
|
|
44
112
|
type GetOptions = {
|
|
45
113
|
/**
|
|
@@ -74,6 +142,7 @@ declare class Cacheable extends Hookified {
|
|
|
74
142
|
private readonly _stats;
|
|
75
143
|
private _namespace?;
|
|
76
144
|
private _cacheId;
|
|
145
|
+
private _sync?;
|
|
77
146
|
/**
|
|
78
147
|
* Creates a new cacheable instance
|
|
79
148
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -183,6 +252,16 @@ declare class Cacheable extends Hookified {
|
|
|
183
252
|
* @param {string} cacheId The cacheId for the cacheable instance
|
|
184
253
|
*/
|
|
185
254
|
set cacheId(cacheId: string);
|
|
255
|
+
/**
|
|
256
|
+
* Gets the sync instance for the cacheable instance
|
|
257
|
+
* @returns {CacheableSync | undefined} The sync instance for the cacheable instance
|
|
258
|
+
*/
|
|
259
|
+
get sync(): CacheableSync | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Sets the sync instance for the cacheable instance
|
|
262
|
+
* @param {CacheableSync | undefined} sync The sync instance for the cacheable instance
|
|
263
|
+
*/
|
|
264
|
+
set sync(sync: CacheableSync | undefined);
|
|
186
265
|
/**
|
|
187
266
|
* Sets the primary store for the cacheable instance
|
|
188
267
|
* @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
|
|
@@ -195,7 +274,6 @@ declare class Cacheable extends Hookified {
|
|
|
195
274
|
* @returns {void}
|
|
196
275
|
*/
|
|
197
276
|
setSecondary(secondary: Keyv | KeyvStoreAdapter): void;
|
|
198
|
-
isKeyvInstance(keyv: any): boolean;
|
|
199
277
|
getNameSpace(): string | undefined;
|
|
200
278
|
/**
|
|
201
279
|
* Retrieves an entry from the cache.
|
|
@@ -376,4 +454,4 @@ declare class Cacheable extends Hookified {
|
|
|
376
454
|
private setTtl;
|
|
377
455
|
}
|
|
378
456
|
|
|
379
|
-
export { Cacheable, CacheableEvents, CacheableHooks, type CacheableOptions };
|
|
457
|
+
export { Cacheable, CacheableEvents, CacheableHooks, type CacheableOptions, CacheableSync, CacheableSyncEvents, type CacheableSyncItem, type CacheableSyncOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,75 @@ import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cach
|
|
|
2
2
|
export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/memoize';
|
|
3
3
|
import { Stats, CacheableItem, HashAlgorithm } from '@cacheable/utils';
|
|
4
4
|
export { CacheableItem, Stats as CacheableStats, HashAlgorithm, calculateTtlFromExpiration, getCascadingTtl, hash, shorthandToMilliseconds, shorthandToTime } from '@cacheable/utils';
|
|
5
|
-
import { Hookified } from 'hookified';
|
|
5
|
+
import { Hookified, HookifiedOptions } from 'hookified';
|
|
6
6
|
import { Keyv, KeyvStoreAdapter, StoredDataRaw } from 'keyv';
|
|
7
7
|
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
8
|
+
import { Qified, MessageProvider } from 'qified';
|
|
8
9
|
export { CacheableMemory, CacheableMemoryOptions, KeyvCacheableMemory, KeyvCacheableMemoryOptions, createKeyv } from '@cacheable/memory';
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Events emitted by CacheableSync
|
|
13
|
+
*/
|
|
14
|
+
declare enum CacheableSyncEvents {
|
|
15
|
+
ERROR = "error",
|
|
16
|
+
SET = "cache:set",
|
|
17
|
+
DELETE = "cache:delete"
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Configuration options for CacheableSync
|
|
21
|
+
*/
|
|
22
|
+
type CacheableSyncOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* Qified instance or message provider(s) for synchronization
|
|
25
|
+
*/
|
|
26
|
+
qified: Qified | MessageProvider | MessageProvider[];
|
|
27
|
+
} & HookifiedOptions;
|
|
28
|
+
type CacheableSyncItem = {
|
|
29
|
+
cacheId: string;
|
|
30
|
+
key: string;
|
|
31
|
+
value?: unknown;
|
|
32
|
+
ttl?: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* CacheableSync provides synchronization capabilities for cacheable items
|
|
36
|
+
* using message providers from Qified
|
|
37
|
+
*/
|
|
38
|
+
declare class CacheableSync extends Hookified {
|
|
39
|
+
private _qified;
|
|
40
|
+
/**
|
|
41
|
+
* Creates an instance of CacheableSync
|
|
42
|
+
* @param options - Configuration options for CacheableSync
|
|
43
|
+
*/
|
|
44
|
+
constructor(options: CacheableSyncOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Gets the Qified instance used for synchronization
|
|
47
|
+
* @returns The Qified instance
|
|
48
|
+
*/
|
|
49
|
+
get qified(): Qified;
|
|
50
|
+
/**
|
|
51
|
+
* Sets the Qified instance used for synchronization
|
|
52
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
53
|
+
*/
|
|
54
|
+
set qified(value: Qified | MessageProvider | MessageProvider[]);
|
|
55
|
+
/**
|
|
56
|
+
* Publishes a cache event to all the cache instances
|
|
57
|
+
* @param data - The cache item data containing cacheId, key, value, and optional ttl
|
|
58
|
+
*/
|
|
59
|
+
publish(event: CacheableSyncEvents, data: CacheableSyncItem): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Subscribes to sync events and updates the provided storage
|
|
62
|
+
* @param storage - The Keyv storage instance to update
|
|
63
|
+
* @param cacheId - The cache ID to identify this instance
|
|
64
|
+
*/
|
|
65
|
+
subscribe(storage: Keyv, cacheId: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Creates or returns a Qified instance from the provided value
|
|
68
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
69
|
+
* @returns A Qified instance configured with the provided message provider(s)
|
|
70
|
+
*/
|
|
71
|
+
createQified(value: Qified | MessageProvider | MessageProvider[]): Qified;
|
|
72
|
+
}
|
|
73
|
+
|
|
10
74
|
type CacheableOptions = {
|
|
11
75
|
/**
|
|
12
76
|
* The primary store for the cacheable instance
|
|
@@ -40,6 +104,10 @@ type CacheableOptions = {
|
|
|
40
104
|
* If it is not set then it will be a random string that is generated
|
|
41
105
|
*/
|
|
42
106
|
cacheId?: string;
|
|
107
|
+
/**
|
|
108
|
+
* The sync instance for the cacheable instance to enable synchronization across cache instances
|
|
109
|
+
*/
|
|
110
|
+
sync?: CacheableSync | CacheableSyncOptions;
|
|
43
111
|
};
|
|
44
112
|
type GetOptions = {
|
|
45
113
|
/**
|
|
@@ -74,6 +142,7 @@ declare class Cacheable extends Hookified {
|
|
|
74
142
|
private readonly _stats;
|
|
75
143
|
private _namespace?;
|
|
76
144
|
private _cacheId;
|
|
145
|
+
private _sync?;
|
|
77
146
|
/**
|
|
78
147
|
* Creates a new cacheable instance
|
|
79
148
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -183,6 +252,16 @@ declare class Cacheable extends Hookified {
|
|
|
183
252
|
* @param {string} cacheId The cacheId for the cacheable instance
|
|
184
253
|
*/
|
|
185
254
|
set cacheId(cacheId: string);
|
|
255
|
+
/**
|
|
256
|
+
* Gets the sync instance for the cacheable instance
|
|
257
|
+
* @returns {CacheableSync | undefined} The sync instance for the cacheable instance
|
|
258
|
+
*/
|
|
259
|
+
get sync(): CacheableSync | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Sets the sync instance for the cacheable instance
|
|
262
|
+
* @param {CacheableSync | undefined} sync The sync instance for the cacheable instance
|
|
263
|
+
*/
|
|
264
|
+
set sync(sync: CacheableSync | undefined);
|
|
186
265
|
/**
|
|
187
266
|
* Sets the primary store for the cacheable instance
|
|
188
267
|
* @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
|
|
@@ -195,7 +274,6 @@ declare class Cacheable extends Hookified {
|
|
|
195
274
|
* @returns {void}
|
|
196
275
|
*/
|
|
197
276
|
setSecondary(secondary: Keyv | KeyvStoreAdapter): void;
|
|
198
|
-
isKeyvInstance(keyv: any): boolean;
|
|
199
277
|
getNameSpace(): string | undefined;
|
|
200
278
|
/**
|
|
201
279
|
* Retrieves an entry from the cache.
|
|
@@ -376,4 +454,4 @@ declare class Cacheable extends Hookified {
|
|
|
376
454
|
private setTtl;
|
|
377
455
|
}
|
|
378
456
|
|
|
379
|
-
export { Cacheable, CacheableEvents, CacheableHooks, type CacheableOptions };
|
|
457
|
+
export { Cacheable, CacheableEvents, CacheableHooks, type CacheableOptions, CacheableSync, CacheableSyncEvents, type CacheableSyncItem, type CacheableSyncOptions };
|
package/dist/index.js
CHANGED
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
getCascadingTtl,
|
|
11
11
|
HashAlgorithm,
|
|
12
12
|
hash,
|
|
13
|
+
isKeyvInstance,
|
|
13
14
|
shorthandToMilliseconds
|
|
14
15
|
} from "@cacheable/utils";
|
|
15
|
-
import { Hookified } from "hookified";
|
|
16
|
+
import { Hookified as Hookified2 } from "hookified";
|
|
16
17
|
import {
|
|
17
18
|
Keyv
|
|
18
19
|
} from "keyv";
|
|
@@ -37,6 +38,86 @@ var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
|
|
|
37
38
|
return CacheableEvents2;
|
|
38
39
|
})(CacheableEvents || {});
|
|
39
40
|
|
|
41
|
+
// src/sync.ts
|
|
42
|
+
import { Hookified } from "hookified";
|
|
43
|
+
import { Qified } from "qified";
|
|
44
|
+
var CacheableSyncEvents = /* @__PURE__ */ ((CacheableSyncEvents2) => {
|
|
45
|
+
CacheableSyncEvents2["ERROR"] = "error";
|
|
46
|
+
CacheableSyncEvents2["SET"] = "cache:set";
|
|
47
|
+
CacheableSyncEvents2["DELETE"] = "cache:delete";
|
|
48
|
+
return CacheableSyncEvents2;
|
|
49
|
+
})(CacheableSyncEvents || {});
|
|
50
|
+
var CacheableSync = class extends Hookified {
|
|
51
|
+
_qified = new Qified();
|
|
52
|
+
/**
|
|
53
|
+
* Creates an instance of CacheableSync
|
|
54
|
+
* @param options - Configuration options for CacheableSync
|
|
55
|
+
*/
|
|
56
|
+
constructor(options) {
|
|
57
|
+
super(options);
|
|
58
|
+
this._qified = this.createQified(options.qified);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Gets the Qified instance used for synchronization
|
|
62
|
+
* @returns The Qified instance
|
|
63
|
+
*/
|
|
64
|
+
get qified() {
|
|
65
|
+
return this._qified;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sets the Qified instance used for synchronization
|
|
69
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
70
|
+
*/
|
|
71
|
+
set qified(value) {
|
|
72
|
+
this._qified = this.createQified(value);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Publishes a cache event to all the cache instances
|
|
76
|
+
* @param data - The cache item data containing cacheId, key, value, and optional ttl
|
|
77
|
+
*/
|
|
78
|
+
async publish(event, data) {
|
|
79
|
+
await this._qified.publish(event, {
|
|
80
|
+
id: crypto.randomUUID(),
|
|
81
|
+
data
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Subscribes to sync events and updates the provided storage
|
|
86
|
+
* @param storage - The Keyv storage instance to update
|
|
87
|
+
* @param cacheId - The cache ID to identify this instance
|
|
88
|
+
*/
|
|
89
|
+
subscribe(storage, cacheId) {
|
|
90
|
+
this._qified.subscribe("cache:set" /* SET */, {
|
|
91
|
+
handler: async (message) => {
|
|
92
|
+
const data = message.data;
|
|
93
|
+
if (data.cacheId !== cacheId) {
|
|
94
|
+
await storage.set(data.key, data.value, data.ttl);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this._qified.subscribe("cache:delete" /* DELETE */, {
|
|
99
|
+
handler: async (message) => {
|
|
100
|
+
const data = message.data;
|
|
101
|
+
if (data.cacheId !== cacheId) {
|
|
102
|
+
await storage.delete(data.key);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Creates or returns a Qified instance from the provided value
|
|
109
|
+
* @param value - Either an existing Qified instance or MessageProvider(s)
|
|
110
|
+
* @returns A Qified instance configured with the provided message provider(s)
|
|
111
|
+
*/
|
|
112
|
+
createQified(value) {
|
|
113
|
+
if (value instanceof Qified) {
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
const providers = Array.isArray(value) ? value : [value];
|
|
117
|
+
return new Qified({ messageProviders: providers });
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
40
121
|
// src/index.ts
|
|
41
122
|
import {
|
|
42
123
|
getOrSet as getOrSet2,
|
|
@@ -58,7 +139,7 @@ import {
|
|
|
58
139
|
shorthandToTime
|
|
59
140
|
} from "@cacheable/utils";
|
|
60
141
|
import { Keyv as Keyv2, KeyvHooks } from "keyv";
|
|
61
|
-
var Cacheable = class extends
|
|
142
|
+
var Cacheable = class extends Hookified2 {
|
|
62
143
|
_primary = createKeyv();
|
|
63
144
|
_secondary;
|
|
64
145
|
_nonBlocking = false;
|
|
@@ -66,6 +147,7 @@ var Cacheable = class extends Hookified {
|
|
|
66
147
|
_stats = new CacheableStats({ enabled: false });
|
|
67
148
|
_namespace;
|
|
68
149
|
_cacheId = Math.random().toString(36).slice(2);
|
|
150
|
+
_sync;
|
|
69
151
|
/**
|
|
70
152
|
* Creates a new cacheable instance
|
|
71
153
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -97,6 +179,10 @@ var Cacheable = class extends Hookified {
|
|
|
97
179
|
this._secondary.namespace = this.getNameSpace();
|
|
98
180
|
}
|
|
99
181
|
}
|
|
182
|
+
if (options?.sync) {
|
|
183
|
+
this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync(options.sync);
|
|
184
|
+
this._sync.subscribe(this._primary, this._cacheId);
|
|
185
|
+
}
|
|
100
186
|
}
|
|
101
187
|
/**
|
|
102
188
|
* The namespace for the cacheable instance
|
|
@@ -232,13 +318,30 @@ var Cacheable = class extends Hookified {
|
|
|
232
318
|
set cacheId(cacheId) {
|
|
233
319
|
this._cacheId = cacheId;
|
|
234
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Gets the sync instance for the cacheable instance
|
|
323
|
+
* @returns {CacheableSync | undefined} The sync instance for the cacheable instance
|
|
324
|
+
*/
|
|
325
|
+
get sync() {
|
|
326
|
+
return this._sync;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Sets the sync instance for the cacheable instance
|
|
330
|
+
* @param {CacheableSync | undefined} sync The sync instance for the cacheable instance
|
|
331
|
+
*/
|
|
332
|
+
set sync(sync) {
|
|
333
|
+
this._sync = sync;
|
|
334
|
+
if (this._sync) {
|
|
335
|
+
this._sync.subscribe(this._primary, this._cacheId);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
235
338
|
/**
|
|
236
339
|
* Sets the primary store for the cacheable instance
|
|
237
340
|
* @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
|
|
238
341
|
* @returns {void}
|
|
239
342
|
*/
|
|
240
343
|
setPrimary(primary) {
|
|
241
|
-
if (
|
|
344
|
+
if (isKeyvInstance(primary)) {
|
|
242
345
|
this._primary = primary;
|
|
243
346
|
} else {
|
|
244
347
|
this._primary = new Keyv(primary);
|
|
@@ -253,7 +356,7 @@ var Cacheable = class extends Hookified {
|
|
|
253
356
|
* @returns {void}
|
|
254
357
|
*/
|
|
255
358
|
setSecondary(secondary) {
|
|
256
|
-
if (
|
|
359
|
+
if (isKeyvInstance(secondary)) {
|
|
257
360
|
this._secondary = secondary;
|
|
258
361
|
} else {
|
|
259
362
|
this._secondary = new Keyv(secondary);
|
|
@@ -262,28 +365,6 @@ var Cacheable = class extends Hookified {
|
|
|
262
365
|
this.emit("error" /* ERROR */, error);
|
|
263
366
|
});
|
|
264
367
|
}
|
|
265
|
-
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
266
|
-
isKeyvInstance(keyv) {
|
|
267
|
-
if (keyv instanceof Keyv) {
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
270
|
-
const keyvMethods = [
|
|
271
|
-
"generateIterator",
|
|
272
|
-
"get",
|
|
273
|
-
"getMany",
|
|
274
|
-
"set",
|
|
275
|
-
"setMany",
|
|
276
|
-
"delete",
|
|
277
|
-
"deleteMany",
|
|
278
|
-
"has",
|
|
279
|
-
"hasMany",
|
|
280
|
-
"clear",
|
|
281
|
-
"disconnect",
|
|
282
|
-
"serialize",
|
|
283
|
-
"deserialize"
|
|
284
|
-
];
|
|
285
|
-
return keyvMethods.every((method) => typeof keyv[method] === "function");
|
|
286
|
-
}
|
|
287
368
|
getNameSpace() {
|
|
288
369
|
if (typeof this._namespace === "function") {
|
|
289
370
|
return this._namespace();
|
|
@@ -476,6 +557,14 @@ var Cacheable = class extends Hookified {
|
|
|
476
557
|
result = results[0];
|
|
477
558
|
}
|
|
478
559
|
await this.hook("AFTER_SET" /* AFTER_SET */, item);
|
|
560
|
+
if (this._sync && result) {
|
|
561
|
+
await this._sync.publish("cache:set" /* SET */, {
|
|
562
|
+
cacheId: this._cacheId,
|
|
563
|
+
key: item.key,
|
|
564
|
+
value: item.value,
|
|
565
|
+
ttl: item.ttl
|
|
566
|
+
});
|
|
567
|
+
}
|
|
479
568
|
} catch (error) {
|
|
480
569
|
this.emit("error" /* ERROR */, error);
|
|
481
570
|
}
|
|
@@ -507,6 +596,16 @@ var Cacheable = class extends Hookified {
|
|
|
507
596
|
}
|
|
508
597
|
}
|
|
509
598
|
await this.hook("AFTER_SET_MANY" /* AFTER_SET_MANY */, items);
|
|
599
|
+
if (this._sync && result) {
|
|
600
|
+
for (const item of items) {
|
|
601
|
+
await this._sync.publish("cache:set" /* SET */, {
|
|
602
|
+
cacheId: this._cacheId,
|
|
603
|
+
key: item.key,
|
|
604
|
+
value: item.value,
|
|
605
|
+
ttl: shorthandToMilliseconds(item.ttl)
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
510
609
|
} catch (error) {
|
|
511
610
|
this.emit("error" /* ERROR */, error);
|
|
512
611
|
}
|
|
@@ -613,6 +712,12 @@ var Cacheable = class extends Hookified {
|
|
|
613
712
|
const resultAll = await Promise.all(promises);
|
|
614
713
|
result = resultAll[0];
|
|
615
714
|
}
|
|
715
|
+
if (this._sync && result) {
|
|
716
|
+
await this._sync.publish("cache:delete" /* DELETE */, {
|
|
717
|
+
cacheId: this._cacheId,
|
|
718
|
+
key
|
|
719
|
+
});
|
|
720
|
+
}
|
|
616
721
|
return result;
|
|
617
722
|
}
|
|
618
723
|
/**
|
|
@@ -640,6 +745,14 @@ var Cacheable = class extends Hookified {
|
|
|
640
745
|
await this._secondary.deleteMany(keys);
|
|
641
746
|
}
|
|
642
747
|
}
|
|
748
|
+
if (this._sync && result) {
|
|
749
|
+
for (const key of keys) {
|
|
750
|
+
await this._sync.publish("cache:delete" /* DELETE */, {
|
|
751
|
+
cacheId: this._cacheId,
|
|
752
|
+
key
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
643
756
|
return result;
|
|
644
757
|
}
|
|
645
758
|
/**
|
|
@@ -941,6 +1054,8 @@ export {
|
|
|
941
1054
|
CacheableHooks,
|
|
942
1055
|
CacheableMemory,
|
|
943
1056
|
Stats as CacheableStats,
|
|
1057
|
+
CacheableSync,
|
|
1058
|
+
CacheableSyncEvents,
|
|
944
1059
|
HashAlgorithm2 as HashAlgorithm,
|
|
945
1060
|
Keyv2 as Keyv,
|
|
946
1061
|
KeyvCacheableMemory,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacheable",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "High Performance Layer 1 / Layer 2 Caching with Keyv Storage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,24 +21,26 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"private": false,
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@biomejs/biome": "^2.2.
|
|
25
|
-
"@faker-js/faker": "^10.
|
|
26
|
-
"@keyv/redis": "^5.1.
|
|
27
|
-
"@keyv/valkey": "^1.0.
|
|
28
|
-
"@
|
|
24
|
+
"@biomejs/biome": "^2.2.6",
|
|
25
|
+
"@faker-js/faker": "^10.1.0",
|
|
26
|
+
"@keyv/redis": "^5.1.3",
|
|
27
|
+
"@keyv/valkey": "^1.0.10",
|
|
28
|
+
"@qified/redis": "^0.5.0",
|
|
29
|
+
"@types/node": "^24.8.1",
|
|
29
30
|
"@vitest/coverage-v8": "^3.2.4",
|
|
30
|
-
"lru-cache": "^11.2.
|
|
31
|
+
"lru-cache": "^11.2.2",
|
|
31
32
|
"rimraf": "^6.0.1",
|
|
32
33
|
"tsup": "^8.5.0",
|
|
33
|
-
"typescript": "^5.9.
|
|
34
|
+
"typescript": "^5.9.3",
|
|
34
35
|
"vitest": "^3.2.4"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"hookified": "^1.12.
|
|
38
|
+
"hookified": "^1.12.2",
|
|
38
39
|
"keyv": "^5.5.3",
|
|
40
|
+
"qified": "^0.5.0",
|
|
39
41
|
"@cacheable/memoize": "^2.0.3",
|
|
40
42
|
"@cacheable/memory": "^2.0.3",
|
|
41
|
-
"@cacheable/utils": "^2.0
|
|
43
|
+
"@cacheable/utils": "^2.1.0"
|
|
42
44
|
},
|
|
43
45
|
"keywords": [
|
|
44
46
|
"cacheable",
|