cacheable 2.0.2 → 2.1.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/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![npm](https://img.shields.io/npm/v/cacheable)](https://www.npmjs.com/package/cacheable)
9
9
  [![license](https://img.shields.io/github/license/jaredwray/cacheable)](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` (coming soon). It is built on top of the robust storage engine [Keyv](https://keyv.org) and provides a simple API to cache and retrieve data.
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 (coming soon)
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
- * [CacheSync - Distributed Updates](#cachesync---distributed-updates)
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
- # CacheSync - Distributed Updates
362
+ # CacheableSync - Distributed Updates
363
363
 
364
- `cacheable` has a feature called `CacheSync` that is coming soon. This feature will allow you to have distributed caching with Pub/Sub. This will allow you to have multiple instances of `cacheable` running and when a value is set, deleted, or cleared it will update all instances of `cacheable` with the same value. Current plan is to support the following:
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
- * [AWS SQS](https://aws.amazon.com/sqs)
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
- This feature should be live by end of year.
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