memoredis
TypeScript icon, indicating that this package has built-in type declarations

2.0.0 • Public • Published

memoredis

Redis memoization library with good Typescript generics, locking, and argument-wide bulk invalidation

Usage

yarn add memoredis

Initialization

import memoredis from 'memoredis';

// pass options as they would directly to redis.createClient
const memoizer = memoredis({ clientOpts: 'redis://' });

// or pass in an existing client
const client = redis.createClient();
const memoizer = memoredis({ client });

Basic Usage

const expensiveDatabaseLookup = async ({ authorId, genre }) => {
  // some expensive database lookup
  return { countOfBooks: n };
};

const countOfBooksPublishedByAuthorInGenre = memoizer.memoize(
  expensiveDatabaseLookup,
  { key: 'genre-author-count', ttl: 60 * 1000 }
);

await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // goes to the database
await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // served from redis!

Basic Invalidation

await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // goes to the database
await memoizer.invalidate('genre-author-count', {
  authorId: 4,
  genre: 'fiction'
});
await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // goes to the database

Bulk Partial Invalidation

await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // goes to the database
await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'biology' }); // goes to the database
await memoizer.invalidate('genre-author-count', {
  authorId: 4
});
await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'fiction' }); // goes to the database
await countOfBooksPublishedByAuthorInGenre({ authorId: 4, genre: 'biology' }); // goes to the database

Prefixes

// optionally include a prefix for namespacing caches
const libraryA = memoredis({ prefix: 'a' });
const libraryB = memoredis({ prefix: 'b' });

const expensiveDatabaseLookup = async ({ authorId, genre }) => {
  // some expensive database lookup
  console.log('Finished looking up');
  return { countOfBooks: n };
};

const countOfBooksPublishedByAuthorInGenreInLibraryA = libraryA.memoize(
  expensiveDatabaseLookup,
  { key: 'genre-author-count', ttl: 60 * 1000 }
);

const countOfBooksPublishedByAuthorInGenreInLibraryB = libraryA.memoize(
  expensiveDatabaseLookup,
  { key: 'genre-author-count', ttl: 60 * 1000 }
);

await countOfBooksPublishedByAuthorInGenreInLibraryA({
  authorId: 4,
  genre: 'fiction'
}); // goes to the database

await countOfBooksPublishedByAuthorInGenreInLibraryB({
  authorId: 4,
  genre: 'fiction'
}); // goes to the database

Locking

This library uses redis-lock under the hood to prevent two calls to the same function at the same time, even when the cache is cold.

const expensiveDatabaseLookup = async ({ authorId, genre }) => {
  // some expensive database lookup
  console.log('Finished looking up');
  return { countOfBooks: n };
};

const countOfBooksPublishedByAuthorInGenre = memoizer.memoize(
  expensiveDatabaseLookup,
  { key: 'genre-author-count', ttl: 60 * 1000 }
);

const args = { authorId: 4, genre: 'fiction' };
await Promise.all([
  countOfBooksPublishedByAuthorInGenre(args),
  countOfBooksPublishedByAuthorInGenre(args)
]);
// only logs 'Finished looking up' once

Readme

Keywords

none

Package Sidebar

Install

npm i memoredis

Weekly Downloads

24

Version

2.0.0

License

MIT

Unpacked Size

52.8 kB

Total Files

22

Last publish

Collaborators

  • ikehz
  • derrick-pr
  • quantumaashish
  • ben-pr-p
  • bchrobot
  • mgoldfield
  • priyachatwani