This package aims to simplify the task of implementing a short-lived caching system for an endpoint which may be calling another third party API under the hood with a usage/rate limit. This package can also help to alleviate pressure when consuming data from databases or I/O network operations by implementing a short lived cache that does not scale relative to incoming requests.
- Simple-to-use API
- TypeScript Support
- Dynamic Cache Consumption
- CPU & Memory Efficient
- No Dependencies
CachedLookup can be installed using node package manager (npm
)
npm i cached-lookup
Below is a small snippet that shows how to use a CachedLookup
instance.
const CachedLookup = require('cached-lookup');
// Create a cached lookup instance which fetches music concerts from different cities on a specific date
const ConcertsLookup = new CachedLookup(async (country, state, city) => {
// Assume that the function get_city_concerts() is calling a Third-Party API which has a rate limit
const concerts = await get_city_concerts(country, state, city);
// Simply return the data and CachedLookup will handle the rest
return concerts;
});
// Create some route which serves this data with a 10 second intermittent cache
webserver.get('/api/concerts/:country/:state/:city', async (request, response) => {
// Retrieve the city value from the request - assume there is user validation done on this here
const { country, state, city } = request.path_parameters;
// Retrieve data from the CachedLookup with the cached() and pass the city in the call to the lookup handler
// Be sure to specify the first parameter as the max_age of the cached value in milliseconds
// In our case, 10 seconds would be 10,000 milliseconds
const concerts = await ConcertsLookup.cached(1000 * 10, country, state, city);
// Simply return the data to the user
// Because we retrieved this data from the ConcertsLookup with the cached() method
// We can safely assume that we will only perform up to 1 Third-Party API request per city every 10 seconds
return response.json({
concerts
});
});
Below is a breakdown of the CachedLookup
class.
new CachedLookup(Function: lookup)
: Creates a new CachedLookup instance with defaultoptions
.new CachedLookup(Object?: options, Function(...arguments): lookup)
: Creates a new CachedLookup instance with customoptions
.options
[Object
]: Constructor options for this instance.auto_purge
[Boolean
]: Whether to automatically purge cache values when they have aged past their last known maximum age.- Default:
true
- Default:
purge_age_factor
[Number
]: The factor by which to multiply the last known maximum age of a cache value to determine the age at which it should be purged.- Default:
1.5
- Default:
lookup
[Function
]: Lookup handler which is called to get fresh values.- Note! this callback can be either
synchronous
orasynchronous
. - Note! you must
return
/resolve
a value through this callback for the caching to work properly. - Note!
arguments
passed to the methods below will be available in each call to thislookup
handler.
- Note! this callback can be either
Property | Type | Description |
---|---|---|
lookup |
function(...arguments) |
Lookup handler of this instance. |
cache |
Map<string, ValueRecord> |
Internal map of cached values. |
promises |
Map<string, Promise<T>> |
Internal map of promises for pending lookups. |
cached(Number: max_age, ...arguments)
: Returns thecached
value for the provided set ofarguments
from the lookup handler. Automatically falls back to afresh()
value if no cached value within themax_age
is available.- Returns a
Promise
which is resolved to thecached
value with a fall back to thefresh
value. - Note the parameter
max_age
should be aNumber
inmilliseconds
to specify the maximum acceptable cache age. - Note this method will automatically fall back to a
fresh()
call if no viable cache value is available. - Note the returned
Promise
will reject when the lookup handler also rejects. - Note the provided
arguments
after themax_age
will be available inside of thelookup
handler function. - Note this method should be used over
rolling()
if you want to ensure cache freshness within themax_age
threshold at the sacrifice of increased latency whenever afresh()
is resolved to satify themax_age
requirement.
- Returns a
rolling(Number: target_age, ...arguments)
: Returns thecached
value for the provided set ofarguments
from the lookup handler. Instantly resolves the most recently cached value while triggering afresh()
value call in the background to reload the cache on a rolling basis according to thetarget_age
.- Note this method has the same signature as the
cached()
method above. - Note this method should be used over
cached()
if you want to maintain low latency at the sacrifice of guaranteed cache freshness.
- Note this method has the same signature as the
fresh(...arguments)
: Retrieves thefresh
value for the provided set of arguments from the lookup handler.- Returns a
Promise
which is resolved to thefresh
value.
- Returns a
get(...arguments)
: Returns thecached
value for the provided set of arguments if one exists in cache.- Returns the
cached
value orundefined
.
- Returns the
expire(...arguments)
: Expires thecached
value for the provided set of arguments.- Returns a
Boolean
which specifies whether acached
value was expired or not.
- Returns a
in_flight(...arguments)
: Checks whether afresh
value is currently being resolved for the provided set of arguments.- Returns a
Boolean
to specify the result.
- Returns a
updated_at(...arguments)
: Returns the last value updatetimestamp
in milliseconds for the provided set of arguments.- Returns a
Number
orundefined
if no cached value exists.
- Returns a
clear()
: Clears all the cached values and resets the internal cache state.- Note the
...arguments
are optional but must be of the following types:Boolean
,Number
,String
or anArray
of these types.
- [
fresh
]: Thefresh
event is emitted whenever a fresh value is retrieved from thelookup
function with a given set of arguments.- Example:
CachedLookup.on('fresh', (value, arg1, arg2, arg3) => { /* Your Code */ });
- Example:
- [
purge
]: Thepurge
event is emitted whenever a stale cache value is purged from the cache.- Example:
CachedLookup.on('purge', (value, arg1, arg2, arg3) => { /* Your Code */ });
- Example:
Property | Type | Description |
---|---|---|
value |
T (Generic) |
The cached value. |
max_age |
`undefined | Number` |
updated_at |
Number |
Timestamp (In milliseconds) of when this value was cached. |