Skip to content

Instantly share code, notes, and snippets.

@daniellwdb
Last active June 14, 2022 17:25
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save daniellwdb/0c2dba8b5807393ac9bf1f48429c1f06 to your computer and use it in GitHub Desktop.
Save daniellwdb/0c2dba8b5807393ac9bf1f48429c1f06 to your computer and use it in GitHub Desktop.
Prisma cache middleware
import type { Prisma } from "@prisma/client"
import { redis } from "../redis"
type CacheMiddlewareOptions = {
model: Prisma.ModelName
action: Prisma.PrismaAction
keys?: string[]
defaultValues?: Record<string, unknown>
ttlInSeconds: number
}
export const cacheMiddleware = ({
model,
action,
keys,
defaultValues,
ttlInSeconds,
}: CacheMiddlewareOptions): Prisma.Middleware => async (params, next) => {
if (params.model !== model || action !== params.action) {
return next(params)
}
// Return early if caching should only happen when specific keys are selected
// but the current query does not include all of them
if (keys) {
const selectedKeys = Object.keys(params.args.select)
const match = selectedKeys.every(key => keys.includes(key))
if (!match) {
return next(params)
}
}
let result
const key = `${params.model}:${params.action}:${JSON.stringify(params.args)}`
await redis.del(key)
result = await redis.hgetall(key)
if (!Object.keys(result).length) {
try {
result = await next(params)
} catch (err) {
if (err.name !== "NotFoundError") {
throw err
}
if (!defaultValues) {
throw new Error(
`${err.message}. Either handle the case of undefined by removing \`rejectOnNotFound\` or pass in \`defaultValues\`.`
)
}
result = defaultValues
}
await redis.hmset(key, result)
if (ttlInSeconds) {
redis.expire(key, ttlInSeconds)
}
}
return result
}
prisma.$use(
cacheMiddleware({
model: "Guild",
action: "findUnique",
defaultValues: { language: "nl", prefix: "!a" },
ttlInSeconds: 10,
})
)
const config = await prisma.guild.findUnique({
where: {
id: guild.id,
},
select: {
prefix: true,
language: true,
},
rejectOnNotFound: true,
})
config.prefix // Not null, errors if defaultValues is not present
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment