UNPKG

@cavai/adonis-queue

Version:
149 lines (148 loc) 5.23 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueManager = void 0; const superjson_1 = __importDefault(require("superjson")); /** * Config for manager looks like this * * { * default: 'somename', * queues: { * somename: () => new DatabaseDrive({ * table_name: 'sjdasjk', * }) * } * } */ class QueueManager { constructor(config, logger, jobsRoot) { this.config = config; this.logger = logger; this.jobsRoot = jobsRoot; // Setup default driver this.driver = this.use(config.default); this.logger.level = config.logLevel || logger.level; } use(queue) { if (!this.config.queues[queue]) { throw Error(`Queue not defined: "${String(queue)}"`); } return this.config.queues[queue](); } /** * Starts up given queue jobs execution * * @param queue Queue name to start */ async start(queue) { /** * Just log errors, but don't stop at any * In case of error, will keep queue process alive * Trying to execute next job in-line even after failure */ try { if (this.use(queue).pollingDelay) { /** * Will keep queue running and checking for jobs infinitely */ // eslint-disable-next-line no-constant-condition while (true) { await this.execute(); // Wait before next execution loop await new Promise((res) => setTimeout(() => res(true), this.use(queue).pollingDelay)); } } else { await this.execute(); } } catch (error) { // Check if it's needed in first place this.logger.error(error); } } /** * Executes next job in queue */ async execute() { let job = await this.driver.getNext(); // No job queued, continue with life if (!job) { this.logger.debug('No jobs in queue'); return; } this.logger.debug({ job }, 'Execution started'); /** * Dynamically import job class on the fly * Node stores all imported classes in-memory * so queue has to be restarted if there has been * any change to already imported job class */ let payload = superjson_1.default.parse(job.payload); let jobPath = `${this.jobsRoot}/${job.class_path}`; const JobClass = (await Promise.resolve(`${jobPath}`).then(s => __importStar(require(s)))).default; const jobClassInstance = new JobClass(...payload.data); /** * Wrap handler to try-catch * it's just to deal with execution failures * Other cases are handled in parent Ace command */ try { job.attempts++; await jobClassInstance.handle(); // After execution remove job from queue await this.driver.remove(job.id); } catch (error) { this.logger.error(error, 'Job execution failed'); /** * Check if job has depleted retries * if so, then mark it as failed */ if (job.attempts >= JobClass.retries) { this.logger.error(`Job ${job.id} failed for last time after ${JobClass.retries} retries`); await this.driver.markFailed(job); return; } await this.driver.reSchedule(job, JobClass.retryAfter); } this.logger.debug({ job }, 'Executed successfully'); } /** * Stores job to queue for future execution * * @param path Path to class file * @param payload Job payload * @param options Store options */ async store(path, payload, options) { return this.driver.store(path, payload, options); } } exports.QueueManager = QueueManager;