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 ClsStoreIf 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
thiscontext as the class, you can just use the already injectedClsService, if not, you'll need to use the staticClsServiceManagerto 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/Withreturns whatever the callback returns)