Skip to content

Reduce response times and database load with query-level caching integrated with the ZenStack ORM.

License

Notifications You must be signed in to change notification settings

zenstack-contrib/cache

Repository files navigation

ZenStack Cache (beta)

Reduce response times and database load with query-level caching integrated with the ZenStack ORM.

NPM Version GitHub Actions Workflow Status Join the ZenStack server License: MIT

ℹ️ This project is not affiliated with or endorsed by the ZenStack team.

Features

  • 🌐 Redis Caching: Centralizes your caching to scale across different systems.
  • 🖥️ Memory Caching: Simplifies caching when scale is not a concern.
  • 🛟 Type-safe: The caching options appear in the intellisense for all read queries.

Requirements

  • ZenStack (version >= canary)
  • Node.js (version >= 20.0.0)
  • Redis (version >= 7.0.0)
    • ℹ️ Only if you intend to use the RedisCacheProvider

Installation

npm install @visualbravo/zenstack-cache
pnpm add @visualbravo/zenstack-cache
bun add @visualbravo/zenstack-cache

Sample Usage

import { schema } from './zenstack/schema'
import { ZenStackClient } from '@zenstackhq/orm'
import { defineCachePlugin } from '@visualbravo/zenstack-cache'
import { RedisCacheProvider } from '@visualbravo/zenstack-cache/providers/redis'
import { MemoryCacheProvider } from '@visualbravo/zenstack-cache/providers/memory'

const client = new ZenStackClient(schema, {
  dialect: ...,
}).$use(
  defineCachePlugin({
    // Choose only one provider.

    // 1️⃣
    provider: new RedisCacheProvider({
      url: process.env['REDIS_URL'],
    }),

    // 2️⃣
    provider: new MemoryCacheProvider(),
  }),
)

async function getPostsPublishedByUser(userId: string) {
  const publishedPosts = await client.post.findMany({
    where: {
      published: true,
      authorId: userId,
    },

    // All of these are optional.
    cache: {
      ttl: 60,
      swr: 120,
      tags: [`user:${userId}`],
    },
  })

  return publishedPosts
}

Invalidation

You can easily invalidate multiple cache entries.

// Invalidate specific tags.
await client.$cache.invalidate({
  tags: ['user:1'],
})

// Invalidate everything.
await client.$cache.invalidateAll()

Cache Status

After performing a query, you can check where the result came from.

const publishedPostsStatus = client.$cache.status // 'hit' | 'miss' | 'stale'
  • hit - a cache entry in the ttl window was found, and the database was not queried.
  • miss - a cache entry was not found, and the database was queried.
  • stale - a cache entry in the swr window was found, and the database was queried in the background to revalidate it.

Revalidation

If the result was stale, you can choose to await its revalidation.

const revalidatedPublishedPosts = await client.$cache.revalidation as Post[]

Cache Options

  • ttl reduces response times and database load by serving cached results.
  • swr reduces response times by serving cached results, but does not reduce database load because it performs a revalidation in the background after each request.

Note

The total TTL of a cache entry is equal to its ttl + swr. The ttl window comes first, followed by the swr window. You can combine the two options to best suit the needs of your application.

License

MIT

About

Reduce response times and database load with query-level caching integrated with the ZenStack ORM.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published