npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

orchard

v3.0.1

Published

Read-through, fail-through, Redis-backed caching

Downloads

42

Readme

orchard Build Status Coverage Status

Read-through, fail-through, Redis-backed caching

Getting started

Prerequisites

  • Node.js 4.x (LTS) or newer
  • Redis 2.8 or newer

For local development, consider Docker for managing your Redis installation. First install the image:

docker run -d --name redis -p 6379:6379 redis:2.8

Then, run the image:

docker start redis

Install

Install with npm:

npm install --save orchard

Use

const Orchard = require('orchard');

const orchard = new Orchard();

orchard(key, () => value).then(console.log);

API

Orchard([options])

This module exports a constructor. Instantiate an Orchard cache with desired options:

const Orchard = require('orchard');

const options = {...};

const orchard = new Orchard(options);

Options

| Option | Type | Description | Default | | :----- | :--- | :---------- | :------ | | herdCacheParams | Object | Parameters passed to the internal, in-memory LRU cache | { max: 1024, maxAge: 60000 } | | keyHash | Function | Hashing function applied to resolved keys (prior to prefixing) | An identity function | | prefix | String | Prepended to resolved cache keys; use if a single database supports multiple caching services | None | | scanCount | Number | Hints Redis' SCAN command during keyspace enumeration (e.g. with delete) | 10 | | ttl | String or Number | Sets expiration for a cached value, a Number is treated as milliseconds and a String is treated as an ms duration | None | | url | String | Redis URI with required authentication | redis://localhost:6379 |

Notes:

  • herdCacheParams: To mitigate thundering herd risks, Orchard holds a key in memory while initially resolving the priming value; subsequent calls using the same key (within the same process) receive the same Promise until the value is resolved. This temporary cache is pruned to avoid unnecessary memory consumption.
  • keyHash: This function is invoked with the resolved key and should resolve to (or return) a deterministically hashed digest of the input. For example: function keyHash(key) { return makeDigest(key); }. By providing a hashing function at instantiation, applications can avoid hashing sensitive keys at every Orchard call-site.
  • ttl: Redis uses seconds for expiration timers; Orchard converts ttl from milliseconds to seconds, rounding down.

orchard(key, primingFunction[, options])

Retrieve data from the Orchard cache, invoking the priming function to prime the cache.

const Orchard = requirefastr'orchard');

const orchard = new Orchard(options);

orchard(key, () => Promise.resolve(value)).then(console.log);

Returns a Promise that resolves to the final value of the primingFunction. Internally, Orchard attempts to get the current value of key from the database. If the key does not exist or the database is not available, the primingFunction is invoked with the resolved key (in "raw" form, without the prefix and without the keyHash function applied) and the final value is set in the database for future use.

key can be any one of:

  • a String
  • a Promise that resolves to a String
  • a Function that returns a String
  • a Function that returns a Promise that resolves to a String

primingFunction can be any one of:

The Promise is rejected if there is an error resolving the primingFunction. Rejected cache calls are not persisted.

Warning: The key resolution process does not have the same stampede protections as the priming function. Instead, if key is a Function, it is invoked on every cache call. If you plan to remotely resolve the key you may want to consider caching the key function as well.

Options

| Option | Type | Description | Default | | :----- | :--- | :---------- | :------ | | force | Boolean | If true, ignore current cached value and overwrite with new value | false |

cache#del(key)

Immediately delete one or more keys and associated data from the Orchard cache.

const Orchard = require('orchard');

const orchard = new Orchard(options);

orchard.del(key).then(console.log);

Returns a Promise that resolves to the number of removed keys. If the last character of the resolved key is an asterisk (* – e.g. items:*), the key is treated as a pattern to use with Redis' SCAN and MATCH commands.

cache#on(eventName, eventListener)

Listen to events emitted by Orchard.

cache.on('cache:hit', console.log);

The cache instance is also an event emitter. eventName is a String corresponding to a supported event and eventListener is a callback function invoked each time the event is triggered.

cache:hit

{
  requestId: <String:UUID>,
  key: <String>,
  ms: <Number:Integer:Milliseconds>
}

ms is milliseconds elapsed between invocation and resolution of the cached value.

cache:miss

{
  requestId: <String:UUID>,
  key: <String>,
  ms: <Number:Integer:Milliseconds>
}

ms is milliseconds elapsed between invocation and resolution of the priming value before writing to the database.

redis:error

<Error>{
  code: <String>,
  errno: <String>,
  syscall: <String>
}

redis:ready

No event data

Development

Tests

To run the full test suite, including unit tests and linting:

npm test

To run the only the unit test suite:

npm run test-unit

This project maintains 100% coverage of statements, branches, and functions. To determine unit test coverage:

npm run coverage

To run the integrated test suit against a live Redis database (redis://localhost:6379):

npm run test-integrated

Warning: The integrated test suite deletes all keys prefixed with __ORCHARD_INTEGRATED_TEST.

Debug

This module is instrumented with debug to provide information about behavior during development. All debug invocations use the orchard prefix for targeted debug output:

DEBUG=orchard* npm test

Contribute

PRs are welcome! PRs must pass unit tests and linting prior to merge. For bugs, please include a failing test which passes when your PR is applied. To enable a git hook that runs npm test prior to pushing, cd into your repo and run:

touch .git/hooks/pre-push
chmod +x .git/hooks/pre-push
echo "npm test" > .git/hooks/pre-push

Versioning

This project follows semantic versioning. See the change log for release information.

License