1.14.0 • Published 1 year ago

distributed-systems-cache v1.14.0

Weekly downloads
-
License
-
Repository
github
Last release
1 year ago

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.. :)

1.14.0

1 year ago

1.12.0

2 years ago

1.11.0

2 years ago

1.9.1

2 years ago

1.9.0

2 years ago

1.10.0

2 years ago

1.8.0

3 years ago

1.7.0

3 years ago

1.6.0

3 years ago

1.5.0

3 years ago

1.4.0

3 years ago

1.3.0

3 years ago

1.2.0

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago