Почему NestJs не может разрешать зависимости

Я пытаюсь интегрировать bullmq в проект NestJs. Но столкнулся со следующей ошибкой:

Error: Nest can't resolve dependencies of the CustomerSubscriptionPaymentsService (CustomerSubscriptionPaymentsRepo, ?). Please make sure that the argument "BullQueue_invoice" at index [1] is available in the CustomerSubscriptionPaymentsModule context.

Potential solutions:
- Is CustomerSubscriptionPaymentsModule a valid NestJS module?
- If "BullQueue_invoice" is a provider, is it part of the current CustomerSubscriptionPaymentsModule?
- If "BullQueue_invoice" is exported from a separate @Module, is that module imported within CustomerSubscriptionPaymentsModule?
  @Module({
    imports: [ /* the Module containing "BullQueue_invoice" */ ]
  })

Вот каталог проекта:

modules
  app
    app.module.ts
    app.controller.ts    
  customerSubscriptionPayments
    customerSubscriptionPayments.module.ts
    customerSubscriptionPayments.service.ts
    customerSubscriptionPayments.controller.ts
  invoice
    invouce.module.ts
    invoice.controller.ts
    invoice.service.ts
    invoice.processor.ts

app.module.ts

import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bullmq';
import { AppController } from './app.controller';
import { CustomerSubscriptionPaymentsModule } from '../customerSubscriptionPayments/customerSubscriptionPayments.module';
import { CustomerSubscriptionPaymentsService } from '../customerSubscriptionPayments/customerSubscriptionPayments.service';

@Module({
  imports: [
    BullModule.forRoot({
      connection: {
        host: 'localhost',
        port: 6379,
      },
    }),
    CustomerSubscriptionPaymentsModule,
  ],
  providers: [CustomerSubscriptionPaymentsService],
  controllers: [AppController],
})
export class AppModule {}

счет-фактура.module.ts

import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bullmq';
import { InvoiceController } from './invoice.controller';
import { InvoiceService } from './invoice.service';
import { InvoiceRepo } from './invoice.repo';
import { RedisQueues } from 'src/constants';
import { InvoiceProcessor } from './invoice.processor';

@Module({
  imports: [
    BullModule.registerQueue({
      name: 'invoice',
    }),
  ],
  controllers: [InvoiceController],
  providers: [InvoiceService, InvoiceRepo],
  exports: [InvoiceService, InvoiceRepo],
})
export class InvoiceModule {}

счет-фактура.processor.ts

import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Job } from 'bullmq';
import { InvoiceQueueTasks } from './constants';

@Processor('invoice')
export class InvoiceProcessor extends WorkerHost {
  async generateInvoice(job: Job) {
    const { data } = job;

    if (data.customerSubscriptionId) {
      console.error('customerSubscriptionId not found');
      return {};
    }

    //TODO: Implement invoice generation logic
  }

  async process(job: Job) {
    const { data, name } = job;

    if (name === InvoiceQueueTasks.GENERATE) {
      return this.generateInvoice(job);
    }

    return {};
  }
}

customerSubscriptionPayments.module.ts

import { Module } from '@nestjs/common';
import { CustomerSubscriptionPaymentsController } from './customerSubscriptionPayments.controller';
import { CustomerSubscriptionPaymentsRepo } from './customerSubscriptionPayments.repo';
import { CustomerSubscriptionPaymentsService } from './customerSubscriptionPayments.service';

@Module({
  controllers: [CustomerSubscriptionPaymentsController],
  providers: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
  exports: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
})
export class CustomerSubscriptionPaymentsModule {}

customerSubscriptionPayments.service.ts

import { InjectQueue } from '@nestjs/bullmq';
import { Queue } from 'bullmq';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';

@Injectable()
export class CustomerSubscriptionPaymentsService {
  constructor(@InjectQueue('invoice') private invoiceQueue: Queue) {}

  async generateInvoice() {
    const job = await this.invoiceQueue.add('generate', {
      customerSubscriptionId: 1,
    });

    if (!job) {
      throw new HttpException(
        'Failed to generate invoice',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }

    return {
      success: true,
    };
  }
}

🤔 А знаете ли вы, что...
Node.js имеет интегрированный менеджер пакетов npm для управления зависимостями.


1
62
1

Ответ:

Решено

Проблема в том, что вы не импортируете свою Bull Queue в свой модуль customerSubscriptionPayments, поэтому, когда вы попытаетесь внедрить ее в службу customerSubscriptionPayments, она не сможет разрешить зависимость.

@Module({
  imports: [
    BullModule.registerQueue({
      name: 'invoice',
    }),
  ]
  controllers: [CustomerSubscriptionPaymentsController],
  providers: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
  exports: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
})

Другой способ сделать что-то

Поскольку в документации NestJS нет документации, показывающей, как экспортировать зарегистрированную Bull Queue, вы можете создать Module, который экспортирует Service, который обрабатывает очередь независимо, после этого вы можете импортировать этот модуль в другие сервисы, чтобы вы могли добавлять, удалять или выполнять любые действия. действие, связанное с очередью, в любой нужной вам службе. Вы можете сделать это в своем Invoice Module, поскольку именно там вы в первую очередь регистрировали очередь.

Пример:

Модуль счетов

@Module({
  imports: [
    BullModule.registerQueue({
      name: 'invoice',
    }),
  ],
  controllers: [InvoiceController],
  providers: [InvoiceService, InvoiceRepo, InvoiceQueueHandler],
  exports: [InvoiceService, InvoiceRepo, InvoiceQueueHandler],
})
export class InvoiceModule {}

Обработчик очереди счетов

export class InvoiceQueueHandler(){
 constructor(InjectQueue('invoice') private invoiceQueue: Queue){}

 addJob(){
  // perform some action 
 }

 // rest of your functions to handle the queue
}

КлиентПодпискаПлатежный модуль

@Module({
  import: [InvoiceModule]
  controllers: [CustomerSubscriptionPaymentsController],
  providers: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
  exports: [
    CustomerSubscriptionPaymentsService,
    CustomerSubscriptionPaymentsRepo,
  ],
})
export class CustomerSubscriptionPaymentsModule {}

КлиентПодпискаПлатежный модуль

@Injectable()
export class CustomerSubscriptionPaymentsService {
  constructor(private invoiceQueueHandler: InvoiceQueueHandler) {}
  
  someFunction(){
   this.invoiceQueueHandler.addJob()
  }
}