UNPKG

@midwayjs/bullmq

Version:
281 lines 10.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BullMQFramework = exports.BullMQQueue = void 0; const core_1 = require("@midwayjs/core"); const bullmq_1 = require("bullmq"); const constants_1 = require("./constants"); class BullMQQueue extends bullmq_1.Queue { constructor(queueName, queueOptions) { super(queueName, queueOptions); this.queueName = queueName; this.queueOptions = queueOptions; this.queueEventsList = []; this.queueEventsProducerList = []; } async addJobToQueue(data, options) { const { repeat, ...OtherOptions } = options !== null && options !== void 0 ? options : {}; if (repeat) { return this.upsertJobScheduler(this.name, repeat, { name: 'jobName', data, opts: OtherOptions, // additional job options }); } return this.add('jobName', data || {}, options); } /** * @deprecated use addJobToQueue instead */ // runJob 与 @midwayjs/bull 保持一致,如果想要使用 jobName 则可以直接调用 queue.add async runJob(data, options) { return this.addJobToQueue(data, options); } getQueueName() { return this.queueName; } createQueueEvents(options) { const evt = new bullmq_1.QueueEvents(this.name, { connection: this.queueOptions.connection, prefix: this.queueOptions.prefix, ...options, }); this.queueEventsList.push(evt); return evt; } getQueueEventsList() { return this.queueEventsList; } createQueueEventsProducer(options) { const producer = new bullmq_1.QueueEventsProducer(this.name, { connection: this.queueOptions.connection, prefix: this.queueOptions.prefix, ...options, }); this.queueEventsProducerList.push(producer); return producer; } getQueueEventsProducerList() { return this.queueEventsProducerList; } async close() { // 并发关闭 await Promise.all(this.queueEventsList.map(evt => evt.close())); await Promise.all(this.queueEventsProducerList.map(producer => producer.close())); await super.close(); } } exports.BullMQQueue = BullMQQueue; let BullMQFramework = class BullMQFramework extends core_1.BaseFramework { constructor() { super(...arguments); this.queueMap = new Map(); this.workerMap = new Map(); this.flowProducerMap = new Map(); } async applicationInitialize(options) { this.app = {}; } loadConfig() { const defaultConnection = this.configService.getConfiguration('bullmq.defaultConnection'); const defaultPrefix = this.configService.getConfiguration('bullmq.defaultPrefix'); this.defaultConnection = { connection: defaultConnection, prefix: defaultPrefix, }; this.defaultQueueConfig = this.configService.getConfiguration('bullmq.defaultQueueOptions'); this.defaultWorkerConfig = this.configService.getConfiguration('bullmq.defaultWorkerOptions'); this.clearRepeatJobWhenStart = this.configService.getConfiguration('bullmq.clearRepeatJobWhenStart'); } configure() { return this.configService.getConfiguration('bullmq'); } getFrameworkName() { return 'bullmq'; } async run() { var _a, _b, _c; const processorModules = (0, core_1.listModule)(constants_1.BULLMQ_PROCESSOR_KEY); for (const mod of processorModules) { const options = (0, core_1.getClassMetadata)(constants_1.BULLMQ_PROCESSOR_KEY, mod); const { repeat, ...otherOptions } = (_a = options.jobOptions) !== null && _a !== void 0 ? _a : {}; const queueOptions = (_b = options.queueOptions) !== null && _b !== void 0 ? _b : {}; const currentQueue = this.ensureQueue(options.queueName, { ...queueOptions, defaultJobOptions: otherOptions, }); if (!currentQueue) { throw new core_1.MidwayCommonError(`[midway:bullmq] Queue ${options.queueName} not found`); } // clear old repeat job when start if (this.clearRepeatJobWhenStart) { const jobs = await currentQueue.getJobSchedulers(); for (const job of jobs) { await currentQueue.removeJobScheduler(job.key); } // Repeatable in jobOptions is depecrate const repeatableJobs = await currentQueue.getRepeatableJobs(); for (const job of repeatableJobs) { await currentQueue.removeRepeatableByKey(job.key); } } await this.addProcessor(mod, options.queueName, options.workerOptions); if (repeat) { // add repeatable job await ((_c = this.getQueue(options.queueName)) === null || _c === void 0 ? void 0 : _c.addJobToQueue({}, options.jobOptions)); } } } async beforeStop() { // loop queueMap and stop all queue await Promise.all(Array.from(this.queueMap.values()).map(queue => queue.close())); await Promise.all(Array.from(this.workerMap.values()).map(worker => worker.map(w => w.close()))); await Promise.all(Array.from(this.flowProducerMap.values()).map(producer => producer.close())); } /** * Create a queue with name and queueOptions */ createQueue(name, queueOptions = {}) { const mergedOptions = (0, core_1.extend)(true, {}, this.defaultQueueConfig, this.defaultConnection, queueOptions); const queue = new BullMQQueue(name, mergedOptions); this.queueMap.set(name, queue); queue.on('error', err => { this.bullMQLogger.error(err); }); return queue; } /** * Get a queue by name */ getQueue(name) { return this.queueMap.get(name); } /** * Ensure a queue by name and queueOptions */ ensureQueue(name, queueOptions = {}) { if (!this.queueMap.has(name)) { this.createQueue(name, queueOptions); } return this.queueMap.get(name); } getQueueList() { return Array.from(this.queueMap.values()); } /** * Get the first worker by queueName */ getWorker(queueName) { var _a; return (_a = this.workerMap.get(queueName)) === null || _a === void 0 ? void 0 : _a[0]; } /** * Get all workers by queueName */ getWorkers(queueName) { return this.workerMap.get(queueName); } /** * Create a worker */ createWorker(queueName, processor, workerOptions = {}) { const merged = { ...this.defaultConnection, ...this.defaultWorkerConfig, ...workerOptions, }; const worker = new bullmq_1.Worker(queueName, processor, merged); if (!this.workerMap.has(queueName)) { this.workerMap.set(queueName, []); } this.workerMap.get(queueName).push(worker); return worker; } /** * Add a processor class and init a worker */ async addProcessor(processor, queueName, workerOptions) { const queue = this.queueMap.get(queueName); if (!queue) throw Error(`queue not found ${queueName}`); return this.createWorker(queueName, async (job, token) => { const ctx = this.app.createAnonymousContext({ jobId: job.id, job, token, from: processor, }); try { ctx.logger.info(`start process job ${job.id} from ${processor.name}`); const isPassed = await this.app .getFramework() .runGuard(ctx, processor, 'execute'); if (!isPassed) { throw new core_1.MidwayInvokeForbiddenError('execute', processor); } const service = await ctx.requestContext.getAsync(processor); const fn = await this.applyMiddleware(async (ctx) => { return await core_1.Utils.toAsyncFunction(service.execute.bind(service))(job.data, job, token); }); const result = await Promise.resolve(await fn(ctx)); ctx.logger.info(`complete process job ${job.id} from ${processor.name}`); return result; } catch (err) { ctx.logger.error(err); return Promise.reject(err); } }, workerOptions); } /** * Add a job to the queue */ async addJobToQueue(queueName, jobData, options) { const queue = this.queueMap.get(queueName); if (queue) { return await queue.addJobToQueue(jobData, options); } } /** * @deprecated use addJobToQueue instead */ async runJob(queueName, jobData, options) { return this.addJobToQueue(queueName, jobData, options); } /** * Create a flow producer, if producerName is provided, it will be store. */ createFlowProducer(options, producerName) { const producer = new bullmq_1.FlowProducer({ ...this.defaultConnection, ...options, }); if (producerName) { this.flowProducerMap.set(producerName, producer); } return producer; } /** * Get a flow producer by name */ getFlowProducer(producerName) { return this.flowProducerMap.get(producerName); } }; __decorate([ (0, core_1.Logger)('bullMQLogger'), __metadata("design:type", Object) ], BullMQFramework.prototype, "bullMQLogger", void 0); BullMQFramework = __decorate([ (0, core_1.Framework)() ], BullMQFramework); exports.BullMQFramework = BullMQFramework; //# sourceMappingURL=framework.js.map