Closed adrianlocurciohotovo closed 5 months ago
Hi, I'll investigate this further when I get to a computer, but there shouldn't be a problem with passing a prisma client created by a factory.
What I see as a problem is the line here:
const webhookHandle = await prisma.webhookHandle.findFirst(args);
Here, prisma
is always referring to the original instance and not to the proxied transaction instance, since you injected the non-proxied PrismaClient.
You might try using this
instead of prisma
, although I'm not sure if that won't create a recursive call (since you overwrote a similarly-named method)
Although fetching the cache in the query extension instead the model extension might also work.
Passing in the transaction host instead of PrismaClient woild probably also not work due to a circular dependency.
@Papooch Hey, thanks for answering!, effectively thanks to your answer I have realized I was using prisma extension in the wrong way. I have changed my approach and I have created new model method called findFirstUsingCache
instead of overwriting built-in findFirst
.
And I have also used Prisma.getExtensionContext(this)
as docs say here https://www.prisma.io/docs/orm/prisma-client/client-extensions/model#call-a-custom-method-from-another-custom-method
That method returns me a valid prisma model and this prisma model is the one that is modified by @nestjs-cls/transactional-adapter-prisma
plugin so now when I execute findFirst
from extension context, it is executed within Transaction context!.
Thanks so much for helping me!, just in case I leave you the modified working code here:
export const createWebhookHandleExtension = (cache: Cache, logger: Logger) => {
return Prisma.defineExtension({
name: 'webhookHandle',
model: {
webhookHandle: {
async findFirstUsingCache<T>(
this: T,
args: Prisma.WebhookHandleFindFirstArgs,
): Promise<ReturnType<PrismaClient['webhookHandle']['findFirst']>> {
const cacheKey = getCacheKey(args);
if (cacheKey) {
const cachedResult = await cache.get<WebhookHandle>(cacheKey);
if (cachedResult) {
logger.verbose('WebhookHandle cache: HIT');
return cachedResult;
} else {
logger.verbose('WebhookHandle cache: MISS');
}
}
// Extension context operations like `findFirst` are executed within Transaction object if exists.
const extensionContext = (Prisma.getExtensionContext(this) as any);
const webhookHandle = await extensionContext.findFirst(args);
if (cacheKey && webhookHandle) {
await cache.set(cacheKey, webhookHandle);
}
return webhookHandle;
},
},
},
query: {
webhookHandle: {
async update({ args, query }) {
const webhookHandle = await query(args);
if (args.where.id) {
await cache.del(getCacheKey(args)!);
await invalidateCustomFunctionWebhookHandleCache(cache, args.where.id);
}
return webhookHandle;
},
async delete({ args, query }) {
const webhookHandle = await query(args);
if (args.where.id) {
await cache.del(getCacheKey(args)!);
await invalidateCustomFunctionWebhookHandleCache(cache, args.where.id);
}
return webhookHandle;
},
},
},
});
};
Definitively everything is working fine with providers that make use of useFactory
method!.
Hi, thanks for this amazing library!.
I'm facing an issue that I hope you can help me to solve.
I have following prisma module that is using
useFactory
method to be able to use other dependencies likeCache
andConfigService
in order to proper build extended prisma client based on my needs.src/prisma-module/prisma.module.ts
getPrismaClient
is just a function that builds custom prisma client and returns it.src/prisma-module/prisma.client.ts
And this is the file where I export
PrismaService
class that is being used as the provider token insrc/prisma-module/prisma.module.ts
src/prisma-module/prisma.service.ts
The main purpose of this custom prisma client that I built is caching results in redis. This is an example of how
createWebhookHandleExtension
used insidegetPrismaClient
works:Ass you can see I override
findFirst
(and this is very important) method and apply cache logic into it. Based on this I'm having an issue when I start a transaction from transactionHost object in the normal way as docs explain by ruinning:Everything is working fine until I use the
findFirst
method fromwebhookHandle
model, I have realized that callawait prisma.webhookHandle.findFirst(args);
that is being used inside extension is not being executed in the context of a transaction.This is how I register the ClsModule in my
app.module.ts
as docs say here https://papooch.github.io/nestjs-cls/plugins/available-plugins/transactional/prisma-adapter#custom-client-typeI'm suspecting the transactional adapter does not currently support passing providers that are using
useFactory
method. Am I right ? Or there is something I'm missing here ?Thanks