UNPKG

@imqueue/job

Version:

Simple job queue

297 lines (296 loc) 9.14 kB
/*! * Job Queue for @imqueue framework * * I'm Queue Software Project * Copyright (C) 2025 imqueue.com <support@imqueue.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * * If you want to use this code in a closed source (commercial) project, you can * purchase a proprietary commercial license. Please contact us at * <support@imqueue.com> to get commercial licensing options. */ import { ILogger, IMessageQueue } from '@imqueue/core'; /** * Job queues options */ export interface JobQueueOptions { /** * Name of the job queue. In worker/publisher mode worker and * publisher must share the same job queue name. * Mandatory. * * @type {string} */ name: string; /** * Connection params of the queue engine cluster (typically - * host and port). By default the broker is redis. * Optional. * * @default [{ host: "localhost", port: 6379 }] * @type {Array<{host: string, port: number}>} */ cluster?: { host: string; port: number; }[]; /** * Message queue username * * @type {string} */ username?: string; /** * Message queue password * * @type {string} */ password?: string; /** * Logger to be used for producing log and error messages. * Optional. * By default is console. * * @default console * @type {ILogger} */ logger?: ILogger; /** * Safe message delivery or not? When safe delivery is enabled (by default) * queue is processing jobs with guarantied job data delivery. If process * fails or dies - job data is re-queued for future processing by another * worker. * Optional. * * @default true * @type {boolean} */ safe?: boolean; /** * TTL in milliseconds of the job in worker queue during safe delivery. * If worker does not finish processing after this TTL - job is re-queued * for other workers to be processed. * Optional. * * @default 10000 * @type {number} */ safeLockTtl?: number; /** * Job queue prefix in queue broker. * Optional. * * @default "imq-job" * @type {string} */ prefix?: string; /** * Enables/disables verbose logging * * @default false * @type {boolean} */ verbose?: boolean; /** * Enables/disables extended verbose logging. The output may contain * sensitive information, so use it with caution. Does not work if a verbose * option is disabled. * * @default false * @type {boolean} */ verboseExtended?: boolean; } export interface JobQueuePopHandler<T> { /** * Handles popped from a queue job. If it throws error job will be * re-scheduled with the same delay as it was pushed into queue, * If it returns positive number it will be treated as new delay to * re-schedule message in the queue. Normally, if re-schedule is not needed * it should return nothing (undefined, void return). * If worker goes down during the job processing, job will be re-scheduled * after configured by options safeLockTtl. * * @example * ```typescript * // job logged and not re-scheduled (normal typical job processing) * queue.onPop(job => { * console.log(job); * }); * // job logged and re-schedule immediately * queue.onPop(job => { * console.log(job); * return 0; * }); * // job logged and not re-scheduled (normal typical job processing) * queue.onPop(job => { * console.log(job); * return -1; * }); * // job re-scheduled with the initial delay (job throws) * queue.on(job => { * throw new Error('Job error'); * }); * // job re-scheduled with new delay of 1 second * queue.onPop(job => { * console.log(job); * return 1000; // re-run after 1 second * }); * ``` * * @param {T} job * @return {Promise<number | void>} */ (job: T): number | void | Promise<number | void>; } export interface PushOptions { /** * Delay before message to be processed by workers */ delay?: number; /** * Time to live for message in queue in milliseconds */ ttl?: number; } export interface AnyJobQueue<T> { name: string; readonly logger: ILogger; start(): Promise<T>; stop(): Promise<T>; destroy(): Promise<void>; } export interface AnyJobQueueWorker<T, U> { onPop(handler: JobQueuePopHandler<U>): T; } export interface AnyJobQueuePublisher<T, U> { push(job: U, options?: PushOptions): T; } /** * Abstract job queue, handles base implementations of AnyJobQueue interface. */ export declare abstract class BaseJobQueue<T, U> implements AnyJobQueue<T> { protected options: JobQueueOptions; protected imq: IMessageQueue; protected handler: JobQueuePopHandler<U>; readonly logger: ILogger; protected constructor(options: JobQueueOptions); /** * Full name of this queue * * @type {string} */ get name(): string; /** * Starts processing job queue * * @return {Promise<T>} - this queue */ start(): Promise<T>; /** * Stops processing job queue * * @return {Promise<T>} - this queue */ stop(): Promise<T>; /** * Destroys job queue * * @return {Promise<void>} */ destroy(): Promise<void>; } /** * Implements simple scheduled job queue publisher. Job queue publisher is only * responsible for pushing queue messages. */ export declare class JobQueuePublisher<T> extends BaseJobQueue<JobQueuePublisher<T>, T> implements AnyJobQueuePublisher<JobQueuePublisher<T>, T> { /** * Constructor. Instantiates new JobQueue instance. * * @constructor * @param {JobQueueOptions} options */ constructor(options: JobQueueOptions); /** * Pushes new job to this queue * * @param {T} job - job data itself of user defined type * @param {PushOptions} options - push options, like delay and ttl for job * @return {JobQueue<T>} - this queue */ push(job: T, options?: PushOptions): JobQueuePublisher<T>; } /** * Implements simple scheduled job queue worker. Job queue worker is only * responsible for processing queue messages. */ export declare class JobQueueWorker<T> extends BaseJobQueue<JobQueueWorker<T>, T> implements AnyJobQueueWorker<JobQueueWorker<T>, T> { /** * Constructor. Instantiates new JobQueue instance. * * @constructor * @param {JobQueueOptions} options */ constructor(options: JobQueueOptions); /** * Sets up job handler, which is called when the job is popped from this * queue. * * @param {JobQueuePopHandler<T>} handler - job pop handler * @return {JobQueueWorker<T>} - this queue */ onPop(handler: JobQueuePopHandler<T>): JobQueueWorker<T>; } /** * Implements simple scheduled job queue. Job scheduling is optional. It may * process jobs immediately or after specified delay for particular job. * It also allows to define max lifetime of the job in a queue, after which * the job is removed from a queue. * Supports graceful shutdown, if TERM or SIGINT is sent to the process. */ export default class JobQueue<T> extends BaseJobQueue<JobQueue<T>, T> implements AnyJobQueueWorker<JobQueue<T>, T>, AnyJobQueuePublisher<JobQueue<T>, T> { /** * Constructor. Instantiates new JobQueue instance. * * @constructor * @param {JobQueueOptions} options */ constructor(options: JobQueueOptions); /** * Starts processing job queue. Throws if handler is not set before start. * * @throws {TypeError} * @return {Promise<T>} - this queue */ start(): Promise<JobQueue<T>>; /** * Pushes new job to this queue. Throws if handler is not set. * * @throws {TypeError} * @param {T} job - job data itself of user defined type * @param {PushOptions} options - push options, like delay and ttl for job * @return {JobQueue<T>} - this queue */ push(job: T, options?: PushOptions): JobQueue<T>; /** * Sets up job handler, which is called when the job is popped from this * queue. * * @param {JobQueuePopHandler<T>} handler - job pop handler * @return {JobQueue<T>} - this queue */ onPop(handler: JobQueuePopHandler<T>): JobQueue<T>; }