From fd47e402056a357c393142fc2b99eb2aba342e55 Mon Sep 17 00:00:00 2001 From: PodkopovP <113348735+PodkopovP@users.noreply.github.com> Date: Mon, 23 Jun 2025 08:23:39 +0100 Subject: [PATCH 1/2] refactor: streamline cache uncache logic and add direct uncache method to README --- README.md | 18 ++++++++++++++++++ src/cacheUncache.ts | 33 +++++++++++++++++++-------------- src/prismaExtensionRedis.ts | 5 ++++- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0b0a0be..b42b79c 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,24 @@ extendedPrisma.user.update({ }); ``` +### Direct Cache Invalidation + +Cache invalidation can also be performed directly using the `uncache` method, allowing you to uncache without needing to perform a database operation. + +**Example of Direct Cache Invalidation:** + +```javascript +// Invalidate cache when updating a user's information +extendedPrisma.uncache({ + uncacheKeys: [ + extendedPrisma.getKey({ params: [{ prisma: 'User' }, { id: userId }] }), // Specific key to invalidate + extendedPrisma.getKeyPattern({ params: [{ prisma: '*' }, { id: userId }]}), // Pattern for wildcard invalidation + extendedPrisma.getKeyPattern({ params: [{ prisma: 'Post' }, { id: userId }, { glob: '*' }]}), // Use glob for more complex patterns + ], + hasPattern: true, // Use pattern matching for invalidation +}); +``` + **Explanation of Cache Invalidation:** - **`uncacheKeys`**: Specifies the keys or patterns to be invalidated. diff --git a/src/cacheUncache.ts b/src/cacheUncache.ts index 8900f30..194bfde 100644 --- a/src/cacheUncache.ts +++ b/src/cacheUncache.ts @@ -1,5 +1,6 @@ import micromatch from 'micromatch'; import {coalesceAsync} from 'promise-coalesce'; +import {type Redis} from 'iovalkey' import type {Operation} from '@prisma/client/runtime/library'; @@ -212,6 +213,23 @@ export const customCacheAction = async ({ }); }; +export const uncacheAction = async (redis: Redis, {uncacheKeys, hasPattern}: UncacheOptions) => { + if (hasPattern) { + const patternKeys = micromatch(uncacheKeys, ['*\\**', '*\\?*']); + const plainKeys = micromatch(uncacheKeys, ['*', '!*\\**', '!*\\?*']); + + const unlinkPromises = [ + ...unlinkPatterns({ + redis, + patterns: patternKeys, + }), + ...(plainKeys.length ? [redis.unlink(plainKeys)] : []), + ]; + + await Promise.all(unlinkPromises); + } else await redis.unlink(uncacheKeys); +} + export const customUncacheAction = async ({ redis, options: {args, query}, @@ -219,20 +237,7 @@ export const customUncacheAction = async ({ }: ActionParams) => { const {uncacheKeys, hasPattern} = args.uncache as unknown as UncacheOptions; - if (hasPattern) { - const patternKeys = micromatch(uncacheKeys, ['*\\**', '*\\?*']); - const plainKeys = micromatch(uncacheKeys, ['*', '!*\\**', '!*\\?*']); - - const unlinkPromises = [ - ...unlinkPatterns({ - redis, - patterns: patternKeys, - }), - ...(plainKeys.length ? [redis.unlink(plainKeys)] : []), - ]; - - await Promise.all(unlinkPromises); - } else await redis.unlink(uncacheKeys); + await uncacheAction(redis, {uncacheKeys, hasPattern}); return {result: await query({...args, uncache: undefined})}; }; diff --git a/src/prismaExtensionRedis.ts b/src/prismaExtensionRedis.ts index 9ac6829..caf5baa 100644 --- a/src/prismaExtensionRedis.ts +++ b/src/prismaExtensionRedis.ts @@ -8,10 +8,11 @@ import { isAutoCacheEnabled, isCustomCacheEnabled, isCustomUncacheEnabled, + uncacheAction } from './cacheUncache'; import {getAutoKeyGen, getKeyGen, getKeyPatternGen} from './cacheKey'; -import type {ExtendedModel, PrismaExtensionRedisOptions} from './types'; +import type {ExtendedModel, PrismaExtensionRedisOptions, UncacheOptions} from './types'; export const PrismaExtensionRedis = (options: PrismaExtensionRedisOptions) => { const { @@ -27,6 +28,7 @@ export const PrismaExtensionRedis = (options: PrismaExtensionRedisOptions) => { const getKey = getKeyGen(delimiter, cacheCase, prefix); const getAutoKey = getAutoKeyGen(getKey); const getKeyPattern = getKeyPatternGen(delimiter, cacheCase, prefix); + const uncache = (args: UncacheOptions) => uncacheAction(redis, args) return Prisma.defineExtension({ name: 'prisma-extension-redis', @@ -35,6 +37,7 @@ export const PrismaExtensionRedis = (options: PrismaExtensionRedisOptions) => { getKey, getKeyPattern, getAutoKey, + uncache }, model: { $allModels: {} as ExtendedModel, From f1543e256013d03b5426f7b6619d2b54b5ce0470 Mon Sep 17 00:00:00 2001 From: PodkopovP <113348735+PodkopovP@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:02:24 +0100 Subject: [PATCH 2/2] Fix returning wrapper result in auto query --- src/prismaExtensionRedis.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/prismaExtensionRedis.ts b/src/prismaExtensionRedis.ts index caf5baa..3f471e9 100644 --- a/src/prismaExtensionRedis.ts +++ b/src/prismaExtensionRedis.ts @@ -71,9 +71,7 @@ export const PrismaExtensionRedis = (options: PrismaExtensionRedisOptions) => { config, }); - return { - result: await query({...args, cache: undefined}), - }; + return await query({...args, cache: undefined}) }, }, },