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

locustjs-cache

v1.3.0

Published

This library provides a simple caching class.

Downloads

3

Readme

locustjs-cache

This library provides a simple caching utility in an abstract manner.

It can be used independently in any javascript project, however, since the abstraction layer locustjs-cache provides, it is best used in conjuction with an IoC container or DI container such as locustjs-locator.

Installation

NPM

npm i locustjs-cache

Yarn

yarn add locustjs-cache

Classes

CacheBase

This is the abstract class that defines structure/API of all Cache classes.

Constructor

constructor(config)

config is an optional configuration with the following structure that could be used by child classes based on their discretion:

{
    "duration": number  // default validity duration of cahced items
}

Methods

| Method | Result | Description | |--------|--------|-----------------------| | getEntry(key) | CacheItem | This method returns cache item entry in the cache based on its key. | | getItem(key, fnCondition?) | any (cached value) | This method returns a cached value based on its key. The get operation can be performed conditionally using the fnCondition function which is explained a little further. | | getItemAsync(key, fnCondition?) | Promise<any> (cached value) | This method acts the same way as getItem(). It just returns a promise, since it supports asynchronous fnCondition. | | setItem(key, value, duration?) | void | This method adds a new cache item into cache with specified duration. if duration is not specified, config.duration will be used for given cache item. If an item already exists in the cache with the same key, it is overwritten unconditionally. In order to perform an add/update operation, developers should use addOrUpdate method. | | setItemAsync(key, value, duration?) | Promise<any> | This method acts the same way as setItem(). It just returns a promise, since it supports asynchronous value factory. | | addOrUpdate(key, value, fnUpdate, duration) | any (cached value) | This method adds a new item into the cache with given value and key if an item does not already exist with the given key; Otherwise, it updates the existing cache entry with the new value based on the fnUpdate function. | | addOrUpdateAsync(key, value, fnUpdate, duration) | Promise<any> (cached value) | This method acts the same way as addOrUpdate(). It just returns a promise, since it supports asynchronous value factory and fnUpdate. | | getOrSet(key, fnCondition, value, duration?) | any (cached value) | This method returns a cached value if it already exists in the cahe. It adds a new item into cache if such item does not exist. The get operation can be conditional by specifying fnCondition function. This is explained a little further. | | getOrSetAsync(key, fnCondition, value, duration?) | Promise<any> (cached value) | This method acts the same way as getOrSet(). It just returns a promise, since it supports asynchronous value factory. | | exists(key) | boolean | This method checks whether an item with given key exists in the cache. | | remove(key) | boolean | This method removes a cached item with given key and returns true if succeeded (item was existing) or false (otherwise) | | contains(value, fnEqualityComparer?) | boolean | This methods looks in the cache for the given value and returns true if it finds a cach entry with this value or false (otherwise). If fnEqualityComparer function specified, it uses that in order to find cached entry when comparing given value with a cached value upon iterating over cached entries. | | clean() | void | This method cleans cache; removes items that are invalid (expired) but staying in the cache and wasting memory. | | clear() | void | This method clears out the cache (removes all entries). | | getDuration(duration) | number | This is a helper protected method that is inherited to sub-classes. It validates given duation value. a zero or lower than zero value indicates that the item is expired. |

Properties

| Property | Description | |--------|-------------------------------| | config | configuration passed to cache class constructor. | | length | Number of items in the cache. |

Notes

  1. There is no restriction in the format or type of cache keys. It is upon CacheBase sub-classes to approve/reject any value based on their implementaton. Normally, string values are used for cache keys, however, numbers could also be used. It is important though to know that, in order for the application -that depends on CacheBase abstraction- to work correctly, cache implementations should have a consistent behavior (use the same key type/format) regarding cache entries' keys. This is a developer concern not a locustjs-cache concern.
  2. Signature of fnCondition function in getItem() or getOrSet() is as follows:
function fnCondition(cache: CacheBase, entry: CacheItem): boolean

For their async equivalent, i.e. getItemAsync() and getOrSetAsync(), the signature could be either of the followings:

function fnCondition(cache: CacheBase, entry: CacheItem): boolean
function fnCondition(cache: CacheBase, entry: CacheItem): Promise<boolean>

That is, getItemAsync or getOrSetAsync should support both sync and async functions regarding fnCondition.

