nestjs / bull

Bull module for Nest framework (node.js) :cow:
https://nestjs.com
MIT License
609 stars 102 forks source link

registerAsync Error version 0.8.4 #164

Closed jayakusumah closed 4 years ago

jayakusumah commented 5 years ago

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 commented 5 years ago

@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.

smonv commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

captainjapeng commented 5 years ago

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 commented 5 years ago

@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.

adam-s commented 5 years ago

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

captainjapeng commented 5 years ago

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 commented 5 years ago

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 commented 4 years ago

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 commented 4 years ago

@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 commented 4 years ago

Got it, thanks for sharing this.

onbetelgeuse commented 4 years ago

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 commented 4 years ago

Let's track this here https://github.com/nestjs/bull/issues/171