refactor: made the sms to use queue

This commit is contained in:
2026-07-31 18:46:21 +03:30
parent ac4e34436a
commit a4c50496c5
18 changed files with 306 additions and 73 deletions
+4 -8
View File
@@ -2,25 +2,21 @@ import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UtilsModule } from '../utils/utils.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { OTP } from './entities/otp.entity';
import { OtpRepository } from './repositories/otp.repository';
import { UsersModule } from 'src/modules/users/users.module';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './strategies/jwt.strategy';
import { OtpService } from './otp.service';
import { NotificationModule } from '../notifications/notification.module';
@Module({
imports: [
TypeOrmModule.forFeature([OTP]),
PassportModule,
JwtModule.register({}),
UtilsModule,
UsersModule,
NotificationModule,
],
controllers: [AuthController],
providers: [AuthService, OtpService, OtpRepository, JwtStrategy],
providers: [AuthService, OtpService, JwtStrategy],
exports: [JwtModule, PassportModule],
})
export class AuthModule {}
export class AuthModule {}
+5 -10
View File
@@ -1,27 +1,23 @@
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import type { ISmsConfigs } from 'src/config/sms.config';
import { SMS_CONFIG } from '../utils/constants';
import { SmsService } from '../utils/providers/sms.service';
import { OtpRepository } from './repositories/otp.repository';
import { OtpStatus } from './enums/otp-status.enum';
import { SMS_CONFIG } from '../notifications/constants';
import { VerifyOtpDto } from './DTO/verify-otp.dto';
import { OTPMessages, UserMessages } from 'src/common/enums/messages.enum';
import { UserMessages } from 'src/common/enums/messages.enum';
import { LoginCredentialDto } from './DTO/login-credential.dto';
import { UsersService } from 'src/modules/users/users.service';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import ms from 'ms';
import { OtpService } from './otp.service';
import { RoleType } from '../users/enums/user-role.enum';
import { SendOtpDto } from './DTO/send-otp.dto';
import { string } from 'joi';
import { SmsProducer } from '../notifications/producers/sms.producer';
@Injectable()
export class AuthService {
constructor(
@Inject(SMS_CONFIG) private smsConfig: ISmsConfigs,
private readonly smsService: SmsService,
private readonly smsProducer: SmsProducer,
private readonly configService: ConfigService,
private readonly userService: UsersService,
private readonly jwtService: JwtService,
@@ -35,7 +31,7 @@ export class AuthService {
});
try {
await this.smsService.sendSms({
await this.smsProducer.sendSms({
Mobile: dto.phoneNumber,
TemplateId: this.smsConfig.SMS_PATTERN_OTP,
Parameters: [
@@ -61,7 +57,6 @@ export class AuthService {
{ phoneNumber: dto.phoneNumber, role: dto.role },
dto.code,
);
if (dto.role) console.log('VERIFIED OTP FOR ROLE: ', dto.role);
}
async checkLoginCredentials(credential: LoginCredentialDto): Promise<void> {
-23
View File
@@ -1,23 +0,0 @@
import { Column, Entity } from 'typeorm';
import { BaseEntity } from 'src/common/entities/base.entity';
import { OtpStatus } from '../enums/otp-status.enum';
@Entity('otps')
export class OTP extends BaseEntity {
@Column({ type: 'varchar', length: 6 })
code: string;
@Column({ type: 'timestamptz' })
expirationDate: Date;
@Column({type: 'enum', enum: OtpStatus, default: OtpStatus.PENDING})
status: OtpStatus;
@Column({ type: 'smallint', default: 0 })
numberOfTries: number;
@Column({
length: 11,
})
phoneNumber: string;
}
@@ -1,13 +0,0 @@
import { Repository } from 'typeorm';
import { OTP } from '../entities/otp.entity';
import { InjectRepository } from '@nestjs/typeorm';
export class OtpRepository extends Repository<OTP> {
constructor(@InjectRepository(OTP) otpRepository: Repository<OTP>) {
super(
otpRepository.target,
otpRepository.manager,
otpRepository.queryRunner,
);
}
}
+2
View File
@@ -0,0 +1,2 @@
export const SMS_CONFIG = "SMS_CONFIG";
export const SMS_QUEUE = 'sms';
@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bullmq';
import { SmsService } from './providers/sms.service';
import { SmsProducer } from './producers/sms.producer';
import { SmsProcessor } from './processors/sms.processor';
import { SMS_CONFIG, SMS_QUEUE } from './constants';
import { smsConfigsProvider } from 'src/config/sms.config';
import { HttpModule } from '@nestjs/axios';
@Module({
imports: [
HttpModule,
BullModule.registerQueue({
name: SMS_QUEUE,
}),
],
providers: [SmsService, smsConfigsProvider, SmsProducer, SmsProcessor],
exports: [SmsProducer, SMS_CONFIG],
})
export class NotificationModule {}
export { SMS_QUEUE };
@@ -0,0 +1,22 @@
import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Job } from 'bullmq';
import { Logger } from '@nestjs/common';
import { SMS_QUEUE } from '../constants';
import { SmsService } from '../providers/sms.service';
import { SmsRequest } from '../interfaces/ISms';
@Processor(SMS_QUEUE)
export class SmsProcessor extends WorkerHost {
private readonly logger = new Logger(SmsProcessor.name);
constructor(private readonly smsService: SmsService) {
super();
}
async process(job: Job<SmsRequest>): Promise<void> {
this.logger.log(
`Processing SMS job ${job.id} (attempt ${job.attemptsMade + 1})`,
);
await this.smsService.sendSms(job.data);
}
}
@@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bullmq';
import { Queue } from 'bullmq';
import { SMS_QUEUE } from '../constants';
import { SmsRequest } from '../interfaces/ISms';
@Injectable()
export class SmsProducer {
constructor(@InjectQueue(SMS_QUEUE) private readonly smsQueue: Queue) {}
async sendSms(body: SmsRequest) {
return this.smsQueue.add('send-sms', body, {
attempts: 3,
backoff: { type: 'exponential', delay: 2000 },
removeOnComplete: true,
removeOnFail: false,
});
}
}
@@ -1,5 +1,4 @@
import {
BadGatewayException,
Inject,
Injectable,
InternalServerErrorException,
-1
View File
@@ -1,5 +1,4 @@
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';
import {
IsEmail,
IsNotEmpty,
-1
View File
@@ -1 +0,0 @@
export const SMS_CONFIG = "SMS_CONFIG";
-10
View File
@@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { SmsService } from './providers/sms.service';
import { smsConfigsProvider } from 'src/config/sms.config';
import { SMS_CONFIG } from './constants';
@Module({
providers: [SmsService, smsConfigsProvider],
exports: [SMS_CONFIG, SmsService],
})
export class UtilsModule {}