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

registerAsync Error version 0.8.4 #164

Closed
jayakusumah opened this issue Aug 25, 2019 · 14 comments
Closed

registerAsync Error version 0.8.4 #164

jayakusumah opened this issue Aug 25, 2019 · 14 comments
Assignees
Labels
bug Something isn't working

Comments

@jayakusumah
Copy link

I get an error Nest can't resolve dependencies of the controller (service, ?).... Please make sure that the argument at index [1] is available when using BullModule.registerAsync, but it works fine when using BullModule.register(). I use a shared module, and import it in another module.

nest-bull version 0.8.4

@fwoelffel
Copy link
Contributor

@jayakusumah Thanks for reporting this

I'll try to look into this issue in the next few days. It'd be great if, in the meantime, you could provide some code reproducing this error, or even submit a PR with failing tests.

@fwoelffel fwoelffel self-assigned this Aug 26, 2019
@smonv
Copy link

smonv commented Sep 22, 2019

I got the same problem: controllers in others module cannot inject queue defined in another module.

I tried exports processors, import queue defined module but no luck.

https://github.com/smonv/bull-queue-test here is code for quick setup demo the problem

Screen Shot 2019-09-22 at 13 39 43

@smonv
Copy link

smonv commented Sep 22, 2019

I found a workaround to solve this problem. Instead of directed inject queue inside controller, indirect inject queue by a service.

Create a task service inside QueueModule so naturally that service can inject queue. Export task service and let other controllers import it.

@captainjapeng
Copy link

Same issue, in my case I need to use registerAsync so that I can load my ConfigService to get redis credentials from.

@captainjapeng
Copy link

captainjapeng commented Sep 22, 2019

I think I've found the issue, when you use registerAsync it doesn't respect the name from the options and registering the ff instead of the name used in registerAsync
image

@fwoelffel fwoelffel added the bug Something isn't working label Oct 4, 2019
@fwoelffel
Copy link
Contributor

fwoelffel commented Oct 4, 2019

@smonv The queue can only be injected in the scope where BullModule has been registered. That's why you can't directly inject it in another module without wrapping it in a service that you export. This is the expected behavior.
Also I don't think this has anything to do with what @jayakusumah and @captainjapeng are reporting.

@captainjapeng might be right here. There seems to be a confusion between the name of the options and the name of the queue. I'll see what can be done to prevent this kind of error.

EDIT:
Well, @captainjapeng is actually right.

  • BullModule.register: the BullModuleOptions.name is used as the queue name and as the queue injection token also.
  • BullModule.registerAsync: the BullModuleAsyncOptions.name is used as the injection token and the BullModuleOptions.name is used as the queue name.

@adam-s
Copy link

adam-s commented Oct 18, 2019

I'm experiencing this same problem. Is there a work around at this moment?

@captainjapeng
Copy link

Yes, you'll need to create a module to reexport the BullModule

Here's an example:

import { BullModule, BullModuleOptions } from 'nest-bull'
import { Module } from '@nestjs/common'

import { ConfigModule } from 'src/config/config.module'
import { ConfigService } from 'src/config/config.service'

function redisOptions(configService: ConfigService) {
  return {
    host: configService.getString('REDIS_HOST'),
    port: configService.getInt('REDIS_PORT'),
  }
}

const BullQueueModule = BullModule.registerAsync([
  {
    name: 'email',
    imports: [ConfigModule],
    useFactory: (configService: ConfigService): BullModuleOptions => {
      return {
        name: 'email',
        options: {
          redis: redisOptions(configService),
        },
      }
    },
    inject: [ConfigService],
  },
  {
    name: 'cron',
    imports: [ConfigModule],
    useFactory: (configService: ConfigService): BullModuleOptions => {
      return {
        name: 'cron',
        options: {
          redis: redisOptions(configService),
        },
      }
    },
    inject: [ConfigService],
  },
])

@Module({
  imports: [BullQueueModule],
  exports: [BullQueueModule],
})
export class QueueModule { }

@ratio91
Copy link

ratio91 commented Oct 24, 2019

had the same issue.
really glad i found this thread here, otherwise there is no documentation yet.
It would be really great if it could be added to the readme. Thanks!

@maxymshg
Copy link

Yes, you'll need to create a module to reexport the BullModule

Here's an example:

import { BullModule, BullModuleOptions } from 'nest-bull'
import { Module } from '@nestjs/common'

import { ConfigModule } from 'src/config/config.module'
import { ConfigService } from 'src/config/config.service'

function redisOptions(configService: ConfigService) {
  return {
    host: configService.getString('REDIS_HOST'),
    port: configService.getInt('REDIS_PORT'),
  }
}

const BullQueueModule = BullModule.registerAsync([
  {
    name: 'email',
    imports: [ConfigModule],
    useFactory: (configService: ConfigService): BullModuleOptions => {
      return {
        name: 'email',
        options: {
          redis: redisOptions(configService),
        },
      }
    },
    inject: [ConfigService],
  },
  {
    name: 'cron',
    imports: [ConfigModule],
    useFactory: (configService: ConfigService): BullModuleOptions => {
      return {
        name: 'cron',
        options: {
          redis: redisOptions(configService),
        },
      }
    },
    inject: [ConfigService],
  },
])

@Module({
  imports: [BullQueueModule],
  exports: [BullQueueModule],
})
export class QueueModule { }

Hi @captainjapeng ,

Could you please share full example with usage, I tried re-export but still got same error.

@captainjapeng
Copy link

@maxymshg you'll need to import the QueueModule to the module you want to use it and then also setup your Processor on the Providers

email.module.ts

@Module({
  imports: [
    forwardRef(() => QueueModule),
  ],
  providers: [EmailService, CronProcessor],
  exports: [EmailService],
})
export class EmailModule {}

cron.processor.ts

@Injectable()
@Processor({ name: 'cron' })
export class CronProcessor {
    private readonly logger = new Logger('EmailCron')

    constructor(
        @InjectQueue('email')
        private queueService: Queue<EmailJob>,
        @InjectQueue('cron')
        private cron: Queue,
    ) {
        this.logger.log('Intializing Cron Processor')
        cron.add(null, {
            repeat: { cron: '0 0 1-2 * * *' },
            jobId: 'resume-email',
        })
    }

    @Process()
    async process(job: Job) {
        this.logger.log('Resuming Email Service')
        await this.queueService.resume()
    }
}

Here's an example of a cron job that resume the email queue every 1-2 AM UTC if ever the quota has been reached.

@maxymshg
Copy link

Got it, thanks for sharing this.

@onbetelgeuse
Copy link

onbetelgeuse commented Nov 30, 2019

Hi, I tried it, but i have the same problem. When you give a name (@processor({ name: 'foo' }), this.moduleRef.get cannot find the object. But it work very well with @processor({ name: '' }) and InjectQueue('').

@kamilmysliwiec
Copy link
Member

Let's track this here #171

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

9 participants