Prisma Adapter makes a lot of SQL queries to the database. Is it possible to cache it? #11134
-
Hello, is it possible to use This is what my Prisma log looks like. I am caching the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
I have a solution in mind. I have defined a @balazsorban44 @ndom91 is this something the project can make use of? I will create a PR. Sample Usage (src/auth.ts): import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client/edge"
import NodeCacheAdapter from "./node-cache-adapter"
const prisma = new PrismaClient();
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: NodeCacheAdapter(PrismaAdapter(prisma), { ttl: 60 }),
providers: [
...
],
} Sample Implementation (src/node-cache-adapter.ts). import type {
Adapter,
AdapterUser,
AdapterSession
} from "@auth/core/adapters"
import NodeCache from 'node-cache'
export default function NodeCacheAdapter(
dbAdapter: Adapter,
options?: { ttl?: number },
): Adapter {
const adapter = dbAdapter as Adapter
const stdTTL = options?.ttl || 1
const cache = new NodeCache({ stdTTL: stdTTL, checkperiod: stdTTL + 2 })
const getSessionAndUserCacheKey = (sessionToken: string) => `nca:getSessionAndUser:${sessionToken}`
return {
createUser: (data) => {
return adapter.createUser!(data)
},
getUser: (id) => {
return adapter.getUser!(id)
},
getUserByEmail: (email) => {
return adapter.getUserByEmail!(email)
},
async getUserByAccount(provider_providerAccountId) {
return adapter.getUserByAccount!(provider_providerAccountId)
},
updateUser: (data) => {
return adapter.updateUser!(data)
},
deleteUser: (id) => {
return adapter.deleteUser!(id)
},
linkAccount: (data) => {
return adapter.linkAccount!(data)
},
unlinkAccount: (provider_providerAccountId) => {
return adapter.unlinkAccount!(provider_providerAccountId)
},
async getSessionAndUser(sessionToken) {
const cacheKey = getSessionAndUserCacheKey(sessionToken)
const cached : {user: AdapterUser, session: AdapterSession} | undefined = cache.get(cacheKey)
let userAndSession: {user: AdapterUser, session: AdapterSession} | null = null;
if (cached === undefined) {
const toCache = await adapter.getSessionAndUser!(sessionToken)
if (toCache) {
cache.set(cacheKey, toCache)
}
userAndSession = toCache
} else {
userAndSession = cached
}
if (!userAndSession) return null
const { user, session } = userAndSession
return { user, session } as { user: AdapterUser; session: AdapterSession }
},
createSession: (data) => {
return adapter.createSession!(data)
},
updateSession: (data) => {
const cacheKey = getSessionAndUserCacheKey(data.sessionToken)
const result = adapter.updateSession!(data);
if (result instanceof Promise) {
result.then(() => {
cache.del(cacheKey)
})
} else {
cache.del(cacheKey)
}
return result;
},
deleteSession: (sessionToken) => {
const cacheKey = getSessionAndUserCacheKey(sessionToken)
const result = adapter.deleteSession!(sessionToken)
if (result instanceof Promise) {
result.then(() => {
cache.del(cacheKey)
})
} else {
cache.del(cacheKey)
}
return result;
},
async createVerificationToken(data) {
return adapter.createVerificationToken!(data)
},
async useVerificationToken(identifier_token) {
return adapter.useVerificationToken!(identifier_token)
},
async getAccount(providerAccountId, provider) {
return adapter.getAccount!(providerAccountId, provider)
},
async createAuthenticator(authenticator) {
return adapter.createAuthenticator!(authenticator)
},
async getAuthenticator(credentialID) {
return adapter.getAuthenticator!(credentialID)
},
async listAuthenticatorsByUserId(userId) {
return adapter.listAuthenticatorsByUserId!(userId)
},
async updateAuthenticatorCounter(credentialID, counter) {
return adapter.updateAuthenticatorCounter!(credentialID, counter)
},
}
} |
Beta Was this translation helpful? Give feedback.
I have a solution in mind. I have defined a
NodeCacheAdapater
, and I wrappedPrismaAdapter
with it. It works well for the repeated calls togetSessionAndUser
, and I am planning to run this in production.@balazsorban44 @ndom91 is this something the project can make use of? I will create a PR.
Sample Usage (src/auth.ts):