Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extraProviders to registerQueueAsync #495

Open
1valdis opened this issue Jul 17, 2020 · 4 comments
Open

Add extraProviders to registerQueueAsync #495

1valdis opened this issue Jul 17, 2020 · 4 comments
Labels
enhancement New feature or request

Comments

@1valdis
Copy link

1valdis commented Jul 17, 2020

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Currently I can't inject extra providers while using BullModule.registerQueueAsync, and thus I can't effectively use useFactory because I cannot pass any options there.

Expected behavior

I use HttpModule where there is a key extraProviders and I can pass providers my factory needs, and I'd like to be able to do a similar thing with BullModule:

HttpModule.registerAsync({
  useFactory: (options: MyOptions) => {
    return {
      baseURL: options.baseURL,
      timeout: 3000,
    }
  },
  inject: [MyOptionsSymbol],
  extraProviders: [
    MyOptionsProvider,
  ],
  imports: options.imports
})

Minimal reproduction of the problem with instructions

export interface ModuleOptions {
  redisConnectionOptions: {}
}

export interface AsyncModuleOptions {
  inject?: any[],
  imports?: any[],
  useFactory: (...args: any[]) => Promise<ModuleOptions> | ModuleOptions,
}

export const ModuleOptionsSymbol = Symbol('ModuleOptions interface symbol for Nest DI')

export class SomeModule {
  static registerAsync(options: AsyncModuleOptions): DynamicModule {
    return {
      module: SomeModule,
      imports: [
        BullModule.registerQueueAsync({
          useFactory: (options: ModuleOptions) => {
            return options.redisConnectionOptions;
          },
          // right there, how do I provide "module options" factory (options.useFactory)?
          // in HttpModule it would be:
          // extraProviders: {
          //   provide: ModuleOptionsSymbol,
          //   useFactory: options.useFactory,
          //   inject: options.inject,
          // }
          // but as I can't pass the extra provider, I effectively can't inject it to my factory
          // so Nest says it "can't resolve dependencies"
          inject: [ModuleOptionsSymbol],
        }),
        ...options.imports ?? []
      ],
      providers: [
        {
          provide: ModuleOptionsSymbol,
          useFactory: options.useFactory,
          inject: options.inject,
        }
      ],
      exports: []
    }
  }
}

I will also appreciate suggestions of alternative approach, since I can't really move forward with my project now.

What is the motivation / use case for changing the behavior?

It already works in HttpModule this way so I'd like to see this working this way in BullModule also.

Environment


Nest version: 7.3.2
`@nestjs/bull` version: 0.1.2
@kamilmysliwiec
Copy link
Member

Would you like to create a PR for this issue?

@1valdis
Copy link
Author

1valdis commented Jul 17, 2020

@kamilmysliwiec I'm afraid it'll take too much time to look up contributing guides, learn the code and write the tests (I haven't written tests before so I will also have to learn how to do it). If HttpModule and BullModule have similar codebases, I could have a look, but I think there are people who would be able to implement this many times faster.

@kamilmysliwiec kamilmysliwiec added the enhancement New feature or request label Jul 24, 2020
@micalevisk
Copy link
Member

an workaround for this (I guess):

export class SomeModule {
  static registerAsync(options: AsyncModuleOptions): DynamicModule {
    return {
      module: SomeModule,
      imports: [
        BullModule.registerQueueAsync({
          // ====================================== //
          imports: [
            {
              module: class {},
              providers: [
                provide: ModuleOptionsSymbol,
                useFactory: options.useFactory,
                inject: options.inject,
              ],
              exports: [ModuleOptionsSymbol]
            }
          ],
          // ====================================== //
          useFactory: (options: ModuleOptions) => {
            return options.redisConnectionOptions;
          },
          inject: [ModuleOptionsSymbol],
        }),
        ...options.imports ?? []
      ],
      providers: [
        {
          provide: ModuleOptionsSymbol,
          useFactory: options.useFactory,
          inject: options.inject,
        }
      ],
      exports: []
    }
  }
}

@micalevisk
Copy link
Member

micalevisk commented Oct 12, 2021

btw I just prototyped the implementation for this feature here and it worked. If you want to give it a try, just install it doing
npm i github:micalevisk/bull#build-of-feat-issue-459

@1valdis, Feel free to improve that code and add tests to open a PR adding this here :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants