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

distributed-systems-cache

v1.14.0

Published

distributed-systems-cache

Downloads

248

Readme

distributed-systems-cache

Set a cache, get a cache, define the cache object shape.

Table of Contents generated with DocToc

Overview

  • All content is expected to be a js object so everything is stringified on input and parsed on output.
  • All keys run through a regex check, ie the bit after the cache key prefix. This regex has a default but can be injected on setup.
  • All objects can be passed through a function to filter the persisted content, this must be injected on setup, else nothing is filtered.
  • All keys not found will be requested via the injected call to populate on setup, this can be anything from a RMQ call or REST or some arbitrary DB aggregation.
  • !Important: the call to populate function should call the setCache on its own, or trigger your application to do so, the response from the call to populate is expected to be void.

API

construct

You must initialise before calling another of the other methods, here are all the options from the source code: src/DistributedSystemsCache.ts

Here is an example: Connect first somewhere in your app

Options

For all options available and descriptions please see src/DistributedSystemsCache.ts

Method: setCache

Set a cache value, pass in a key and an object. The key will be automatically prefixed with the cacheKeyPrefix. The setCache will also add an updatedAt field to the object you provide, this will be used to determine the age of the cache on extraction.

async setCache (cacheKey: string, cacheObject: T): Promise<void>

Method: getCache

Gets a cache by key (excluding the prefix, this is prepended automatically). If the cache key is not found, the cachePopulator callback is called. After the grace time, it will try and fetch the cache again... It will repeat this up until a cache hit is found, or the qty of tries is equal to the cachePopulatorMaxTries. Each cache hit is returned and validated/ refreshed.

async getCache (cacheKey: string): Promise<T>

NB: the private validateAgeAndFetch method is called, but the getCache doesn't await the response. Instead, the callee will only catch and error console a rejected promise at this point.

Method: getAll

Does what you would imagine, grabs all the cache values for a given key.

Method: clearCacheRecord

Does what you would imagine, for a given cache key, it removes it (as usual, the prefix is added internally):

await distributedSystemsCache.clearCacheRecord('admin')

Method: clearAllCacheRecords

Does what you would imagine, clears all records for instantiated prefix:

await distributedSystemsCache.clearAllCacheRecords()

Example

Currently this requires the use of async-redis-shared.

Connect first somewhere in your app

import { connect } from 'distributed-systems-cache';

// from https://www.npmjs.com/package/async-redis-shared
await connect({
    db: 6,
});

Set a model up PermissionsCache.ts

import { DistributedSystemsCache } from 'distributed-systems-cache'

// the cache definition
export interface MsRolesPermissionsRole {
  permissions: string[];
}

// instantiate, declaring the cachePopulator and cacheKeyPrefix
export default new DistributedSystemsCache<MsRolesPermissionsRole>({
  cacheKeyPrefix: 'RolesPermissionsCache:',
  cacheKeyReplaceRegex: new Regex(/:/gm), // replace the default to only replace :
  cacheKeyReplaceWith: '-', // replace the default _ with -
  cachePopulator: (packageJsonName: string) => {
    // This function will be called when the cache is either not found or too old
    // This function should do something that will create a new cache object based 
    // on the cache key requests
    RabbitMQService.msRolesPermissionsRolesRequest({
      fromService: packageJsonName
    });
  },
  cachePopulatorDelete: false, // When this is true, the cache populator will not be called and a cache miss will return undefined. You should refill this cache on your own
  cacheMaxAgeMs: 1000 * 60 * 60 * 24 * 7, // 1 week life
  cachePopulatorMsGraceTime: 200,
  cachePopulatorMaxTries: 3,
  // Ensuring that we only persist what we need from the provided cache set data
  cacheSetFilter: (input: any): MsRolesPermissionsRole => {
    return input.map((input: any) => {
      return {
        permissions: input.permissions,
      };
    });
  }
});

Use it:

import PermissionsCache form '@/PermissionsCache'

// get the permissions for the role admin
await PermissionsCache.get('admin')

// or set the permissions for the role admin
await PermissionsCache.set('admin': { permissions: ['write', 'read'] })

If you set the cachePopulatorDelete to true you will have check the cache exists

import PermissionsCache form '@/PermissionsCache'

// get the permissions for the role admin
const cache = await PermissionsCache.get('admin')

if(!cache){
  // do something
} 

cacheMaxAgeMs and cachePopulatorMsGraceTime options

Both the cacheMaxAgeMs and cachePopulatorMsGraceTime have default values that can be overriden by injecting a number replacement or a string to be coverted to a millisecond timestamp with https://www.npmjs.com/package/ms.

(ms timestamps can be a pain to type out over and over hence https://www.npmjs.com/package/ms)

eg with strings:

export default new DistributedSystemsCache<MsRolesPermissionsRole>({
  cacheKeyPrefix: 'MyCache:',
  cacheMaxAgeMs: '5 days', // translates to 1000 * 60 * 60 * 24 * 5
  cachePopulatorMsGraceTime: '2m', // translates to 1000 * 60 * 2
  cachePopulator: () => {  /* some populator */ },
});

eg with numbers:

export default new DistributedSystemsCache<MsRolesPermissionsRole>({
  cacheKeyPrefix: 'MyCache:',
  cacheMaxAgeMs: 1000 * 60 * 60, // 1 hour
  cachePopulatorMsGraceTime: 1000 * 60, // 1 min
  cachePopulator: () => {  /* some populator */ },
});

Developers

Start at the unit tests: src/__tests__/DistributedSystemsCache.spec.ts

Additionally, to run the tests you need redis running on local host for now.

But you cannot publish unless the tests pass.. :)