Is there an example for GraphQL Subscriptions? #88
-
Hello, Now I'm trying to implement subscriptions endpoints with filter method like here. This filter method does a database call via Prisma. The Prisma middleware is triggered and manipulates the database query to ensure the listener gets only a notification for events he's allowed to. The middleware uses the NestJs-CLS context to identify the user and manipulate the database query correctly. Now I'm facing the problem, that the mutation request which will publish an event overrides the NestJs-CLS context so that the Prisma middleware (which is triggered from the subscription filter method) does not have any context (here I need the context of the user, which listened to the subscription). Here is a code example: @Subscription(() => Approval, {
async filter(
this: ApprovalSubResolver,
payload: { onFileApproved: Approval },
_: undefined,
context,
): Promise<boolean> {
return true;
// try {
// return !!(await this.approvalService.findOneApproval( <-- This will trigger the middleware
// {
// id: payload.onFileApproved.id,
// },
// undefined,
// true,
// ));
// } catch (e) {
// console.error(e);
// }
},
})
async onFileApproved() {
console.log(this.clsService.get()); // Logs correct context of websocket connection
this.clsService.runWith<void>(this.clsService.get(), async () => {
console.log('INSIDE RUN WITH', this.clsService.get()); // Logs correct context of websocket connection
await this.pubSub.subscribe('onFileApproved', (res) => {
console.log(this.clsService.get('user')); // Logs the context http request (mutation) where the message is published
});
});
// this.clsService.enterWith(this.clsService.get());
return this.pubSub.asyncIterator<Approval>('onFileApproved');
} I'm confused. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
Hi, I have not used GrahQL subscriptions before, but it seems that since the middleware call is defined in the Subscription decorator, Nest calls the Are you using a middleware or an interceptor to set up the ClsContext? In case of an interceptor, you can leverage a little "workaround" I had to do to keep the CLS context the same across all parallel queries/mutations within a single request. As a result of this, if you can get ahold of the context // ExecutionContext
.getArgByIndex(2) // GqlContext (if context.getType() == 'graphql')
.__CLS_STORE__ // the ClsStore If that works, I can investigate how this can be turned into a public API and make it more stable. |
Beta Was this translation helpful? Give feedback.
If the decorator function has the same
this
context as the class, you can just use the already injectedClsService
, if not, you'll need to use the staticClsServiceManager
to retrieve the singleton ClsService instance.Then just wrap the middleware call and pass in the store:
The context will be then preserved within this callback/promise chain.
(remember that
cls.run/With
returns whatever the callback returns)