yxx4c / prisma-extension-redis

Extensive Prisma extension designed for efficient caching and cache invalidation using Redis and Dragonfly Databases
https://npmjs.com/package/prisma-extension-redis
MIT License
34 stars 2 forks source link

Prisma Extension Redis

NPM License NPM Version NPM Downloads

prisma-extension-redis provides seamless integration with Prisma and Redis/Dragonfly databases, offering efficient caching mechanisms to improve data access times and overall application performance.

🚀 If prisma-extension-redis proves helpful, consider giving it a star! ⭐ Star Me!


Installation

You can install prisma-extension-redis using your preferred package manager:

Using npm:

npm install prisma-extension-redis

Using yarn:

yarn add prisma-extension-redis

Using pnpm:

pnpm add prisma-extension-redis

Using bun:

bun add prisma-extension-redis

Setup and Configuration

Step 1: Initialize Required Clients

Before setting up caching, initialize your Prisma client, Redis client config, and logger:

import pino from 'pino';
import { PrismaClient } from '@prisma/client';
import { Redis } from 'iovalkey';
import {SuperJSON} from 'superjson';

import {
  CacheCase,
  PrismaExtensionRedis,
  type AutoCacheConfig,
  type CacheConfig,
} from 'prisma-extension-redis';

// Prisma Client
const prisma = new PrismaClient();

// Redis client config
const client = {
  host: process.env.REDIS_HOST_NAME, // Redis host
  port: process.env.REDIS_PORT,      // Redis port
};

// Create a logger using pino (optional)
const logger = pino();

Step 2: Configure Auto-Cache Settings

auto settings enable automated caching for read operations with flexible customization.

Example Auto-Cache Configuration

const auto: AutoCacheConfig = {
  excludedModels: ['Post'], // Models excluded from auto-caching
  excludedOperations: ['findFirst', 'count', 'findMany'], // Operations excluded from auto-caching
  models: [
    {
      model: 'User', // Model-specific auto-cache settings
      excludedOperations: ['count'], // Operations to exclude
      ttl: 10,  // Time-to-live (TTL) for cache in seconds
      stale: 5, // Stale time in seconds
    },
  ],
  ttl: 30, // Default TTL for cache in seconds
};

Note:

  1. Excluded operations and models will not benefit from auto-caching.
  2. Use ttl and stale values to define caching duration.

Step 3: Configure Cache Client

The cache client configuration is necessary to enable caching, either automatically or manually.

Example Cache Configuration

const config: CacheConfig = {
 ttl: 60, // Default Time-to-live for caching in seconds
  stale: 30, // Default Stale time after ttl in seconds
  auto, // Auto-caching options (configured above)
  logger, // Logger for cache events (configured above)
  transformer: {
    // Custom serialize and deserialize function for additional functionality if required
    deserialize: data => SuperJSON.parse(data),
    serialize: data => SuperJSON.stringify(data),
  },
  type: 'JSON', // Redis cache type, whether you prefer the data to be stored as JSON or STRING in Redis
  cacheKey: { // Inbuilt cache key configuration
    case: CacheCase.SNAKE_CASE, // Select a cache case conversion option for generated keys from CacheCase
    delimiter: '*', // Delimiter for keys (default value: ':')
    prefix: 'awesomeness', // Cache key prefix (default value: 'prisma')
  },
};

Note: Cache case conversion strips all non alpha numeric characters

Step 4: Extend Prisma Client

Now, extend your Prisma client with caching capabilities using prisma-extension-redis:

const extendedPrisma = prisma.$extends(
  PrismaExtensionRedis({ config, client })
);

Usage Guide

Automatic Caching

With auto-caching, read operations (e.g., findUnique, findMany) are cached automatically based on the defined configuration.

Basic Example:

// Cached automatically based on auto-cache settings
extendedPrisma.user.findUnique({
  where: { id: userId },
});

// Manually enable cache for a query
extendedPrisma.user.findUnique({
  where: { id: userId },
  cache: true, // Toggle caching on
});

// Disable cache for specific query
extendedPrisma.user.findFirst({
  where: { id: userId },
  cache: false, // Toggle caching off
});

Note:

  1. If auto-cache is set to false and cache is set to true for the query, the default values from the cache configuration will be applied.
  2. If cache is set to false and auto-cache is set to true, the query will not be cached.

Custom Caching with getKey

For greater control over caching, generate custom cache keys and TTL settings.

Example with Custom Cache Key:

const customKey = extendedPrisma.getKey({ params: [{ prisma: 'User' }, { id: userId }] });

extendedPrisma.user.findUnique({
  where: { id: userId },
  cache: { ttl: 5, key: customKey }, // Custom TTL and cache key
});

Cache Invalidation

Cache invalidation ensures data consistency by removing or updating cached data when changes occur in the database.

Example of Cache Invalidation:

// Invalidate cache when updating a user's information
extendedPrisma.user.update({
  where: { id: userId },
  data: { username: newUsername },
  uncache: {
    uncacheKeys: [
      extendedPrisma.getKey({ params: [{ prisma: 'User' }, { id: userId }] }), // Specific key to invalidate
      getKeyPattern({ params: [{ prisma: '*' }, { id: userId }]}), // Pattern for wildcard invalidation
      getKeyPattern({ params: [{ prisma: 'Post' }, { id: userId }, { glob: '*' }]}), // Use glob for more complex patterns
    ],
    hasPattern: true, // Use pattern matching for invalidation
  },
});

Explanation of Cache Invalidation:


Key Concepts Explained

1. Time-to-Live (TTL)

2. Stale Time

3. Cache Key Management


Key Features


Prerequisites

Dependencies


Final Thoughts

prisma-extension-redis offers an efficient and powerful way to manage caching in Prisma-based applications. By leveraging both automatic and custom caching, you can optimize your application's performance while maintaining data consistency.

Upgrade to prisma-extension-redis for an optimized caching strategy and contribute to its growth by starring the repository if you find it useful!