torotask
Version:
Task queue processing in NodeJS based on BullMQ and Redis
123 lines • 5.13 kB
JavaScript
import { Queue } from 'bullmq'; // Import JobsOptions
import { TaskJob } from './job.js';
export class TaskQueue extends Queue {
taskClient;
logger;
constructor(taskClient, name, options) {
if (!taskClient) {
throw new Error('ToroTask instance is required.');
}
if (!name) {
throw new Error('Queue name is required.');
}
options = options || {};
options.prefix = options.prefix || taskClient.queuePrefix;
options.connection = options.connection = taskClient.getQueueConnectionOptions();
// Use shared Redis instance for queue connection reusing if enabled
const sharedQueueRedisInstance = taskClient.getSharedQueueRedisInstance();
if (sharedQueueRedisInstance) {
options.connection = sharedQueueRedisInstance;
}
super(name, options);
this.taskClient = taskClient;
this.logger = options.logger || taskClient.logger.child({ taskQueue: name });
}
/**
* Override the Job class to use TaskJob
* @returns {typeof Job}
*/
get Job() {
return TaskJob;
}
get TaskJob() {
return TaskJob;
}
/**
* Get the Redis client instance used by the queue.
* @returns The Redis client instance.
*/
async getRedisClient() {
return this.client;
}
/**
* Core logic to add a job to the queue.
* Public method intended for use by subclasses or related classes (e.g., SubTask).
*/
async add(name, payload, options, state) {
// Return specific TaskJob
const data = {
payload,
state,
};
const job = await super.add(name, data, options); // Cast options to JobsOptions
// Cast the result from the base Job to the specific TaskJob
return job;
}
/**
* Core logic to add multiple jobs to the queue.
* Public method intended for use by subclasses or related classes (e.g., SubTask).
*/
// Assuming BulkJob's options are compatible with BullMQ's BulkJobOptions
async addBulk(jobs) {
this.logger.debug(`Bulk adding jobs ${jobs.length} to queue [${this.name}]`);
const bulkJobs = jobs.map((job) => {
const data = {
...job.data,
};
if (job.payload)
data.payload = job.payload;
if (job.state)
data.state = job.state;
return {
name: job.name,
opts: job.options,
data: data,
};
});
const result = await super.addBulk(bulkJobs);
this.logger.debug(`${result.length} Jobs bulk added added to queue [${this.name}]`);
return result;
}
/**
* Core logic to add a job and wait for its completion.
* Public method intended for use by subclasses or related classes.
*/
async _runJobAndWait(name, payload, options, state) {
// Use specific JobReturn generic
const waitLogger = this.logger.child({ jobName: name, action: 'runAndWait' });
waitLogger.debug({ payload, options }, 'Adding job and waiting for completion');
// Call the corrected _runJob
const job = await this.add(name, payload, options, state); // Cast data if needed
const jobLogger = this.logger.child({ jobId: job.id, jobName: name });
try {
jobLogger.debug('Waiting for job completion...');
// Make sure queueEvents is accessible (might need to be passed or stored)
// Assuming this.queueEvents exists similar to BaseQueue/WorkerQueue
if (!this.queueEvents) {
throw new Error('QueueEvents instance not available for waiting.');
}
await job.waitUntilFinished(this.queueEvents);
if (!job.id) {
jobLogger.error('Job ID is missing after waiting. Cannot get result.');
throw new Error('Job ID is missing after waiting. Cannot get result.');
}
jobLogger.debug('Refetching job after completion');
// Use the overridden this.Job getter which returns TaskJob
const finishedJob = await this.Job.fromId(this, job.id);
if (!finishedJob) {
jobLogger.error('Failed to refetch job after completion.');
throw new Error(`Failed to refetch job ${job.id} after completion.`);
}
jobLogger.debug({ returnValue: finishedJob.returnvalue }, 'Job completed successfully');
return finishedJob.returnvalue;
}
catch (error) {
jobLogger.error({ err: error instanceof Error ? error : new Error(String(error)) }, 'Job failed or could not be waited for');
throw error;
}
}
// Add queueEvents property if it's needed by _runJobAndWait and not already present
// You might need to initialize this in the constructor similar to WorkerQueue
queueEvents; // Replace 'any' with the actual type, e.g., TaskQueueEvents
}
//# sourceMappingURL=queue.js.map