#Ensure a Module is `always` the first to be loaded in the dependency tree

14 messages · Page 1 of 1 (latest)

warped bloom
#

👋 Howdy! Is there a way to ?

@Module({
  imports: [OpenTelemetryModuleConfig],
})
export class AppModule {}

I've had a case in the past that when Multer (express) was enabled, this module would be loaded after some other modules. But for this library to work, it's essential that it's always the first . Any ideas?

magic marsh
#

What are the reasons it needs to be first? That sounds like the problem. Not making it first.

twin jolt
#

Opentelemetry needs to be loaded before everything else, not just nestjs modules. It should be imported as the first thing in the applications entrypoint (that is, the first thing in your main.ts.

fleet slate
#

@warped bloom Does OpenTelemetryModuleConfig will expose any provider that others modules may use?

gritty ginkgo
#

There's really not a way to programatically ensure a module is first loaded. The closest you could probably do is make a "dynamic" OpenTelemetryMoudle that takes in the AppModule and returns a new module metadata with the OpenTelemetryModuleConfig as the first module in the imports. My CommandFactory kind of does something like this if you want to see an example

#

Oh, or you could wrap the NestFactory in an OpenTelemetryNestFactory or whatever you want to call it (again, the CommandFactory is kind of an example of this)

gritty ginkgo
# fleet slate like this?

Similar, but would also import the OpenTelemetryModuleConifig that Ivan had mentioned needing, so it would be imports: [OpenTelemetryModuleConfig, Module]

warped bloom
#

For some reason, I didn't get notifications for this thread, sorry.

I think you all are on the same page about the "problem" but enforcing external inclusion is how I already solved the problem, but still feels that's a bad developer experience for the users of a package I've created in the past.

I'm aware this is not ideal, but there's no concept of preHook in NestJS where I can execute a block of code before the application starts by configuring that block in the global module itself ;/

I will try to meddle with this example above, but not sure if it will enforce guarantees that it will always be the first one

warped bloom
#

@gritty ginkgo how would you go about supporting forRootAsync ?

static forRootAsync(options: OpenTelemetryModuleAsyncOptions): DynamicModule {
    return {
      module: OpenTelemetryModule,
      imports: [OpenTelemetryCoreModule.forRootAsync(options)],
    };
  }
gritty ginkgo
warped bloom
#

The behavior I wish was available is the following (probably a stretch):

  • Module 1 - sync
  • Module 2 - async
  • OtelOrSimilarModule - async or sync (forRoot vs forRootAsync)
    - Implements method contract:
    - preHookFn() -> otel setup happens here.

Dependency Injection Behavior:

  • Evaluate modules defined in App and looks for preHookFn in order as they appear.
  • Calls that function before anything.
  • Proceeds with conventional logic

Because OpenTelemetry literally does monkeypatching all over the place (including NestJS Core), It's ideal that it's the first thing to be loaded when an "App" starts.

#

I don't think there's another way around what I did so far, by extracting the opentelemetry file and enforcing it to be imported as the first import in main.ts

twin jolt
# warped bloom The behavior `I wish` was available is the following (probably a stretch): * Mo...

Because OpenTelemetry literally does monkeypatching all over the place (including NestJS Core), It's ideal that it's the first thing to be loaded when an "App" starts
Opentelemetry also patches the require/import of NodeJS itself, so it can then hook into imports of the other Node modules it patches. Therefore it's integral that it loads before the Node modules it needs to patch. This goes beyond Nest modules. If you made it load as the first Nest module, it would still load after all Node modules have been loaded - which is also already too late.