UNPKG

actionhero

Version:

actionhero.js is a multi-transport API Server with integrated cluster capabilities and delayed tasks

166 lines (141 loc) 7.26 kB
'use strict' const NR = require('node-resque') /** * The node-resque workers and scheduler which process tasks. * @see https://github.com/taskrabbit/node-resque * * @namespace api.resque * @property {Object} queue - The Node Resque `queue`. Used to enqueue tasks and read properties from Redis. * @property {Object} multiWorker - The Node Resque `Multi Worker`. Runs tasks. * @property {Object} scheduler - The Node Resque `scheduler`. Checks on delaed tasks. * @property {Object} connectionDetails - Connection oprions (from `api.redis.clients.tasks`). */ module.exports = { startPriority: 200, stopPriority: 100, loadPriority: 600, initialize: function (api, next) { const resqueOverrides = api.config.tasks.resque_overrides api.resque = { verbose: false, queue: null, multiWorker: null, scheduler: null, connectionDetails: {redis: api.redis.clients.tasks}, startQueue: function (callback) { let Queue = NR.queue if (resqueOverrides && resqueOverrides.queue) { Queue = resqueOverrides.queue } this.queue = new Queue({connection: this.connectionDetails}, api.tasks.jobs) this.queue.on('error', (error) => { api.log(error, 'error', '[api.resque.queue]') }) this.queue.connect(callback) }, stopQueue: function (callback) { if (api.resque.queue) { api.resque.queue.end(callback) } else { callback() } }, startScheduler: function (callback) { let Scheduler = NR.scheduler if (resqueOverrides && resqueOverrides.scheduler) { Scheduler = resqueOverrides.scheduler } if (api.config.tasks.scheduler === true) { this.schedulerLogging = api.config.tasks.schedulerLogging this.scheduler = new Scheduler({connection: this.connectionDetails, timeout: api.config.tasks.timeout}) this.scheduler.on('error', (error) => { api.log(error, 'error', '[api.resque.scheduler]') }) this.scheduler.connect(() => { this.scheduler.on('start', () => { api.log('resque scheduler started', this.schedulerLogging.start) }) this.scheduler.on('end', () => { api.log('resque scheduler ended', this.schedulerLogging.end) }) this.scheduler.on('poll', () => { api.log('resque scheduler polling', this.schedulerLogging.poll) }) this.scheduler.on('working_timestamp', (timestamp) => { api.log(`resque scheduler working timestamp ${timestamp}`, this.schedulerLogging.working_timestamp) }) this.scheduler.on('transferred_job', (timestamp, job) => { api.log(`resque scheduler enqueuing job ${timestamp}`, this.schedulerLogging.transferred_job, job) }) this.scheduler.on('master', (state) => { api.log('This node is now the Resque scheduler master') }) this.scheduler.start() callback() }) } else { callback() } }, stopScheduler: function (callback) { if (!this.scheduler) { callback() } else { this.scheduler.end(() => { delete this.scheduler callback() }) } }, startMultiWorker: function (callback) { let MultiWorker = NR.multiWorker if (resqueOverrides && resqueOverrides.multiWorker) { MultiWorker = resqueOverrides.multiWorker } this.workerLogging = api.config.tasks.workerLogging this.schedulerLogging = api.config.tasks.schedulerLogging this.multiWorker = new MultiWorker({ connection: api.resque.connectionDetails, queues: api.config.tasks.queues, timeout: api.config.tasks.timeout, checkTimeout: api.config.tasks.checkTimeout, minTaskProcessors: api.config.tasks.minTaskProcessors, maxTaskProcessors: api.config.tasks.maxTaskProcessors, maxEventLoopDelay: api.config.tasks.maxEventLoopDelay, toDisconnectProcessors: api.config.tasks.toDisconnectProcessors }, api.tasks.jobs) // normal worker emitters this.multiWorker.on('start', (workerId) => { api.log('[ worker ] started', this.workerLogging.start, {workerId: workerId}) }) this.multiWorker.on('end', (workerId) => { api.log('[ worker ] ended', this.workerLogging.end, {workerId: workerId}) }) this.multiWorker.on('cleaning_worker', (workerId, worker, pid) => { api.log(`[ worker ] cleaning old worker ${worker}, (${pid})`, this.workerLogging.cleaning_worker) }) this.multiWorker.on('poll', (workerId, queue) => { api.log(`[ worker ] polling ${queue}`, this.workerLogging.poll, {workerId: workerId}) }) this.multiWorker.on('job', (workerId, queue, job) => { api.log(`[ worker ] working job ${queue}`, this.workerLogging.job, {workerId: workerId, job: {class: job['class'], queue: job.queue}}) }) this.multiWorker.on('reEnqueue', (workerId, queue, job, plugin) => { api.log('[ worker ] reEnqueue job', this.workerLogging.reEnqueue, {workerId: workerId, plugin: plugin, job: {class: job['class'], queue: job.queue}}) }) this.multiWorker.on('success', (workerId, queue, job, result) => { api.log(`[ worker ] job success ${queue}`, this.workerLogging.success, {workerId: workerId, job: {class: job['class'], queue: job.queue}, result: result}) }) this.multiWorker.on('pause', (workerId) => { api.log('[ worker ] paused', this.workerLogging.pause, {workerId: workerId}) }) this.multiWorker.on('failure', (workerId, queue, job, failure) => { api.exceptionHandlers.task(failure, queue, job, workerId) }) this.multiWorker.on('error', (workerId, queue, job, error) => { api.exceptionHandlers.task(error, queue, job, workerId) }) // multiWorker emitters this.multiWorker.on('internalError', (error) => { api.log(error, this.workerLogging.internalError) }) this.multiWorker.on('multiWorkerAction', (verb, delay) => { api.log(`[ multiworker ] checked for worker status: ${verb} (event loop delay: ${delay}ms)`, this.workerLogging.multiWorkerAction) }) if (api.config.tasks.minTaskProcessors > 0) { this.multiWorker.start(() => { if (typeof callback === 'function') { callback() } }) } else { if (typeof callback === 'function') { callback() } } }, stopMultiWorker: function (callback) { if (this.multiWorker && api.config.tasks.minTaskProcessors > 0) { this.multiWorker.stop(() => { api.log('task workers stopped') callback() }) } else { callback() } } } next() }, start: function (api, next) { if (api.config.tasks.minTaskProcessors === 0 && api.config.tasks.maxTaskProcessors > 0) { api.config.tasks.minTaskProcessors = 1 } api.resque.startQueue(function () { api.resque.startScheduler(function () { api.resque.startMultiWorker(function () { next() }) }) }) }, stop: function (api, next) { api.resque.stopScheduler(function () { api.resque.stopMultiWorker(function () { api.resque.stopQueue(function () { next() }) }) }) } }