Korer
Korer

Reputation: 197

Nest can't resolve dependencies when using Queue inside Service and vice-versa

I have the following code:

transaction.processor.ts

import { Process, Processor } from '@nestjs/bull';
import { TransactionService } from '@src/modules/transaction/transaction.service';
import { Job } from 'bull';

export const transactionQueue = 'TransactionQueue';
export const transactionJob = 'TransactionJob';

@Processor(transactionQueue)
export class TransactionProcessor {
  constructor(private readonly _transactionService: TransactionService) {}

  @Process(transactionJob)
  async handleFinalizeTransaction(job: Job) {
    const { transactionId } = job.data;

    try {
      await this._transactionService.finalizeTransaction(transactionId);
    } catch (error) {
      console.error('Error finalizing transaction:', error);
      throw error;
    }
  }
}
transaction.service.ts
import { InjectQueue } from '@nestjs/bull';
import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { BaseService } from '@src/core/bases/base.service';
import { ErrorMessages } from '@src/core/enums/error-messages.enum';
import { Roles } from '@src/core/enums/roles.enum';
import { TransactionStatus } from '@src/core/enums/transaction-status.enum';
import { InputTransactionPaginationDto } from '@src/modules/transaction/dtos/input.transaction-pagination.dto';
import { TransactionEntity } from '@src/modules/transaction/entities/transaction.entity';
import { transactionJob, transactionQueue } from '@src/modules/transaction/queues/transaction.processor';
import { UserEntity } from '@src/modules/user/entities/user.entity';
import { pagination } from '@src/utils/utils';
import { Queue } from 'bull';
import { Repository } from 'typeorm';

@Injectable()
export class TransactionService extends BaseService<TransactionEntity> {
  constructor(
    @InjectRepository(TransactionEntity) private _transactionRepository: Repository<TransactionEntity>,
    @InjectQueue(transactionQueue)
    private readonly _transactionQueue: Queue,
  ) {
    super(_transactionRepository);
  }

  async createTransaction(user: UserEntity, teacher: UserEntity, amount: number) {
    if (user.tokens < amount) {
      throw new BadRequestException(ErrorMessages.INSUFFICIENT_TOKENS);
    }

    user.tokens -= amount;
    await this._transactionRepository.save(user);

    const transaction = this._transactionRepository.create({
      user,
      teacher,
      amount,
      status: TransactionStatus.ACTIVE,
    });

    await this._transactionQueue.add(
      transactionJob,
      { transactionId: transaction.id },
      { delay: 14 * 24 * 60 * 60 * 1000 },
    );

    await this._transactionRepository.save(transaction);

    return transaction;
  }
}


Unfortunately, in console I've got:

 Nest can't resolve dependencies of the TransactionService (TransactionEntityRepository, ?). Please make sure that the argument BullQueue_default at index [1] is available in the TransactionModule context.

When I remove transactionService from processor then it works but I need to use this service there. Is that some kind of circular dependency? In my transacion.module.ts I have:

import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TransactionEntity } from '@src/modules/transaction/entities/transaction.entity';
import { TransactionProcessor, transactionQueue } from '@src/modules/transaction/queues/transaction.processor';
import { TransactionController } from '@src/modules/transaction/transaction.controller';
import { TransactionService } from '@src/modules/transaction/transaction.service';

@Module({
  providers: [TransactionService, TransactionProcessor],
  imports: [
    TypeOrmModule.forFeature([TransactionEntity]),
    PassportModule.register({ defaultStrategy: 'jwt' }),
    BullModule.registerQueue({ name: transactionQueue }),
  ],
  controllers: [TransactionController],
  exports: [TransactionService, BullModule],
})
export class TransactionModule {}

Upvotes: 0

Views: 164

Answers (2)

ValentinG
ValentinG

Reputation: 196

Yes it's circular dependencies. Because the service inject the queue and your queue use the service

In your case you should change the pattern and maybe work with the event system of nest js.

Imagine triggering a CreatedTransaction event that queue a new Transaction job. It's preventing the circular dependancies because

For my personal use case i just created a new service that just enqueue because methods were call from the controller

Upvotes: 0

Eduardo Serrano
Eduardo Serrano

Reputation: 97

If you are importing the TransactionService into another module I think you might need to register the queue again in the new module.

import { Module } from '@nestjs/common';
import { NewService } from './new.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { NewEntity } from './entities/new.entity';
import { BullModule } from '@nestjs/bull';
import { transactionQueue } from '@src/modules/transaction/queues/transaction.processor';
import { TransactionModule } from '@src/modules/transaction/transaction.module';

@Module({
  imports: [
    TransactionModule,
    TypeOrmModule.forFeature([NewEntity]),
    BullModule.registerQueue({
      name: transactionQueue,
    }),
  ],
  providers: [NewService],
  exports: [NewService],
})
export class NewModule {}

Upvotes: 0

Related Questions