The fnCondition function enables developer to conditionally get items based on a custom business used in his fnCondition. This way, the developer is able to bind validity of cached items to his custom business logic.

CacheBase sub-classes are expected follow the following rules regrding fnCondition function.

  • They should call this function upon finding a cached value when getItem or getOrSet or their async versions is called.
  • Upon invokation, they should pass their instance reference together with the found cached value to fnCondition.
  • They should invalidate the cache entry if fnCondition returns false.
  1. fnEqualityComparer function in contains() method has the following signature:
function fnEqualityComparer(valueA, valueB): boolean

By default, contains() method should use === when comparing values.

  1. In addOrUpdate method, fnUpdate has the following signature:
function fnUpdate(cache: CacheBase, oldValue: any, currentValue: any): any

For the async equivalent, i.e. addOrUpdateAsync(), the signature could be either of the followings:

function fnUpdate(cache: CacheBase, oldValue: any, currentValue: any): any
function fnUpdate(cache: CacheBase, oldValue: any, currentValue: any): Promise<any>

That is, addOrUpdateAsync should support both sync and async functions regarding fnUpdate.

CacheDefault

This is a default working implementation of CacheBase. It stores cached items in an internal array. Cache entries are stored as CacheItem instances in the array.

CacheItem

This class defines structure of cache entries. Its structure is as follows:

{
    "key": string,  // cache key
    "value": any,   // cached value
    "createdDate": date,    // date/time when cache entry was stored in the cache
    "lastHit": date,    // date/time when cache entry was last hit
    "hits": number, // how many times the item was last hit (requested)
    "duration": number  // how long cached value can be assumed valid and stay in the cache (in milliseconds)
}

CacheItem has the following methods:

| Method | Result | Description | |--------|-------------------------------|-----| | isValid() | boolean | Specifies whether cache entry is valid (not expired) or not. | | setValue(value, duration) | void | sets value and duration of current entry to given value and duration. | | hit() | void | updates current cache entry's number of hits and lastHit field. It is used by CacheDefault and is called whenever an existing cache item is requested by user in getItem or getOrSet methods. | | invalid() | void | Invalidates cache entry. |

CacheNull

This is a no-cache implementation of CacheBase that does not store anything and its getItem always returns null. It can be used whenever application intends to disable caching.

Examples

Example 1: Normal getItem/setItem, no condition

const user = { id: '123', username: 'john.doe', email: '[email protected]' }

const cache = new CacheDefault({ duration: 5000 });

cache.setItem(user.id, user);

const u = cache.getItem(user.id);

console.log(cache.length);     // 1
console.log(cache.exists(user.id));     // true
console.log(u);

Example 2: contains()

const user = { id: '123', username: 'john.doe', email: '[email protected]' }

const cache = new CacheDefault({ duration: 5000 });

cache.setItem(user.id, user);

console.log(cache.contains(user));     // false
console.log(cache.contains(user, (ua, ub) => ua.id === ub.id));     // true

Example 3: conditional getItem

const cache = new CacheDefault({ duration: 5000 });

cache.setItem('key1', 24);
cache.setItem('key2', 100);

let x = cache.getItem('key2', c => c.exists('key1'));

console.log(cache.exists('key2'));     // true
console.log(x); // 100

cache.remove('key1');

x = cache.getItem('key2', c => c.exists('key1'));

console.log(cache.exists('key2'));     // false
console.log(x); // undefined

Conditional getItem() is useful when we have a parent/child relationship between our entities. We can get child entities from cache conditionally, say. if their parent is still in the cache or its properties matches we already have in our child.

Example 4: conditional getItem, async

async function doSomething() {
    const cache = new CacheDefault({ duration: 5000 });

    async function getChild(childKey, parentKey) {
        const result = await cache.getItemAsync(childKey, c => new Promise(res => {
            setTimeout(() => {
                res(c.exists(parentKey));
            }, 2000);
        }));

        return result;
    }

    cache.setItem('key1', 24);
    cache.setItem('key2', 100);

    let x = await getChild('key1', 'key2');

    console.log(cache.exists('key2'));     // true
    console.log(x); // 100

    cache.remove('key1');

    x = await getChild('key1', 'key2');

    console.log(cache.exists('key2'));     // false
    console.log(x); // undefined
}