UNPKG

celery-node

Version:
179 lines (178 loc) 6.42 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const base_1 = require("./base"); class Worker extends base_1.default { constructor() { super(...arguments); this.handlers = {}; this.activeTasks = new Set(); } /** * Register task handler on worker handlers * @method Worker#register * @param {String} name the name of task for dispatching. * @param {Function} handler the function for task handling * * @example * worker.register('tasks.add', (a, b) => a + b); * worker.start(); */ register(name, handler) { if (!handler) { throw new Error("Undefined handler"); } if (this.handlers[name]) { throw new Error("Handler is already set"); } this.handlers[name] = function registHandler(...args) { try { return Promise.resolve(handler(...args)); } catch (err) { return Promise.reject(err); } }; } /** * Start celery worker to run * @method Worker#start * @example * worker.register('tasks.add', (a, b) => a + b); * worker.start(); */ start() { console.info("celery.node worker starting..."); console.info(`registered task: ${Object.keys(this.handlers)}`); return this.run().catch(err => console.error(err)); } /** * @method Worker#run * @private * * @returns {Promise} */ run() { return this.isReady().then(() => this.processTasks()); } /** * @method Worker#processTasks * @private * * @returns function results */ processTasks() { const consumer = this.getConsumer(this.conf.CELERY_QUEUE); return consumer(); } /** * @method Worker#getConsumer * @private * * @param {String} queue queue name for task route */ getConsumer(queue) { const onMessage = this.createTaskHandler(); return () => this.broker.subscribe(queue, onMessage); } createTaskHandler() { const onTaskReceived = (message) => { if (!message) { return Promise.resolve(); } let payload = null; let taskName = message.headers["task"]; if (!taskName) { // protocol v1 payload = message.decode(); taskName = payload["task"]; } // strategy let body; let headers; if (payload == null && !("args" in message.decode())) { body = message.decode(); // message.body; headers = message.headers; } else { const args = payload["args"] || []; const kwargs = payload["kwargs"] || {}; const embed = { callbacks: payload["callbacks"], errbacks: payload["errbacks"], chord: payload["chord"], chain: null }; body = [args, kwargs, embed]; headers = { lang: payload["lang"], task: payload["task"], id: payload["id"], rootId: payload["root_id"], parentId: payload["parentId"], group: payload["group"], meth: payload["meth"], shadow: payload["shadow"], eta: payload["eta"], expires: payload["expires"], retries: payload["retries"] || 0, timelimit: payload["timelimit"] || [null, null], kwargsrepr: payload["kwargsrepr"], origin: payload["origin"] }; } // request const [args, kwargs /*, embed */] = body; const taskId = headers["id"]; const handler = this.handlers[taskName]; if (!handler) { throw new Error(`Missing process handler for task ${taskName}`); } console.info(`celery.node Received task: ${taskName}[${taskId}], args: ${args}, kwargs: ${JSON.stringify(kwargs)}`); const timeStart = process.hrtime(); const taskPromise = handler(...args, kwargs).then(result => { const diff = process.hrtime(timeStart); console.info(`celery.node Task ${taskName}[${taskId}] succeeded in ${diff[0] + diff[1] / 1e9}s: ${result}`); this.backend.storeResult(taskId, result, "SUCCESS"); this.activeTasks.delete(taskPromise); }).catch(err => { console.info(`celery.node Task ${taskName}[${taskId}] failed: [${err}]`); this.backend.storeResult(taskId, err, "FAILURE"); this.activeTasks.delete(taskPromise); }); // record the executing task this.activeTasks.add(taskPromise); return taskPromise; }; return onTaskReceived; } /** * @method Worker#whenCurrentJobsFinished * * @returns Promise that resolves when all jobs are finished */ whenCurrentJobsFinished() { return __awaiter(this, void 0, void 0, function* () { return Promise.all(Array.from(this.activeTasks)); }); } /** * @method Worker#stop * * @todo implement here */ // eslint-disable-next-line class-methods-use-this stop() { throw new Error("not implemented yet"); } } exports.default = Worker;