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

autocache

v1.1.0

Published

Caching system that automatically populates itself

Downloads

11

Readme

Autocache

Travis Status

TL;DR memorisation back by a persistent store.

Instead of caching single keys and values, autocache allows you to define a setter and when a request for that key is placed, it will run the setter live, caching the result and returning it.

Importantly, the autocache can, and should be used with a persistent store so long as the adapter implements the storage api.

Note that by default, the cache is stored in memory (which kinda isn't the point), so when you restart, the cache will be lost.

Usage

Autocache can be used either on the server or on the client (again, recommended with a persistent adapter).

General usage:

  • Define a storage proceedure against a key
  • Get the key value
  • Clear/invalidate values

Note that autocache is a singleton, so we only need to set the store once.

var redisAC = require('autocache-redis');
var cache = require('autocache')({ store: redisAC });

cache.define('testStatus', function (done) {
  // call an imaginary test status API
  http.request('/test-status').then(function (result) {
    done(null, result.status);
  }).catch(function (error) {
    done(error);
  });
});

...now in another script elsewhere:

var cache = require('autocache');

app.get('/status', function (req, res) {
  cache.get('testStatus', function (error, status) {
    if (error) {
      return res.send(error);
    }

    res.render(status === 'pass' ? 'test-passing' : 'test-fail');
  });
});

// every 10 minutes, clear the cache
// note: we could also do this using the object notation and the TTL property
setInterval(function () {
  cache.clear('testStatus');
}, 10 * 60 * 1000);

Important notes

  • If an update is taking a long time, this does not block .get requests. The gets will be served with the old value until the update has completed and commited a new value.
  • Calls to .clear will queue (and thus block) gets until the clear is complete, after which the .get requests are automatically flushed.

Adapters

Current adapters:

Please do contribute your own adapters - missing: mongodb, memcache, sqlite..?

Methods

cache.define(string, function)

For a particular string key, set a function that will return a cached value.

Note that the function can be synchronous or asynchronous. If your code accepts a done function, you can pass the value you wish to cache to the done function argument (as seen in the usage example above).

cache.define(options)

As above, but with extended options:

{
  name: "string",
  update: function () {},
  ttl: 1000, // time to live (ms)
  ttr: 1000, // time to refresh (ms)
}

TTL will auto expire (and clear) the entry based on the ttl milliseconds since the last time it was accessed.

Note that if ttr is present, ttl will be ignored.

cache.get(string, function)

If a cached value is available for string it will call your function with an error first, then the result.

If there is no cached value, autocache will run the definition, cache the value and then call your function.

If multiple calls are made to get under the same string value, and the value hasn't been cached yet, the calls will queue up until a cached value has been returned, after which all the queued functions will be called.

cache.get(string, [fn args], function)

Cache getting also supports arguments to your definition function. This is only supported on async definitions.

For example:

cache.define('location', function (name, done) {
  xhr.get('/location-lookup/' + name).then(function (result) {
    done(null, result);
  }).catch(function (error) {
    done(error);
  });
});

// this will miss the cache, and run the definition
cache.get('location', 'brighton', function (error, data) {
  // does something with data
});

// this will ALSO miss the cache
cache.get('location', 'berlin', function (error, data) {
  // does something with data
});

// this will hit the cache
cache.get('location', 'berlin', function (error, data) {
  // does something with data
});

In the above example, once the cache is called with the argument brighton, the name and argument are now the unique key to the cache.

cache.update(string, function)

Calls the definition for the string, caches it internally, and calls your function with and error and the result.

cache.clear([string])

Clear all (with no arguments) or a single cached entry.

cache.destroy([string])

Destroy the all definitions (with no arguments) or a single definition entry.

cache.configure({ store: adapter })

Set and store the storage adapter for persistent storage. See notes on adapters.

cache.reset()

Clear all of the internal state of the cache, except for the storage adapter.

Storage API

If you want to write your own adapter for persistent storage you must implement the following functions:

get(key<string>, callback<function>) // get single
set(key<string>, value<string>, callback<function>) // set single
destroy([key<string>], callback<function>) // delete single
clear(callback<function>) // delete all
dock(autocache<Autocache>) // passes copy of active cache
toString() // returns a string representation of your store (for debugging)

See the adapters for examples of code.

Notes:

  1. Callbacks must pass an error first object, then the value. The value should be undefined if not found.
  2. Callbacks are expected to be asynchronous (but are acceptable as synchronous).
  3. clear should only clear objects created by the cache (which can be identified by a prefix).
  4. Calling the adapter function should accept the autocache as an argument, example below.
  5. Autocache will handle converting user objects to and from JSON, so the adapter will always be storing a string.
  6. dock is called with the autocache instance passed in, if the store is already connected, you should call autocache.emit('connect') immediately.

Important once your adapter has been attached, it should emit a connect event:

// this tells autocache that we're reading to start caching
autocache.emit('connect');

Automatically setting the autocache store

When the adapter is required, the user must be able to pass the autocache object into your adapter. This call will set the autocache's store to your adapter.

Below is the code from the localStorage adapter. It returns the store if called, but also checks if the autocache was passed in, and if it was, calls the configure function to assign the store as itself:

function LocalStore(autocache) {
  if (autocache) {
    autocache.configure({ store: new LocalStore() });
    return LocalStore;
  }
}

TODO

  • Test prefix support

License

MIT