catbox
Installation:

npm: npm install @hapi/catbox

yarn: yarn add @hapi/catbox

catbox is a multi-strategy key-value object store. It comes with extensions supporting a memory cache, Redis, and Memcached. Additional providers from the community can be found on the npm Registry.

catbox provides two interfaces: a low-level Client and a high-level Policy.

Installation

In order to reduce module dependencies, catbox does not include the external caching strategies. To use other strategies, each service must be manually installed via npm or package dependencies manually. The available strategies are:

Client

The Client object provides a low-level cache abstraction. The object is constructed using new Client(engine, options) where:

  • engine - is an object or a prototype function implementing the cache strategy:
    • function - a prototype function with the signature function(options). catbox will call new func(options).
    • object - a pre instantiated client implementation object. Does not support passing options.
  • options - the strategy configuration object. Each strategy defines its own configuration options with the following common options:
    • partition - the partition name used to isolate the cached results across multiple clients. The partition name is used as the MongoDB database name, the Riak bucket, or as a key prefix in Redis and Memcached. To share the cache across multiple clients, use the same partition name.

Note that any implementation of client strategies must return deep copies of the stored data as the API assumes that the object returned from a get() is owned by the called and can be safely modified without affecting the cache copy.

API

The Client object provides the following methods:

  • await start() - creates a connection to the cache server. Must be called before any other method is available. Any errors are thrown.
  • await stop() - terminates the connection to the cache server.
  • await get(key) - retrieve an item from the cache engine if found where:
    • key - a cache key object (see below).
    • return value:
      • null is the item is not found.
      • throws an error if the request failed.
      • otherwise, an object with the following properties:
        • item - the value stored in the cache using set().
        • stored - the timestamp when the item was stored in the cache (in milliseconds).
        • ttl - the remaining time-to-live (not the original value used when storing the object).
  • await set(key, value, ttl) - store an item in the cache for a specified length of time, where:
    • key - a cache key object (see below).
    • value - the string or object value to be stored.
    • ttl - a time-to-live value in milliseconds after which the item is automatically removed from the cache (or is marked invalid).
    • any errors are thrown.
  • await drop(key) - remove an item from cache where:
    • key - a cache key object (see below).
    • any errors are thrown.
  • isReady() - returns true if cache engine determines itself as ready, false if it is not ready.
  • validateSegmentName(segment) - returns null if the segment name is valid (see below), otherwise should return an instance of Error with an appropriate message.

Any method with a key argument takes an object with the following required properties:

  • segment - a caching segment name string. Enables using a single cache server for storing different sets of items with overlapping ids.
  • id - a unique item identifier string (per segment). Can be an empty string.

Policy

The Policy object provides a convenient cache interface by setting a global policy which is automatically applied to every storage action. The object is constructed using new Policy(options, [cache, segment]) where:

  • options - is an object with the following optional keys (unless noted otherwise):
    • expiresIn - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used together with expiresAt.
    • expiresAt - time of day expressed in 24h notation using the 'HH:MM' format, at which point all cache records for the route expire. Uses local time. Cannot be used together with expiresIn.
    • generateFunc - a function used to generate a new cache item if one is not found in the cache when calling get(). The method's signature is async function(id, flags) where:
      • id - the id string or object provided to the get() method.
      • flags - an object used to pass back additional flags:
        • ttl - the cache ttl value in milliseconds. Set to 0 to skip storing in the cache. Defaults to the cache global policy.
    • staleIn - number of milliseconds to mark an item stored in cache as stale and attempt to regenerate it when generateFunc is provided. Must be less than expiresIn. Alternatively function that returns staleIn value in milliseconds. The function signature is function(stored, ttl) where:
      • stored - the timestamp when the item was stored in the cache (in milliseconds).
      • ttl - the remaining time-to-live (not the original value used when storing the object).
    • staleTimeout - number of milliseconds to wait before returning a stale value while generateFunc is generating a fresh value.
    • generateTimeout - number of milliseconds to wait before returning a timeout error when the generateFunc function takes too long to return a value. When the value is eventually returned, it is stored in the cache for future requests. Required if generateFunc is present. Set to false to disable timeouts which may cause all get() requests to get stuck forever.
    • dropOnError - if true, an error or timeout in the generateFunc causes the stale value to be evicted from the cache. Defaults to true.
    • generateOnReadError - if false, an upstream cache read error will stop the get() method from calling the generate function and will instead pass back the cache error. Defaults to true.
    • generateIgnoreWriteError - if false, an upstream cache write error will be passed back with the generated value when calling the get() method. Defaults to true.
    • pendingGenerateTimeout - number of milliseconds while generateFunc call is in progress for a given id, before a subsequent generateFunc call is allowed. Defaults to 0, no blocking of concurrent generateFunc calls beyond staleTimeout.
    • getDecoratedValue - if true, the return value of policy.get() calls is an object with { value, cached, report }. Defaults to false which returns a plain value.
  • cache - a Client instance (which has already been started).
  • segment - required when cache is provided. The segment name used to isolate cached items within the cache partition.

API

