Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
cache-manager
Advanced tools
The cache-manager npm package is a flexible caching library for Node.js applications, which supports a variety of storage solutions and provides a uniform API to interact with different caching mechanisms. It allows for easy integration and switching between different cache stores without changing the underlying application code.
Caching and Retrieving Data
This feature allows you to cache data in memory and retrieve it using a key. The 'set' method stores the value, and the 'get' method retrieves it. The 'ttl' option specifies the time-to-live in seconds.
{"const cacheManager = require('cache-manager');
const memoryCache = cacheManager.caching({ store: 'memory', max: 100, ttl: 10/*seconds*/ });
// Now set a value
memoryCache.set('myKey', 'myValue', { ttl: 5 }, (err) => {
if (err) { throw err; }
// Get the value
memoryCache.get('myKey', (error, result) => {
console.log(result);
// >> 'myValue'
});
});
}
Cache Store Agnosticism
Cache-manager supports different stores such as memory, Redis, and more. This feature allows you to switch between different cache stores seamlessly. The example shows how to use Redis as the cache store.
{"const cacheManager = require('cache-manager');
const redisStore = require('cache-manager-redis-store');
const redisCache = cacheManager.caching({ store: redisStore, host: 'localhost', port: 6379, auth_pass: 'XXXX', db: 0, ttl: 600 });
// Listen for redis ready event
redisCache.store.events.on('redisReady', () => {
console.log('Redis is ready');
});
// Listen for redis error event
redisCache.store.events.on('redisError', (error) => {
console.error('Redis error', error);
});
}
Multi-Level Caching
Cache-manager allows for multi-level caching, where you can have a hierarchy of cache stores. Data is first checked in the fastest cache (e.g., memory), and if not found, it falls back to slower caches (e.g., Redis).
{"const cacheManager = require('cache-manager');
const memoryCache = cacheManager.caching({ store: 'memory', max: 100, ttl: 10 });
const redisCache = cacheManager.caching({ store: require('cache-manager-redis-store'), ttl: 600 });
const multiCache = cacheManager.multiCaching([memoryCache, redisCache]);
multiCache.set('foo', 'bar', { ttl: 5 }, (err) => {
if (err) { throw err; }
multiCache.get('foo', (error, result) => {
console.log(result);
// >> 'bar'
});
});
}
node-cache is an in-memory caching package similar to cache-manager's memory store. It offers a simple and fast caching solution but does not support multiple backends or a tiered caching system.
lru-cache is an in-memory cache that implements the LRU (Least Recently Used) eviction policy. Unlike cache-manager, it is specifically tailored for LRU caching and does not support multiple storage backends.
keyv is a simple key-value storage with support for multiple backends, including Redis, MongoDB, SQLite, and more. It provides a unified interface across different stores but does not have built-in support for multi-level caching.
A cache module for NodeJS that allows easy wrapping of functions in cache, tiered caches, and a consistent interface.
nonBlocking
option that optimizes how the system handles multiple stores.We moved to using Keyv which are more actively maintained and have a larger community.
A special thanks to Tim Phan who took cache-manager
v5 and ported it to Keyv which is the foundation of v6. 🎉 Another special thanks to Doug Ayers who wrote promise-coalesce
which was used in v5 and now embedded in v6.
If you are looking for older documentation you can find it here:
CacheableMemory
or lru-cache
as storage adapterredis
and ioredis
Supportnpm install cache-manager
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:
npm install @keyv/redis
npm install @keyv/memcache
npm install @keyv/mongo
npm install @keyv/sqlite
npm install @keyv/postgres
npm install @keyv/mysql
npm install @keyv/etcd
In addition Keyv supports other storage adapters such as lru-cache
and CacheableMemory
from Cacheable (more examples below). Please read Keyv document for more information.
import { Keyv } from 'keyv';
import { createCache } from 'cache-manager';
// Memory store by default
const cache = createCache()
// Single store which is in memory
const cache = createCache({
stores: [new Keyv()],
})
Here is an example of doing layer 1 and layer 2 caching with the in-memory being CacheableMemory
from Cacheable and the second layer being @keyv/redis
:
import { Keyv } from 'keyv';
import KeyvRedis from '@keyv/redis';
import { CacheableMemory } from 'cacheable';
import { createCache } from 'cache-manager';
// Multiple stores
const cache = createCache({
stores: [
// High performance in-memory cache with LRU and TTL
new Keyv({
store: new CacheableMemory({ ttl: 60000, lruSize: 5000 }),
}),
// Redis Store
new Keyv({
store: new KeyvRedis('redis://user:pass@localhost:6379'),
}),
],
})
Once it is created, you can use the cache object to set, get, delete, and wrap functions in cache.
// 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
Because we are using Keyv, you can use any storage adapter that Keyv supports such as lru-cache
or CacheableMemory
from Cacheable. Below is an example of using CacheableMemory
:
In this example we are using CacheableMemory
from Cacheable which is a fast in-memory cache that supports LRU and and TTL expiration.
import { createCache } from 'cache-manager';
import { Keyv } from 'keyv';
import { KeyvCacheableMemory } from 'cacheable';
const store = new KeyvCacheableMemory({ ttl: 60000, lruSize: 5000 });
const keyv = new Keyv({ store });
const cache = createCache({ stores: [keyv] });
Here is an example using lru-cache
:
import { createCache } from 'cache-manager';
import { Keyv } from 'keyv';
import { LRU } from 'lru-cache';
const keyv = new Keyv({ store: new LRU({ max: 5000, maxAge: 60000 }) });
const cache = createCache({ stores: [keyv] });
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.
nonBlocking?: boolean - Default false
If set to true, the system will not block when multiple stores are used. Here is how it affects the type of functions:
set and mset
- will not wait for all stores to finish.get and mget
- will return the first (fastest) value found.del and mdel
- will not wait for all stores to finish.clear
- will not wait for all stores to finish.wrap
- will do the same as get
and set
(return the first value found and not wait for all stores to finish).set(key, value, [ttl]): Promise<value>
Sets a key value pair. It is possible to define a ttl (in milliseconds). 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.
mset(keys: [ { key, value, ttl } ]): Promise<true>
Sets multiple key value pairs. It is possible to define a ttl (in milliseconds). An error will be throw on any failed
await cache.mset([
{ key: 'key-1', value: 'value 1' },
{ key: 'key-2', value: 'value 2', ttl: 5000 },
]);
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.
mget(keys: [key]): Promise<value[]>
Gets multiple saved values from the cache. Returns a null if not found or expired. If the value was found it returns the value.
await cache.mset([
{ key: 'key-1', value: 'value 1' },
{ key: 'key-2', value: 'value 2' },
]);
await cache.mget(['key-1', 'key-2', 'key-3'])
// => ['value 1', 'value 2', null]
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.
mdel(keys: [key]): Promise<true>
Delete multiple keys, an error will be throw on any failed.
await cache.mset([
{ key: 'key-1', value: 'value 1' },
{ key: 'key-2', value: 'value 2' },
]);
await cache.mdel(['key-1', 'key-2'])
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:
ttl
is set for the key, the refresh mechanism will not be triggered.See unit tests in test/wrap.test.ts
for more information.
disconnect(key): Promise<void>
Will disconnect from the relevant store(s). It is highly recomended to use this when using a Keyv storage adapter that requires a disconnect. For each storage adapter, the use case for when to use disconnect is different. An example is that @keyv/redis
should be used only when you are done with the cache.
await cache.disconnect();
See unit tests in test/disconnect.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.
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
.
There are many storage adapters built for cache-manager
and because of that we wanted to provide a way to use them with KeyvAdapter
. Below is an example of using cache-manager-redis-yet
:
import { createCache, KeyvAdapter } from 'cache-manager';
import { Keyv } from 'keyv';
import { redisStore } from 'cache-manager-redis-yet';
const adapter = new KeyvAdapter( await redisStore() );
const cache = createCache({
stores: [new Keyv({ store: adapter })],
});
This adapter will allow you to add in any storage adapter. If there are issues it needs to follow CacheManagerStore
interface.
If you would like to contribute to the project, please read how to contribute here CONTRIBUTING.md.
FAQs
Cache Manager for Node.js
The npm package cache-manager receives a total of 996,803 weekly downloads. As such, cache-manager popularity was classified as popular.
We found that cache-manager demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.