nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.75k stars 7.63k forks source link

Gateway constructor not called when injecting dependency and after init weird behavior #4639

Closed gempain closed 4 years ago

gempain commented 4 years ago

Bug Report

Current behavior

Take the following gateway:

@WebSocketGateway()
export class TestGateway implements OnGatewayInit {

  protected readonly logger = new Logger(TestGateway.name);

  @WebSocketServer()
  private readonly server: Server;

  constructor(
    private readonly eventsService: EventsService,
    // private readonly myService: MyService,
  ) {
    this.logger.debug(`${TestGateway.name} constructor called`);
  }

  afterInit(server: any): any {
    this.logger.debug(`${TestGateway.name} gateway init`);
  }

}

If I uncomment // private readonly myService: MyService,, the constructor is never called, the server starts and works for controllers, resolvers and pretty much everything, but I get

uncaughtException TypeError: Cannot read property 'debug' of undefined
    at TestGateway.afterInit (...src/notifications/test.gateway.ts:23:17)
    at SafeSubscriber.__tryOrUnsub (...node_modules/rxjs/src/internal/Subscriber.ts:265:10)
    at SafeSubscriber.next (...node_modules/rxjs/src/internal/Subscriber.ts:207:14)
    at Subscriber._next (...node_modules/rxjs/src/internal/Subscriber.ts:139:22)
    at Subscriber.next (...node_modules/rxjs/src/internal/Subscriber.ts:99:12)
    at ReplaySubject._subscribe (...node_modules/rxjs/src/internal/ReplaySubject.ts:80:20)
    at ReplaySubject.Observable._trySubscribe (...node_modules/rxjs/src/internal/Observable.ts:238:19)
    at ReplaySubject.Subject._trySubscribe (...node_modules/rxjs/src/internal/Subject.ts:116:33)
    at ReplaySubject.Observable.subscribe (...node_modules/rxjs/src/internal/Observable.ts:219:14)
    at WebSocketsController.subscribeInitEvent (...node_modules/@nestjs/websockets/web-sockets-controller.js:59:19)

MyService lies in another module that is imported in my NotificationsModule and depends on EventService. There are no circular dependencies. I have debugged the gateway when MyService is not commented out, and noticed that when afterInit is called, this.eventService, this.myService and this.logger are undefined, only this.server is defined.

Input Code

I could not reproduce with a minimal example, I would have to share too much prroprietary code. I could definitely share some code with you privately.

Expected behavior

I would expect the gateway to wait for all dependent services to be instantiated.

Environment

"@nestjs/common": "^7.0.8",
"@nestjs/config": "^0.4.0",
"@nestjs/core": "^7.0.8",
"@nestjs/graphql": "^7.0.15",
"@nestjs/passport": "^7.0.0",
"@nestjs/platform-express": "^7.0.8",
"@nestjs/platform-socket.io": "^7.0.8",
"@nestjs/schedule": "^0.3.1",
"@nestjs/websockets": "^7.0.8",

For Tooling issues:

jmcdo29 commented 4 years ago

To properly debug this, a minimum reproduction would be required. Are any of the services from MyService marked as REQUEST scoped? That's the only thing I could think of that could be causing an issue

kamilmysliwiec commented 4 years ago

Please provide a minimum reproduction repository.

gempain commented 4 years ago

@jmcdo29 @kamilmysliwiec trying

gempain commented 4 years ago

@jmcdo29 right on Sir ! Took me a while, but I crawled my service dependency graph and bumped on a request scoped service. I came here for this kind of hint, thanks a lot for pointing me in the right direction.

By the way, I tried compodoc to get a good picture of the dependency graph, but it's actually not that great. I think there is a place for a little utility tool to generate user friendly, navigable service dependency graphs in Nest. Just a thought :)

jmcdo29 commented 4 years ago

@gempain I had a feeling it was dealing with request scoped dependencies. Glad that helped.

As for the doc generator, I'm actually working on a tool for that called nestjs-spelunker. It's still in early development though, and needs a lot of work.

gempain commented 4 years ago

Interesting, I actually happened to find that page while searching for an alternative to compodoc. I looked at the example JSON. I think you've done most of the work, because now you just need to generate the graph. I really like the way that graphql-voyager works: you just plug in their express middleware and it gives you an amazing interactive graph you can navigate and manipulate. Seems like your API approaches that idea. So many services in a real world app that you get lost in the dependencies, and this would be great to find circular dependencies.

jmcdo29 commented 4 years ago

I plan on extending the JSON graph to an html template that is interactive so that it is easier to read through the dependency graph. Like I said, the project is still in early development, mainly I wanted a proof of concept before going further. I'll need to think about finding the scope of each dependency as well, thanks to this issue 😄. Find me on Discord if you want to discuss further