1.3.1 • Published 9 years ago
redis-cache-decorator v1.3.1
redis-cache-decorator
A decorator to cache your functions. Features:
- Uses Redis caching, expiration, and pub/sub.
- Concurrency locking - if the function is being run elsewhere with the same arguments, it will wait for the result of that function instead of executing again.
- Caching - caches results for as long as you want. If you set
ttl=0, then you're just this library for concurrency locking, which is completely fine. - Timeouts - throws when executing or waiting for a function call takes too long
- Only tested with ioredis
Use Cases:
- Race conditions
- API calls with rate limits
- Expensive database calls
- Expensive function calls
Example
Here's a function that caches all your queries.
const assert = require('assert')
const Redis = require('ioredis')
const pg = require('pg-then')
const pool = pg.Pool(process.env.POSTGRES_URI)
const CreateCacheDecorator = require('redis-cache-decorator')({
client: Redis.createClient(),
subscriber: Redis.createClient()
})
const fn = CreateCacheDecorator({
namespace: 'crazy-database-call',
})((query, values) => {
return db.query(query).then(result => result.rows)
})
fn(`
SELECT *
FROM users
WHERE id = $1
`, [
1
]).then(users => {
assert(Array.isArray(users))
})API
const CreateCacheDecorator = require('redis-cache-decorator')(options)
Creates a constructor with the following options:
client <required>- a redis client for GET/SET/PUBLISH, etc.subscriber <required>- a redis client forPSUBSCIRBEnamespace = ''- a prefix for all the eventsencoding = 'json'- how data is encoded between redis and node.js. Supported values are:json- the defaultstringbuffer
ttl = '30s'- the TTL expiration in seconds.timeout = '30s'- how long to wait for the function to execute.pollFactor = 1 / 10- the fraction of the timeout to poll. For example, a30stimeout with a1 / 10factor means that redis is polled for new changes every 3 seconds.minimumPollInterval = '100ms'- the minimum frequency of polling so you don't end up spamming rediscreateTimeoutError = () => <Error>{ message: 'Timed out!', code: 'RCDTIMEDOUT' }- the function called to create a timeout error. By default, you can check for timeout errors by checkingif (err.code === 'RCDTIMEDOUT').onError = err => console.error(err.stack)- an error handler for redis network errors.disabled = false- disable this decorator, specifically useful for testing.
const decorate = CreateCacheDecorator(options)
Create a decorator with a set of options.
namespace <required>- a namespace for this decoratorpollInterval- by default, calculated fromtimeout,pollFactor, andminimumPollInterval, but you can set this yourself.ttltimeoutpollFactorminimumPollIntervalcreateTimeoutErroronError
const decoratedFunction = decorate(fn)
Decorates the function. The decorated function will have the same API as the original function.
- The function should return a value or a
Promisethat can beJSON.stringify()d. - The function can be synchronous or asynchronous.
thisis not supported. Do not accessthiswithin the function. The primary reason is that it's difficult to decide how to cache.
const job = decoratedFunction(...args)
Execute the decorated function. Will always return a Promise that resolves to the value.
In addition, the promise will have the following properties:
.hash- hash of the arguments for this job.
job.then(value => {}, err => {})
Resolve the promise to retrieve the results of the job.
const hash = decoratedFunction.createHash(...args)
Create the hash string for the specified arguments.
decoratedFunction.set(hash, value).then(value => {})
Manually set the value of a hash.
Streams
If a stream is returned, the values will automatically be buffered.
encoding='json'- the stream will be concatenated as an object stream -> array. If the stream is not an object stream, it will throw.encoding='string'- the stream will be buffered into a string.encoding='buffer'- the stream will be buffered into aBuffer()instance.