2.0.0 • Published 2 years ago

memoredis v2.0.0

Weekly downloads
28
License
MIT
Repository
github
Last release
2 years ago

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
2.0.0

2 years ago

1.1.1

3 years ago

1.1.0

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.2

4 years ago

1.0.3

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago