Skip to content

Commit

Permalink
cache-manager - feat: adding in stores property (#981)
Browse files Browse the repository at this point in the history
* cache-manager - feat: adding in stores property

* adding in disconnect

* adding in stores in readme

* adding in iterator documentation

* adding in TOC

* updating modules
  • Loading branch information
jaredwray authored Jan 23, 2025
1 parent 6d1fd20 commit 7697d40
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 7 deletions.
46 changes: 45 additions & 1 deletion packages/cache-manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ If you are looking for older documentation you can find it here:
* [.mdel](#mdel)
* [.clear](#clear)
* [.wrap](#wrap)
* [.disconnect](#disconnect)
* [Events](#events)
* [.set](#set)
* [.del](#del)
* [.clear](#clear)
* [.refresh](#refresh)
* [Properties](#properties)
* [.cacheId](#cacheId)
* [.stores](#stores)
* [Doing Iteration on Stores](#doing-iteration-on-stores)
* [Update on `redis` and `ioredis` Support](#update-on-redis-and-ioredis-support)
* [Using Legacy Storage Adapters](#using-legacy-storage-adapters)
* [Contribute](#contribute)
Expand Down Expand Up @@ -370,10 +375,17 @@ await cache.disconnect();

See unit tests in [`test/disconnect.test.ts`](./test/disconnect.test.ts) for more information.

# Properties

## cacheId
`cacheId(): string`

Returns cache instance id.
Returns cache instance id. This is primarily used to not have conflicts when using `wrap` with multiple cache instances.

## stores
`stores(): Keyv[]`

Returns the list of Keyv instances. This can be used to get the list of stores and then use the Keyv API to interact with the store directly.

```ts
const cache = createCache({cacheId: 'my-cache-id'});
Expand Down Expand Up @@ -424,6 +436,38 @@ cache.on('refresh', ({ key, value, error }) => {

See unit tests in [`test/events.test.ts`](./test/events.test.ts) for more information.

# Doing Iteration on Stores

You can use the `stores` method to get the list of stores and then use the Keyv API to interact with the store directly. Below is an example of iterating over all stores and getting all keys:

```ts
import Keyv from 'keyv';
import { createKeyv } from '@keyv/redis';
import { createCache } from 'cache-manager';

const keyv = new Keyv();
const keyvRedis = createKeyv('redis://user:pass@localhost:6379');

const cache = createCache({
stores: [keyv, keyvRedis],
});

// add some data
await cache.set('key-1', 'value 1');
await cache.set('key-2', 'value 2');

// get the store you want to iterate over. In this example we are using the second store (redis)
const store = cache.stores[1];

if(store?.iterator) {
for await (const [key, value] of store.iterator({})) {
console.log(key, value);
}
}
```

WARNING: Be careful when using `iterator` as it can cause major performance issues with the amount of data being retrieved. Also, Not all storage adapters support `iterator` so you may need to check the documentation for the storage adapter you are using.

# Update on redis and ioredis Support

We will not be supporting `cache-manager-ioredis-yet` or `cache-manager-redis-yet` in the future as we have moved to using `Keyv` as the storage adapter `@keyv/redis`.
Expand Down
12 changes: 6 additions & 6 deletions packages/cache-manager/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cache-manager",
"version": "6.3.2",
"version": "6.4.0",
"description": "Cache Manager for Node.js",
"type": "module",
"main": "./dist/index.cjs",
Expand Down Expand Up @@ -60,16 +60,16 @@
"keyv": "^5.2.3"
},
"devDependencies": {
"@faker-js/faker": "^9.3.0",
"@faker-js/faker": "^9.4.0",
"@keyv/redis": "^4.2.0",
"@types/node": "^22.10.2",
"@vitest/coverage-v8": "^2.1.8",
"@types/node": "^22.10.9",
"@vitest/coverage-v8": "^3.0.4",
"cache-manager-redis-yet": "^5.1.5",
"cacheable": "workspace:^",
"rimraf": "^6.0.1",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"vitest": "^2.1.8",
"typescript": "^5.7.3",
"vitest": "^3.0.4",
"xo": "^0.60.0"
},
"xo": {
Expand Down
2 changes: 2 additions & 0 deletions packages/cache-manager/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type Cache = {
) => EventEmitter;
disconnect: () => Promise<undefined>;
cacheId: () => string;
stores: Keyv[];
};

export type Events = {
Expand Down Expand Up @@ -334,6 +335,7 @@ export const createCache = (options?: CreateCacheOptions): Cache => {
off,
disconnect,
cacheId,
stores,
};
};

Expand Down
45 changes: 45 additions & 0 deletions packages/cache-manager/test/stores.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {Keyv} from 'keyv';
import {createKeyv} from '@keyv/redis';
import {
describe, expect, it,
} from 'vitest';
import {simpleFaker} from '@faker-js/faker';
import {createCache} from '../src/index.js';

describe('stores', () => {
it('can get the keyv store', () => {
const cache = createCache();
expect(cache.stores.length).toEqual(1);
});

it('can see multiple stores', () => {
const keyv = new Keyv();
const redis = createKeyv();
const cache = createCache({stores: [keyv, redis]});
expect(cache.stores.length).toEqual(2);
expect(cache.stores[0]).toEqual(keyv);
expect(cache.stores[1]).toEqual(redis);
});

it('can get the keyv store and do iterator', async () => {
const cache = createCache();
expect(cache.stores.length).toEqual(1);
const keyName = simpleFaker.string.uuid();
const keyValue = simpleFaker.string.uuid();
await cache.set(keyName, keyValue);
const keyv = cache.stores[0];
expect(keyv).toBeInstanceOf(Keyv);

let returnValue;

if (keyv?.iterator) {
for await (const [key, value] of keyv.iterator({})) {
if (key === keyName) {
returnValue = value;
}
}
}

expect(returnValue).toEqual(keyValue);
});
});

0 comments on commit 7697d40

Please sign in to comment.