Skip to content

A Prisma client abstraction that simplifies caching.

License

Notifications You must be signed in to change notification settings

stormwarestudios/cached-prisma

 
 

Repository files navigation

Cached Prisma

A Prisma client abstraction that simplifies caching.

Status

Source Shields
Project release license lines languages
Health readthedocs github_review codacy codacy_coverage
Publishers npm npm_downloads
Repository issues issues_closed pulls pulls_closed
Activity contributors monthly_commits last_commit

Usage

To implement a cache and divert the prisma client's internals we use readonly singleton instances for the client and cache:

import { Prisma } from 'cached-prisma';

const client1 = new Prisma().client;
const client2 = new Prisma().client;

client1 === client2;
import { Prisma } from 'cached-prisma';

const cache1 = new Prisma().cache;
const cache2 = new Prisma().cache;

cache1 === cache2;

Caches must implement safe read and write methods:

export type Maybe<T> = T | null;

export interface Cache {
  read: (key: string) => Maybe<string>;
  write: (key: string, value: string) => void;
}

export interface AsyncCache {
  read: (key: string) => Promise<Maybe<string>>;
  write: (key: string, value: string) => Promise<void>;
}

To control the caching mechanism you can extend the Prisma class:

import { LruCache } from 'cached-prisma';

class CustomPrisma extends Prisma {
  cacheFactory = () => new LruCache(10);
}

The default cache is a fixed size queue that pops values as it surpasses its maximum length.

new LruCache(100);

Memcached support is provided out of the box:

import { Memcached } from 'cached-prisma';

class CustomPrisma extends Prisma {
  cacheFactory = () => new Memcached('127.0.0.1:11211', 10);
}

Note that the second parameter to the Memcached constructor is the storage lifetime of each write in seconds.

We cache the following methods which do not mutate state:

  • findUnique
  • findMany
  • findFirst
  • queryRaw
  • aggregate
  • count

After any of the following state mutating methods we flush the cache:

  • create
  • createMany
  • delete
  • deleteMany
  • executeRaw
  • update
  • updateMany
  • upsert

Profiling

If you provision a database and a memcached instance there is a crude performance profiler included as a sanity check:

tsc -p profilers
node dist/profilers/time.js
1000 prisma reads:
┌─────────┬─────────────────┬─────────────┐
│ (index) │        0        │      1      │
├─────────┼─────────────────┼─────────────┤
│    0    │ 'Without cache' │ 2.535861637 │
│    1    │ 'LruMap cache'  │ 0.080468443 │
│    2    │   'Memcached'   │ 0.032572969 │
└─────────┴─────────────────┴─────────────┘
1000 prisma read and writes:
┌─────────┬─────────────────┬──────────────┐
│ (index) │        0        │      1       │
├─────────┼─────────────────┼──────────────┤
│    0    │ 'Without cache' │ 10.244921313 │
│    1    │ 'LruMap cache'  │ 10.869037333 │
│    2    │   'Memcached'   │  9.9422369   │
└─────────┴─────────────────┴──────────────┘

Tests

To run unit tests:

grunt test

Documentation

This repository's documentation is hosted on readthedocs.

Tooling

To run linters:

grunt lint

To run formatters:

grunt format

Continuous integration

This repository uses github actions to lint and test each commit. Formatting tasks and writing/generating documentation must be done before committing new code.

Versioning

This repository adheres to semantic versioning standards. For more information on semantic versioning visit SemVer.

Bump2version is used to version and tag changes. For example:

bump2version patch

Changelog

Please read this repository's CHANGELOG for details on changes that have been made.

Contributing

Please read this repository's guidelines on CONTRIBUTING for details on our code of conduct and the process for submitting pull requests.

Contributors

Buy Me A Coffee

Remarks

Lots of love to the open source community!

Be kind

About

A Prisma client abstraction that simplifies caching.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 80.3%
  • JavaScript 19.7%