11import { Injectable , OnModuleDestroy , Inject } from '@nestjs/common' ;
2- import { Queue , Worker , Job } from 'bullmq' ;
2+ import { Queue , Worker } from 'bullmq' ;
33import IORedis from 'ioredis' ;
44import { AppLoggerService } from '@/common/app-logger/app-logger.service' ;
55import { env } from '@/env' ;
@@ -9,8 +9,6 @@ import { BullMQPrometheusService } from '@/common/monitoring/bullmq-prometheus.s
99import type { BullBoardInjectedInstance } from './types' ;
1010import { QueueBullboardService } from './queue-bullboard.service' ;
1111
12- export type JobProcessor < T = any > = ( job : Job < T > ) => Promise < any > ;
13-
1412export interface QueueOptions < T = any > {
1513 name : string ;
1614 concurrency ?: number ;
@@ -62,16 +60,16 @@ export class QueueService implements OnModuleDestroy {
6260 return this . shouldProcessJobs ;
6361 }
6462
65- getQueue < T = any , R = any , N extends string = string > ( options : QueueOptions < T > ) : Queue < T , R , N > {
63+ private getQueue < T = any > ( options : QueueOptions < T > ) : Queue < T > {
6664 if ( ! this . redisClient ) {
6765 throw new Error ( 'Redis client not initialized' ) ;
6866 }
6967
7068 if ( this . queues . has ( options . name ) ) {
71- return this . queues . get ( options . name ) as unknown as Queue < T , R , N > ;
69+ return this . queues . get ( options . name ) as unknown as Queue < T > ;
7270 }
7371
74- const queue = new Queue < T , R , N > ( options . name , {
72+ const queue = new Queue < T > ( options . name , {
7573 connection : this . redisClient as any ,
7674 defaultJobOptions : {
7775 attempts : options . jobOptions ?. attempts ?? 3 ,
@@ -98,50 +96,32 @@ export class QueueService implements OnModuleDestroy {
9896 return queue ;
9997 }
10098
101- registerWorker < T = any , R = any , N extends string = string > (
99+ registerWorker < T = any > (
102100 queueName : string ,
103- processor : JobProcessor < T > ,
104- options : {
105- concurrency ?: number ;
106- forceLocalProcessing ?: boolean ;
107- } = { } ,
108- ) : Worker < T , R , N > | null {
101+ processor : ( job : any ) => Promise < any > ,
102+ options : { concurrency ?: number } = { } ,
103+ ) : void {
109104 if ( ! this . redisClient ) {
110105 throw new Error ( 'Redis client not initialized' ) ;
111106 }
112107
113- if ( ! this . shouldProcessJobs && ! options . forceLocalProcessing ) {
108+ if ( ! this . shouldProcessJobs ) {
114109 this . logger . debug (
115110 `Skipping worker registration for queue ${ queueName } (not a worker instance)` ,
116111 ) ;
117112
118- return null ;
113+ return ;
119114 }
120115
121116 if ( this . workers . has ( queueName ) ) {
122- return this . workers . get ( queueName ) as unknown as Worker < T , R , N > ;
117+ return ;
123118 }
124119
125- const worker = new Worker < T , R , N > (
126- queueName ,
127- async job => {
128- try {
129- return await processor ( job ) ;
130- } catch ( error ) {
131- this . logger . error ( `Error processing job ${ job . id } in queue ${ queueName } ` , {
132- error,
133- jobId : job . id ,
134- queueName,
135- } ) ;
136- throw error ;
137- }
138- } ,
139- {
140- connection : this . redisClient as any ,
141- concurrency : options . concurrency ?? 1 ,
142- autorun : true ,
143- } ,
144- ) ;
120+ const worker = new Worker < T , any , string > ( queueName , processor , {
121+ connection : this . redisClient as any ,
122+ concurrency : options . concurrency ?? 1 ,
123+ autorun : true ,
124+ } ) ;
145125
146126 worker . on ( 'failed' , ( job , error ) => {
147127 this . logger . error ( `Job ${ job ?. id } failed in queue ${ queueName } ` , {
@@ -161,69 +141,34 @@ export class QueueService implements OnModuleDestroy {
161141 } ) ;
162142 } ) ;
163143
164- this . workers . set ( queueName , worker as unknown as Worker ) ;
144+ this . workers . set ( queueName , worker as unknown as Worker < T , any , string > ) ;
165145 this . logger . log ( `Worker registered for queue: ${ queueName } ` ) ;
166-
167- return worker ;
168146 }
169147
170- async setupJobScheduler < T = any > (
171- queue : Queue ,
172- schedulerId : string ,
173- options : {
174- every : number ;
175- data ?: T ;
176- jobName ?: string ;
177- jobOptions ?: {
178- attempts ?: number ;
179- backoff ?: {
180- type : 'exponential' | 'fixed' ;
181- delay : number ;
182- } ;
183- } ;
184- } ,
185- ) {
186- try {
187- const schedulers = await queue . getJobSchedulers ( ) ;
188- const existingScheduler = schedulers . find ( s => s . id === schedulerId ) ;
189-
190- if ( existingScheduler ) {
191- this . logger . log ( `Job scheduler already exists: ${ schedulerId } ` , {
192- schedulerId,
193- pattern : existingScheduler . pattern ,
194- every : existingScheduler . every ,
195- } ) ;
196-
197- return existingScheduler ;
198- }
199-
200- const jobName = options . jobName || 'scheduled-job' ;
201- const firstJob = await queue . upsertJobScheduler (
202- schedulerId ,
203- { every : options . every , jobId : schedulerId } ,
204- {
205- name : jobName ,
206- data : options . data || { timestamp : Date . now ( ) } ,
207- opts : {
208- attempts : options . jobOptions ?. attempts || 10 ,
209- backoff : options . jobOptions ?. backoff || {
210- type : 'exponential' ,
211- delay : 10000 ,
212- } ,
213- } ,
214- } ,
215- ) ;
148+ createQueue < T = any > ( queueName : string , options ?: QueueOptions < T > ) : void {
149+ if ( this . queues . has ( queueName ) ) {
150+ // Optionally update options if needed
151+ return ;
152+ }
216153
217- this . logger . log ( `Created job scheduler: ${ schedulerId } ` , {
218- schedulerId,
219- every : options . every ,
220- firstJobId : firstJob ?. id ,
221- } ) ;
154+ const queue = new Queue < T , any , string > ( queueName , {
155+ connection : this . redisClient as any ,
156+ defaultJobOptions : options ?. jobOptions ?? {
157+ attempts : 3 ,
158+ backoff : { type : 'exponential' , delay : 5000 } ,
159+ removeOnComplete : { count : 100 , age : 3600 * 24 } ,
160+ removeOnFail : false ,
161+ } ,
162+ } ) ;
163+ this . queues . set ( queueName , queue as Queue ) ;
164+ this . logger . log ( `Queue created: ${ queueName } ` ) ;
165+
166+ if ( this . bullMQPrometheusService ) {
167+ this . bullMQPrometheusService . registerQueue ( queue ) ;
168+ }
222169
223- return firstJob ;
224- } catch ( error ) {
225- this . logger . error ( `Failed to set up job scheduler: ${ schedulerId } ` , { error } ) ;
226- throw error ;
170+ if ( this . shouldProcessJobs && this . bullBoard && this . queueBullboardService ) {
171+ this . queueBullboardService . registerQueue ( this . bullBoard , queue ) ;
227172 }
228173 }
229174
0 commit comments