Folk and modify from cache-manager. A cache module for NodeJS that allows easy wrapping of functions in cache, tiered caches, and a consistent interface.
- Made with Typescript and compatible with ESModules.
- Easy way to wrap any function in cache, supports a mechanism to refresh expiring cache keys in background.
- Tiered caches -- data gets stored in each cache and fetched from the highest priority cache(s) first.
- Use with any Keyv-compatible storage adapter.
- 100% test coverage via vitest.
yarn add keyv-caching
By default, everything is stored in memory; you can optionally also install a storage adapter; choose one from any of the storage adapters supported by Keyv:
yarn add @keyv/redis
yarn add @keyv/memcache
yarn add @keyv/mongo
yarn add @keyv/sqlite
yarn add @keyv/postgres
yarn add @keyv/mysql
yarn add @keyv/etcd
Please read Keyv document for more information.
import Keyv from 'keyv'
import KeyvRedis from '@keyv/redis'
import KeyvSqlite from '@keyv/sqlite'
import { createCache } from 'keyv-caching';
// Memory store by default
const cache = createCache()
// Single store
const cache = createCache({
stores: [new Keyv()],
})
// Multiple stores
const cache = createCache({
stores: [
// Redis store
new Keyv({
store: new KeyvRedis('redis://user:pass@localhost:6379'),
}),
// Sqlite store
new Keyv({
store: new KeyvSqlite('cache.db'),
}),
],
})
// With default ttl and refreshThreshold
const cache = createCache({
ttl: 10000,
refreshThreshold: 3000,
})
await cache.set('foo', 'bar')
// => bar
await cache.get('foo')
// => bar
await cache.del('foo')
// => true
await cache.get('foo')
// => null
await cache.wrap('key', () => 'value')
// => value
-
stores?: Keyv[]
List of Keyv instance. Please refer to the Keyv document for more information.
-
ttl?: number - Default time to live in milliseconds.
The time to live in milliseconds. This is the maximum amount of time that an item can be in the cache before it is removed.
-
refreshThreshold?: number - Default refreshThreshold in milliseconds.
If the remaining TTL is less than refreshThreshold, the system will update the value asynchronously in background.
set(key, value, [ttl]): Promise<value>
Sets a key value pair. It is possible to define a ttl (in miliseconds). An error will be throw on any failed
await cache.set('key-1', 'value 1')
// expires after 5 seconds
await cache.set('key 2', 'value 2', 5000)
See unit tests in test/set.test.ts
for more information.
get(key): Promise<value>
Gets a saved value from the cache. Returns a null if not found or expired. If the value was found it returns the value.
await cache.set('key', 'value')
await cache.get('key')
// => value
await cache.get('foo')
// => null
See unit tests in test/get.test.ts
for more information.
del(key): Promise<true>
Delete a key, an error will be throw on any failed.
await cache.set('key', 'value')
await cache.get('key')
// => value
await cache.del('key')
await cache.get('key')
// => null
See unit tests in test/del.test.ts
for more information.
clear(): Promise<true>
Flush all data, an error will be throw on any failed.
await cache.set('key-1', 'value 1')
await cache.set('key-2', 'value 2')
await cache.get('key-1')
// => value 1
await cache.get('key-2')
// => value 2
await cache.clear()
await cache.get('key-1')
// => null
await cache.get('key-2')
// => null
See unit tests in test/clear.test.ts
for more information.
wrap(key, fn: async () => value, [ttl], [refreshThreshold]): Promise<value>
Wraps a function in cache. The first time the function is run, its results are stored in cache so subsequent calls retrieve from cache instead of calling the function.
If refreshThreshold
is set and the remaining TTL is less than refreshThreshold
, the system will update the value asynchronously. In the meantime, the system will return the old value until expiration.
await cache.wrap('key', () => 1, 5000, 3000)
// call function then save the result to cache
// => 1
await cache.wrap('key', () => 2, 5000, 3000)
// return data from cache, function will not be called again
// => 1
// wait 3 seconds
await sleep(3000)
await cache.wrap('key', () => 2, 5000, 3000)
// return data from cache, call function in background and save the result to cache
// => 1
await cache.wrap('key', () => 3, 5000, 3000)
// return data from cache, function will not be called
// => 2
await cache.wrap('error', () => {
throw new Error('failed')
})
// => error
NOTES:
- The store that will be checked for refresh is the one where the key will be found first (highest priority).
- If the threshold is low and the worker function is slow, the key may expire and you may encounter a racing condition with updating values.
- If no
ttl
is set for the key, the refresh mechanism will not be triggered.
See unit tests in test/wrap.test.ts
for more information.
Fired when a key has been added or changed.
cache.on('set', ({ key, value, error }) => {
// ... do something ...
})
Fired when a key has been removed manually.
cache.on('del', ({ key, error }) => {
// ... do something ...
})
Fired when the cache has been flushed.
cache.on('clear', (error) => {
if (error) {
// ... do something ...
}
})
Fired when the cache has been refreshed in the background.
cache.on('refresh', ({ key, value, error }) => {
if (error) {
// ... do something ...
}
})
See unit tests in test/events.test.ts
for more information.
If you would like to contribute to the project, please read how to contribute here CONTRIBUTING.md.
Released under the MIT license.