nestjs / graphql

GraphQL (TypeScript) module for Nest framework (node.js) 🍷
https://docs.nestjs.com/graphql/quick-start
MIT License
1.45k stars 392 forks source link

Durable providers does not work with Graphql resolvers #2452

Closed KamalAman closed 1 year ago

KamalAman commented 1 year ago

Is there an existing issue for this?

Current behavior

When trying to use a durable provider, the ContextIdFactory never gets call when using a Graphql resolver

Minimum reproduction code

https://stackblitz.com/edit/nestjs-typescript-starter-wrfmxw?file=src%2Fdurable.module.ts,package.json,src%2Fcontext-id-strategy.ts,src%2Fmain.ts

Steps to reproduce

Using a basic module here, the REST endpoint works properly with the durable service however the Graphql Resolver never causes the ContextIdFactory documented here to executes, thus always creates a new service each call. Durable providers are documented here: durable-providers

import { Controller, Get } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Field, ObjectType, Resolver, Query } from '@nestjs/graphql';

@Injectable({ scope: Scope.REQUEST, durable: true })
export class DurableService {
  public instanceCounter = 0;

  constructor(@Inject(REQUEST) public readonly requestPayload: unknown) {}

  greeting() {
    ++this.instanceCounter;
    return `Hello world! Counter: ${this.instanceCounter}`;
  }
}

@Controller('durable')
export class DurableController {
  constructor(private readonly durableService: DurableService) {}

  @Get()
  greeting(): string {
    return this.durableService.greeting();
  }

  @Get('echo')
  echo() {
    return this.durableService.requestPayload;
  }
}

@ObjectType('Durable')
class DurableDto {
    @Field(() => String, { nullable: true })
    id: string
}

@Resolver(() => DurableDto)
export class DurableResolver {
  constructor(private readonly service: DurableService) {}

  @Query(() => DurableDto)
  async durable() {
    return {
        id: this.service.greeting()
    }
  }
}

@Module({
  controllers: [DurableController],
  providers: [DurableService, DurableResolver],
})
export class DurableModule {}

Expected behavior

instanceCounter should increment each time the durable resolver is called, however it stays at 1 because the service is recreated each request. The controller works just fine incrementing the counter.

Package version

10.1.3

Graphql version

graphql: 15.6.1

NestJS version

9.1.4

Node.js version

16.15.0

In which operating systems have you tested?

Other

No response

thiagomini commented 1 year ago

I am working on that. Hopefully, this will be a quick fix.

KamalAman commented 1 year ago

Caution for those out there, don't use Durable resolvers if you are also using DataLoader since DataLoaders must be Request scoped