The Policy object provides the following methods:

  • await get(id) - retrieve an item from the cache. If the item is not found and the generateFunc method was provided, a new value is generated, stored in the cache, and returned. Multiple concurrent requests are queued and processed once. The method arguments are:
    • id - the unique item identifier (within the policy segment). Can be a string or an object with the required 'id' key.
    • return value:
      • the requested item if found, otherwise null.
      • any errors are thrown.
      • if getDecoratedValue is true, returns an object with the following properties:
        • value - the fetched or generated value.
        • cached - null if a valid item was not found in the cache, or an object with the following keys:
          • item - the cached value.
          • stored - the timestamp when the item was stored in the cache.
          • ttl - the cache ttl value for the record.
          • isStale - true if the item is stale.
        • report - an object with logging information about the generation operation containing the following keys (as relevant):
          • msec - the cache lookup time in milliseconds.
          • stored - the timestamp when the item was stored in the cache.
          • isStale - true if the item is stale.
          • ttl - the cache ttl value for the record.
          • error - lookup error.
  • await set(id, value, ttl) - store an item in the cache where:
    • id - the unique item identifier (within the policy segment).
    • value - the string or object value to be stored.
    • ttl - a time-to-live override value in milliseconds after which the item is automatically removed from the cache (or is marked invalid). This should be set to 0 in order to use the caching rules configured when creating the Policy object.
    • any errors are thrown.
  • await drop(id) - remove the item from cache where:
    • id - the unique item identifier (within the policy segment).
    • any errors are thrown.
  • ttl(created) - given a created timestamp in milliseconds, returns the time-to-live left based on the configured rules.
  • rules(options) - changes the policy rules after construction (note that items already stored will not be affected) where:
    • options - the same options as the Policy constructor.
  • isReady() - returns true if cache engine determines itself as ready, false if it is not ready or if there is no cache engine set.
  • stats - an object with cache statistics where:
    • sets - number of cache writes.
    • gets - number of cache get() requests.
    • hits - number of cache get() requests in which the requested id was found in the cache (can be stale).
    • stales - number of cache reads with stale requests (only counts the first request in a queued get() operation).
    • generates - number of calls to the generate function.
    • errors - cache operations errors.
  • events - a podium event emitter, emitting 'error' events under the following channels:
    • 'persist' - emits any cache errors thrown during the generation of new values as a result of a get() request.
    • 'generate' - emits any new value generation errors thrown as a result of a get() request.

Note that errors generated by set() and drop() are reported directly by the functions calls and are not included in the reported events.

Changelog

#220
Update joi
#217
Update deps
#216
Update joi dep
#215
Old pendingGenerateTimeout can clear new one
#210
If generate takes longer than staleTimeout, errors get swallowed
#214
Change module namespace
#208
Add changelog.md
#206
Support ioredis client option for catbox-redis
#205
Remove engines
#204
Update hoek v6
#201
Update lab
#200
Unhandled rejection on get() errors
#194
Add bounce protection
#193
Update boom
10.0.0
breaking changes
#192
Require clients to be async
9.0.0
breaking changes
#191
Change policy.get() return value to plain (with override option)
8.0.0
breaking changes
#190
Migrate to async/await
#213
Commercial version of v7 branch
#185
Fix pendingGenerateTimeout timeout issue
#178
Ensure generate timeout is triggered when staleTimeout > ttl
#166
Can we remove the max() from staleIn?
#165
Can't drop method without arguments
#176
Update deps
#168
Update deps
#162
Test on node v6, update dependencies
#152
Adding pendingGenerateTimeout
#149
Proposal: Stale while revalidate - prevent multiple generate calls
#147
Update drop function to allow for object keys
7.0.0
breaking changes
#146
ES6 style changes and node v4
#145
Fixed this.constructor issue
6.0.0
breaking changes
#140
Replace generate cache error handing options
5.0.0
breaking changes
#137
Add generateOnGetError option
#136
Pass cache set() errors when generating value on get()
#134
Require generateTimeout with generateFunc.
#128
Explicitly binding process.domain to the callback
#127
callbacks are called with wrong process.domain
#115
get() can get stuck when first request never returns
#70
No way to monitor cache error rates
#114
Expose cache engine connection isReady as public method
#120
Upgrade to Joi 6
#116
Prefix keys with a `'+'` when using object as a hash
#113
Allow empty keys
#109
Return cached on error when dropOnError is false
#105
StaleIn can be function.
#111
Allow changing policy rules after construction
#104
Fix tests
#103
Explicitly allow hapi keys in policy instead of allowUnknown
#102
Use joi for validating policy rules
4.0.0
breaking changes
#101
Change policy.get() callback to use a consistent signature regardless of generateFunc
#100
Require generateFunc options for staleIn, staleTimeout, and generateTimeout
#99
Remove getOrGenerate()
#98
Adding ability to retain a stale value when generate function fails
#97
Retain stale on error
#95
Leftover background timeouts can interlace with new requests
#93
Rarely cache can serve old value having slower backend
#86
Fix concurrent getOrGenerate bug. Closes #85
#85
Problems with concurrent invocation of getOrGenerate.
#84
null or undefined expiresIn/At break compile
#83
Errors thrown in get() block pending queue
#82
Allow setting cache with default expiresIn 0 (no cache)
#80
Allow setting policy without expiration when server side disabled
#79
Queue get requests
#78
Incomplete coverage when testing at 23:00
#77
expiredAt fails to zero milliseconds
#76
expiredAt returns negative ttl on created < expired < now
#75
Move generate method to policy config
#73
Chain concurrent gets
#71
Update to Lab 4
#69
Error fails to clear cache is error arrives before stale timeout
#68
staleTimeout for first request should returns null if no data at timeout time
3.0.0
breaking changes
#67
Remove internal require() call
#66
Remove large ttl check
#65
Move 32bit ttl restriction to catbox-memory
#62
Bring coverage back to 100%
#58
Allow falsey values to be cached
2.1.0
breaking changes
#56
Policy.getOrGenerate returns content in two different formats
#51
Impossible to use a custom storage backend with the Hapi CLI
#49
Close the redis connection on error
#14
Remove redis and mongodb dependencies (and move to devdeps)
#13
Remove hapi dependencies
#12
Need to better organize config options
#6
Add examples
#5
Document interfaces, features
#4
Bring test coverage to 100%
clipboard