Skip to content

Latest commit

 

History

History
124 lines (104 loc) · 7.87 KB

README.md

File metadata and controls

124 lines (104 loc) · 7.87 KB

CachedLookup: A Simple Package To Cache And Save On Expensive Lookups & Operations.

NPM version NPM downloads GitHub issues GitHub stars GitHub license

Motivation

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.

Features

  • Simple-to-use API
  • TypeScript Support
  • Dynamic Cache Consumption
  • CPU & Memory Efficient
  • No Dependencies

Installation

CachedLookup can be installed using node package manager (npm)

npm i cached-lookup

How To Use?

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
    });
});

CachedLookup

Below is a breakdown of the CachedLookup class.

Constructor Parameters

  • new CachedLookup(Function: lookup): Creates a new CachedLookup instance with default options.
  • new CachedLookup(Object?: options, Function(...arguments): lookup): Creates a new CachedLookup instance with custom options.
    • 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
      • 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
    • lookup [Function]: Lookup handler which is called to get fresh values.
      • Note! this callback can be either synchronous or asynchronous.
      • 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 this lookup handler.

CachedLookup Properties

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.

CachedLookup Methods

  • cached(Number: max_age, ...arguments): Returns the cached value for the provided set of arguments from the lookup handler. Automatically falls back to a fresh() value if no cached value within the max_age is available.
    • Returns a Promise which is resolved to the cached value with a fall back to the fresh value.
    • Note the parameter max_age should be a Number in milliseconds 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 the max_age will be available inside of the lookup handler function.
    • Note this method should be used over rolling() if you want to ensure cache freshness within the max_age threshold at the sacrifice of increased latency whenever a fresh() is resolved to satify the max_age requirement.
  • rolling(Number: target_age, ...arguments): Returns the cached value for the provided set of arguments from the lookup handler. Instantly resolves the most recently cached value while triggering a fresh() value call in the background to reload the cache on a rolling basis according to the target_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.
  • fresh(...arguments): Retrieves the fresh value for the provided set of arguments from the lookup handler.
    • Returns a Promise which is resolved to the fresh value.
  • get(...arguments): Returns the cached value for the provided set of arguments if one exists in cache.
    • Returns the cached value or undefined.
  • expire(...arguments): Expires the cached value for the provided set of arguments.
    • Returns a Boolean which specifies whether a cached value was expired or not.
  • in_flight(...arguments): Checks whether a fresh value is currently being resolved for the provided set of arguments.
    • Returns a Boolean to specify the result.
  • updated_at(...arguments): Returns the last value update timestamp in milliseconds for the provided set of arguments.
    • Returns a Number or undefined if no cached value exists.
  • 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 an Array of these types.

CachedLookup Events

  • [fresh]: The fresh event is emitted whenever a fresh value is retrieved from the lookup function with a given set of arguments.
    • Example: CachedLookup.on('fresh', (value, arg1, arg2, arg3) => { /* Your Code */ });
  • [purge]: The purge event is emitted whenever a stale cache value is purged from the cache.
    • Example: CachedLookup.on('purge', (value, arg1, arg2, arg3) => { /* Your Code */ });

ValueRecord Properties

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.

License

MIT