@boringnode/queue 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -361
- package/build/{chunk-RIXMQXYJ.js → chunk-LI2ZMCNO.js} +14 -1
- package/build/chunk-LI2ZMCNO.js.map +1 -0
- package/build/{chunk-NPQKBCCY.js → chunk-PBGPIFI5.js} +15 -1
- package/build/chunk-PBGPIFI5.js.map +1 -0
- package/build/{index-C0Xg6F4E.d.ts → index-BzPIqdx3.d.ts} +260 -3
- package/build/index.d.ts +6 -2
- package/build/index.js +218 -11
- package/build/index.js.map +1 -1
- package/build/src/contracts/adapter.d.ts +1 -1
- package/build/src/drivers/knex_adapter.d.ts +6 -3
- package/build/src/drivers/knex_adapter.js +90 -8
- package/build/src/drivers/knex_adapter.js.map +1 -1
- package/build/src/drivers/redis_adapter.d.ts +6 -3
- package/build/src/drivers/redis_adapter.js +335 -94
- package/build/src/drivers/redis_adapter.js.map +1 -1
- package/build/src/drivers/sync_adapter.d.ts +6 -3
- package/build/src/drivers/sync_adapter.js +14 -3
- package/build/src/drivers/sync_adapter.js.map +1 -1
- package/build/src/types/index.d.ts +1 -1
- package/build/src/types/main.d.ts +1 -1
- package/package.json +3 -2
- package/build/chunk-NPQKBCCY.js.map +0 -1
- package/build/chunk-RIXMQXYJ.js.map +0 -1
|
@@ -179,6 +179,7 @@ var QueueManagerSingleton = class {
|
|
|
179
179
|
#adapters = {};
|
|
180
180
|
#adapterInstances = /* @__PURE__ */ new Map();
|
|
181
181
|
#globalRetryConfig;
|
|
182
|
+
#globalJobOptions;
|
|
182
183
|
#queueConfigs = /* @__PURE__ */ new Map();
|
|
183
184
|
#logger = consoleLogger;
|
|
184
185
|
#jobFactory;
|
|
@@ -213,6 +214,7 @@ var QueueManagerSingleton = class {
|
|
|
213
214
|
this.#defaultAdapter = config.default;
|
|
214
215
|
this.#adapters = config.adapters;
|
|
215
216
|
this.#globalRetryConfig = config.retry;
|
|
217
|
+
this.#globalJobOptions = config.defaultJobOptions;
|
|
216
218
|
this.#logger = config.logger ?? consoleLogger;
|
|
217
219
|
this.#jobFactory = config.jobFactory;
|
|
218
220
|
if (config.queues) {
|
|
@@ -309,6 +311,17 @@ var QueueManagerSingleton = class {
|
|
|
309
311
|
getJobFactory() {
|
|
310
312
|
return this.#jobFactory;
|
|
311
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Get the merged job options for a job (priority: job > queue > global).
|
|
316
|
+
*/
|
|
317
|
+
getMergedJobOptions(queue, jobOptions) {
|
|
318
|
+
const queueConfig = this.#queueConfigs.get(queue);
|
|
319
|
+
const queueJobOptions = queueConfig?.defaultJobOptions;
|
|
320
|
+
return {
|
|
321
|
+
removeOnComplete: jobOptions?.removeOnComplete ?? queueJobOptions?.removeOnComplete ?? this.#globalJobOptions?.removeOnComplete,
|
|
322
|
+
removeOnFail: jobOptions?.removeOnFail ?? queueJobOptions?.removeOnFail ?? this.#globalJobOptions?.removeOnFail
|
|
323
|
+
};
|
|
324
|
+
}
|
|
312
325
|
#validateConfig(config) {
|
|
313
326
|
if (!config.adapters || Object.keys(config.adapters).length === 0) {
|
|
314
327
|
throw new E_CONFIGURATION_ERROR(["At least one adapter must be configured"]);
|
|
@@ -355,4 +368,4 @@ export {
|
|
|
355
368
|
Locator,
|
|
356
369
|
QueueManager
|
|
357
370
|
};
|
|
358
|
-
//# sourceMappingURL=chunk-
|
|
371
|
+
//# sourceMappingURL=chunk-LI2ZMCNO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/debug.ts","../src/locator.ts","../src/logger.ts","../src/queue_manager.ts"],"sourcesContent":["import { debuglog } from 'node:util'\n\nexport default debuglog('boringnode:queue')\n","import { Job } from './job.js'\nimport * as errors from './exceptions.js'\nimport type { JobClass } from './types/main.js'\nimport debug from './debug.js'\nimport { glob } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\n/**\n * Job class registry.\n *\n * The Locator maintains a mapping of job names to their classes,\n * allowing the Worker to instantiate jobs by name when processing.\n *\n * Jobs are typically registered automatically via `QueueManager.init()`\n * using the `locations` config option, but can also be registered manually.\n *\n * @example\n * ```typescript\n * import { Locator } from '@boringnode/queue'\n * import SendEmailJob from './jobs/send_email_job.js'\n *\n * // Manual registration\n * Locator.register('SendEmailJob', SendEmailJob)\n *\n * // Auto-registration via glob (used by QueueManager.init)\n * await Locator.registerFromGlob(['./jobs/**\\/*.js'])\n *\n * // Retrieve a job class\n * const JobClass = Locator.getOrThrow('SendEmailJob')\n * ```\n */\nclass LocatorSingleton {\n #registry = new Map<string, JobClass>()\n\n /**\n * Register a job class with a given name.\n *\n * @param name - The job name (usually the class name)\n * @param JobClass - The job class constructor\n *\n * @example\n * ```typescript\n * Locator.register('SendEmailJob', SendEmailJob)\n * ```\n */\n register<T extends Job>(name: string, JobClass: JobClass<T>) {\n debug('registering job: %s', name)\n\n this.#registry.set(name, JobClass)\n }\n\n /**\n * Auto-register job classes from files matching glob patterns.\n *\n * Each file should have a default export that is a Job class.\n * The class name is used as the registration name.\n *\n * @param patterns - Glob patterns to match job files\n * @returns Number of jobs successfully registered\n *\n * @example\n * ```typescript\n * const count = await Locator.registerFromGlob([\n * './jobs/**\\/*.js',\n * './app/jobs/**\\/*.ts'\n * ])\n * console.log(`Registered ${count} jobs`)\n * ```\n */\n async registerFromGlob(patterns: string[]): Promise<number> {\n let registered = 0\n\n for (const pattern of patterns) {\n debug('registering jobs from glob pattern: %s', pattern)\n for await (const file of glob(pattern)) {\n debug('found job file: %s', file)\n\n try {\n const absolutePath = resolve(file)\n const module = await import(`file://${absolutePath}`)\n const JobClass = module.default as JobClass\n\n if (JobClass && typeof JobClass === 'function') {\n const jobName = JobClass.options?.name || JobClass.name\n this.register(jobName, JobClass)\n registered++\n }\n } catch (error) {\n console.warn(`Failed to load job from ${file}:`, error)\n }\n }\n }\n\n return registered\n }\n\n /**\n * Get a job class by name.\n *\n * @param name - The job name to look up\n * @returns The job class, or undefined if not found\n *\n * @example\n * ```typescript\n * const JobClass = Locator.get('SendEmailJob')\n * if (JobClass) {\n * const instance = new JobClass(payload)\n * }\n * ```\n */\n get<T extends Job = Job>(name: string): JobClass<T> | undefined {\n return this.#registry.get(name) as JobClass<T> | undefined\n }\n\n /**\n * Get a job class by name, throwing if not found.\n *\n * @param name - The job name to look up\n * @returns The job class\n * @throws {E_JOB_NOT_FOUND} If the job is not registered\n *\n * @example\n * ```typescript\n * const JobClass = Locator.getOrThrow('SendEmailJob')\n * const instance = new JobClass(payload)\n * ```\n */\n getOrThrow<T extends Job = Job>(name: string): JobClass<T> {\n const JobClass = this.get<T>(name)\n\n if (!JobClass) {\n throw new errors.E_JOB_NOT_FOUND([name])\n }\n\n return JobClass\n }\n\n /**\n * Remove all registered jobs.\n *\n * Primarily useful for testing.\n */\n clear(): void {\n this.#registry.clear()\n }\n}\n\n/** Global job class registry singleton */\nexport const Locator = new LocatorSingleton()\n","export interface LogObject {\n [key: string]: unknown\n}\n\nexport interface ErrorObject extends LogObject {\n err?: Error\n}\n\nexport interface Logger {\n trace(msg: string): void\n trace(obj: LogObject, msg: string): void\n\n debug(msg: string): void\n debug(obj: LogObject, msg: string): void\n\n info(msg: string): void\n info(obj: LogObject, msg: string): void\n\n warn(msg: string): void\n warn(obj: LogObject, msg: string): void\n\n error(msg: string): void\n error(obj: ErrorObject, msg: string): void\n\n child(obj: LogObject): Logger\n}\n\n/**\n * A simple logger that writes to console.\n */\nclass ConsoleLogger implements Logger {\n #prefix: string\n\n constructor(prefix: string = 'queue') {\n this.#prefix = prefix\n }\n\n #format(level: string, msgOrObj: string | LogObject, msg?: string): [string, LogObject?] {\n const prefix = `[${this.#prefix}] ${level}:`\n\n if (typeof msgOrObj === 'object') {\n return [`${prefix} ${msg}`, msgOrObj]\n }\n\n return [`${prefix} ${msgOrObj}`]\n }\n\n trace(msg: string): void\n trace(obj: LogObject, msg: string): void\n trace(msgOrObj: string | LogObject, msg?: string): void {\n const [message, obj] = this.#format('TRACE', msgOrObj, msg)\n\n if (obj) {\n return console.log(message, obj)\n }\n\n console.log(message)\n }\n\n debug(msg: string): void\n debug(obj: LogObject, msg: string): void\n debug(msgOrObj: string | LogObject, msg?: string): void {\n const [message, obj] = this.#format('DEBUG', msgOrObj, msg)\n\n if (obj) {\n return console.log(message, obj)\n }\n\n console.log(message)\n }\n\n info(msg: string): void\n info(obj: LogObject, msg: string): void\n info(msgOrObj: string | LogObject, msg?: string): void {\n const [message, obj] = this.#format('INFO', msgOrObj, msg)\n\n if (obj) {\n return console.log(message, obj)\n }\n\n console.log(message)\n }\n\n warn(msg: string): void\n warn(obj: LogObject, msg: string): void\n warn(msgOrObj: string | LogObject, msg?: string): void {\n const [message, obj] = this.#format('WARN', msgOrObj, msg)\n\n if (obj) {\n return console.warn(message, obj)\n }\n\n console.warn(message)\n }\n\n error(msg: string): void\n error(obj: ErrorObject, msg: string): void\n error(msgOrObj: string | ErrorObject, msg?: string): void {\n const [message, obj] = this.#format('ERROR', msgOrObj, msg)\n\n if (obj) {\n return console.error(message, obj)\n }\n\n console.error(message)\n }\n\n child(obj: LogObject): Logger {\n const childPrefix = obj.pkg ? String(obj.pkg) : this.#prefix\n return new ConsoleLogger(childPrefix)\n }\n}\n\nexport const consoleLogger = new ConsoleLogger()\n","import * as errors from './exceptions.js'\nimport debug from './debug.js'\nimport { Locator } from './locator.js'\nimport { consoleLogger, type Logger } from './logger.js'\nimport type { Adapter } from './contracts/adapter.js'\nimport type {\n AdapterFactory,\n JobFactory,\n JobOptions,\n QueueConfig,\n QueueManagerConfig,\n RetryConfig,\n} from './types/main.js'\n\n/**\n * Central configuration and adapter management for the queue system.\n *\n * The QueueManager is responsible for:\n * - Initializing adapters and job registration\n * - Providing adapter instances to workers and dispatchers\n * - Managing retry configuration across global, queue, and job levels\n *\n * @example\n * ```typescript\n * import { QueueManager, redis } from '@boringnode/queue'\n *\n * await QueueManager.init({\n * default: 'redis',\n * adapters: {\n * redis: redis({ host: 'localhost' }),\n * },\n * locations: ['./jobs/**\\/*.js'],\n * retry: {\n * maxRetries: 3,\n * backoff: exponentialBackoff(),\n * },\n * })\n *\n * // Get the default adapter\n * const adapter = QueueManager.use()\n *\n * // Clean up when done\n * await QueueManager.destroy()\n * ```\n */\nclass QueueManagerSingleton {\n #initialized = false\n #defaultAdapter!: string\n #adapters: Record<string, AdapterFactory> = {}\n #adapterInstances: Map<string, Adapter> = new Map()\n #globalRetryConfig?: RetryConfig\n #globalJobOptions?: JobOptions\n #queueConfigs: Map<string, QueueConfig> = new Map()\n #logger: Logger = consoleLogger\n #jobFactory?: JobFactory\n\n /**\n * Initialize the queue system with the given configuration.\n *\n * This must be called before using the queue system. It:\n * - Validates the configuration\n * - Registers adapters\n * - Auto-discovers and registers job classes from `locations`\n *\n * @param config - The queue configuration\n * @returns This instance for chaining\n * @throws {E_CONFIGURATION_ERROR} If the configuration is invalid\n *\n * @example\n * ```typescript\n * await QueueManager.init({\n * default: 'redis',\n * adapters: {\n * redis: redis(),\n * postgres: knex(pgConfig),\n * },\n * locations: ['./jobs/**\\/*.js'],\n * })\n * ```\n */\n async init(config: QueueManagerConfig) {\n debug('initializing queue manager with config: %O', config)\n\n this.#validateConfig(config)\n\n this.#adapterInstances.clear()\n\n this.#defaultAdapter = config.default\n this.#adapters = config.adapters\n this.#globalRetryConfig = config.retry\n this.#globalJobOptions = config.defaultJobOptions\n this.#logger = config.logger ?? consoleLogger\n this.#jobFactory = config.jobFactory\n\n if (config.queues) {\n for (const [queue, queueConfig] of Object.entries(config.queues)) {\n this.#queueConfigs.set(queue, queueConfig as QueueConfig)\n }\n }\n\n if (config.locations && config.locations.length > 0) {\n const registered = await Locator.registerFromGlob(config.locations)\n\n if (registered === 0) {\n this.#logger.warn(\n `No jobs found for locations: ${config.locations.join(', ')}. ` +\n 'Verify your glob patterns match your job files.'\n )\n }\n }\n\n this.#initialized = true\n\n return this\n }\n\n /**\n * Get an adapter instance by name.\n *\n * Adapter instances are cached and reused. If no name is provided,\n * the default adapter is returned.\n *\n * @param adapter - Adapter name (optional, defaults to the default adapter)\n * @returns The adapter instance\n * @throws {E_QUEUE_NOT_INITIALIZED} If `init()` hasn't been called\n * @throws {E_CONFIGURATION_ERROR} If the adapter is not registered\n * @throws {E_ADAPTER_INIT_ERROR} If the adapter factory throws\n *\n * @example\n * ```typescript\n * // Get default adapter\n * const adapter = QueueManager.use()\n *\n * // Get specific adapter\n * const redisAdapter = QueueManager.use('redis')\n * ```\n */\n use(adapter?: string): Adapter {\n if (!this.#initialized) {\n throw new errors.E_QUEUE_NOT_INITIALIZED()\n }\n\n if (!adapter) {\n adapter = this.#defaultAdapter\n }\n\n // Return cached instance if exists\n const cached = this.#adapterInstances.get(adapter)\n if (cached) {\n return cached\n }\n\n const adapterFactory = this.#adapters[adapter]\n\n if (!adapterFactory) {\n throw new errors.E_CONFIGURATION_ERROR([`Adapter \"${adapter}\" is not registered`])\n }\n\n debug('using adapter \"%s\"', adapter)\n\n try {\n const instance = adapterFactory()\n this.#adapterInstances.set(adapter, instance)\n return instance\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new errors.E_ADAPTER_INIT_ERROR([adapter, message])\n }\n }\n\n /**\n * Get the merged retry configuration for a job.\n *\n * Configuration is merged with priority: job > queue > global.\n * This allows specific jobs or queues to override global defaults.\n *\n * @param queue - The queue name\n * @param jobRetryConfig - Optional job-level retry config\n * @returns The merged retry configuration\n *\n * @example\n * ```typescript\n * // Global: maxRetries=3, Queue: maxRetries=5, Job: maxRetries=1\n * // Result: maxRetries=1 (job wins)\n * const config = QueueManager.getMergedRetryConfig('emails', { maxRetries: 1 })\n * ```\n */\n getMergedRetryConfig(queue: string, jobRetryConfig?: RetryConfig): RetryConfig {\n const queueConfig = this.#queueConfigs.get(queue)\n const queueRetryConfig = queueConfig?.retry || {}\n\n let maxRetries =\n jobRetryConfig?.maxRetries ||\n queueRetryConfig.maxRetries ||\n this.#globalRetryConfig?.maxRetries ||\n 0\n\n let backoff =\n jobRetryConfig?.backoff || queueRetryConfig.backoff || this.#globalRetryConfig?.backoff\n\n return { maxRetries, backoff }\n }\n\n /**\n * Get the configured job factory for custom instantiation.\n *\n * @returns The job factory function, or undefined if not configured\n */\n getJobFactory(): JobFactory | undefined {\n return this.#jobFactory\n }\n\n /**\n * Get the merged job options for a job (priority: job > queue > global).\n */\n getMergedJobOptions(queue: string, jobOptions?: JobOptions): JobOptions {\n const queueConfig = this.#queueConfigs.get(queue)\n const queueJobOptions = queueConfig?.defaultJobOptions\n\n return {\n removeOnComplete:\n jobOptions?.removeOnComplete ??\n queueJobOptions?.removeOnComplete ??\n this.#globalJobOptions?.removeOnComplete,\n removeOnFail:\n jobOptions?.removeOnFail ??\n queueJobOptions?.removeOnFail ??\n this.#globalJobOptions?.removeOnFail,\n }\n }\n\n #validateConfig(config: QueueManagerConfig): void {\n if (!config.adapters || Object.keys(config.adapters).length === 0) {\n throw new errors.E_CONFIGURATION_ERROR(['At least one adapter must be configured'])\n }\n\n if (!config.default) {\n throw new errors.E_CONFIGURATION_ERROR(['Default adapter must be specified'])\n }\n\n if (!config.adapters[config.default]) {\n throw new errors.E_CONFIGURATION_ERROR([\n `Default adapter \"${config.default}\" not found in adapters configuration`,\n ])\n }\n\n for (const [name, factory] of Object.entries(config.adapters)) {\n if (typeof factory !== 'function') {\n throw new errors.E_CONFIGURATION_ERROR([`Adapter \"${name}\" must be a factory function`])\n }\n }\n }\n\n /**\n * Clean up all adapter instances and reset state.\n *\n * Call this when shutting down the application or when\n * you need to reinitialize with a new configuration.\n *\n * @example\n * ```typescript\n * // On application shutdown\n * await QueueManager.destroy()\n * ```\n */\n async destroy() {\n for (const [name, adapter] of this.#adapterInstances) {\n debug('destroying adapter \"%s\"', name)\n await adapter.destroy()\n }\n this.#adapterInstances.clear()\n this.#initialized = false\n }\n}\n\n/** Global queue manager singleton */\nexport const QueueManager = new QueueManagerSingleton()\n"],"mappings":"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","names":[]}
|
|
@@ -5,6 +5,19 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/utils.ts
|
|
7
7
|
import { parse as parseDuration } from "@lukeed/ms";
|
|
8
|
+
function resolveRetention(retention) {
|
|
9
|
+
if (retention === void 0 || retention === true) {
|
|
10
|
+
return { keep: false, maxAge: 0, maxCount: 0 };
|
|
11
|
+
}
|
|
12
|
+
if (retention === false) {
|
|
13
|
+
return { keep: true, maxAge: 0, maxCount: 0 };
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
keep: true,
|
|
17
|
+
maxAge: retention.age ? parse(retention.age) : 0,
|
|
18
|
+
maxCount: retention.count ?? 0
|
|
19
|
+
};
|
|
20
|
+
}
|
|
8
21
|
function parse(duration) {
|
|
9
22
|
if (typeof duration === "number") {
|
|
10
23
|
return duration;
|
|
@@ -20,7 +33,8 @@ function calculateScore(priority, timestamp) {
|
|
|
20
33
|
}
|
|
21
34
|
|
|
22
35
|
export {
|
|
36
|
+
resolveRetention,
|
|
23
37
|
parse,
|
|
24
38
|
calculateScore
|
|
25
39
|
};
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-PBGPIFI5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { parse as parseDuration } from '@lukeed/ms'\nimport type { Duration, JobRetention } from './types/main.js'\nimport * as errors from './exceptions.js'\nimport { PRIORITY_SCORE_MULTIPLIER } from './constants.js'\n\nexport interface ResolvedRetention {\n keep: boolean\n maxAge: number\n maxCount: number\n}\n\nexport function resolveRetention(retention?: JobRetention): ResolvedRetention {\n if (retention === undefined || retention === true) {\n return { keep: false, maxAge: 0, maxCount: 0 }\n }\n\n if (retention === false) {\n return { keep: true, maxAge: 0, maxCount: 0 }\n }\n\n return {\n keep: true,\n maxAge: retention.age ? parse(retention.age) : 0,\n maxCount: retention.count ?? 0,\n }\n}\n\nexport function parse(duration: Duration): number {\n if (typeof duration === 'number') {\n return duration\n }\n\n const milliseconds = parseDuration(duration)\n\n if (typeof milliseconds === 'undefined') {\n throw new errors.E_INVALID_DURATION_EXPRESSION([duration])\n }\n\n return milliseconds\n}\n\n/**\n * Calculate the score for job ordering in the queue.\n * Lower scores are processed first.\n *\n * @param priority - Job priority (1-10, lower = higher priority)\n * @param timestamp - Timestamp in milliseconds\n * @returns Score for queue ordering\n */\nexport function calculateScore(priority: number, timestamp: number): number {\n return priority * PRIORITY_SCORE_MULTIPLIER + timestamp\n}\n"],"mappings":";;;;;;AAAA,SAAS,SAAS,qBAAqB;AAWhC,SAAS,iBAAiB,WAA6C;AAC5E,MAAI,cAAc,UAAa,cAAc,MAAM;AACjD,WAAO,EAAE,MAAM,OAAO,QAAQ,GAAG,UAAU,EAAE;AAAA,EAC/C;AAEA,MAAI,cAAc,OAAO;AACvB,WAAO,EAAE,MAAM,MAAM,QAAQ,GAAG,UAAU,EAAE;AAAA,EAC9C;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,UAAU,MAAM,MAAM,UAAU,GAAG,IAAI;AAAA,IAC/C,UAAU,UAAU,SAAS;AAAA,EAC/B;AACF;AAEO,SAAS,MAAM,UAA4B;AAChD,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,cAAc,QAAQ;AAE3C,MAAI,OAAO,iBAAiB,aAAa;AACvC,UAAM,IAAW,8BAA8B,CAAC,QAAQ,CAAC;AAAA,EAC3D;AAEA,SAAO;AACT;AAUO,SAAS,eAAe,UAAkB,WAA2B;AAC1E,SAAO,WAAW,4BAA4B;AAChD;","names":[]}
|
|
@@ -198,6 +198,21 @@ interface Logger {
|
|
|
198
198
|
* ```
|
|
199
199
|
*/
|
|
200
200
|
type Duration = number | string;
|
|
201
|
+
/**
|
|
202
|
+
* Retention policy for completed/failed jobs.
|
|
203
|
+
*
|
|
204
|
+
* - `true` (default): Remove job immediately
|
|
205
|
+
* - `false`: Keep job in history indefinitely
|
|
206
|
+
* - `{ age?, count? }`: Keep with pruning by age and/or count
|
|
207
|
+
*/
|
|
208
|
+
type JobRetention = boolean | {
|
|
209
|
+
age?: Duration;
|
|
210
|
+
count?: number;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Possible statuses for a job in the queue.
|
|
214
|
+
*/
|
|
215
|
+
type JobStatus = 'pending' | 'active' | 'delayed' | 'completed' | 'failed';
|
|
201
216
|
/**
|
|
202
217
|
* Result returned when dispatching a job.
|
|
203
218
|
*
|
|
@@ -211,6 +226,19 @@ interface DispatchResult {
|
|
|
211
226
|
/** Unique identifier for this specific job instance */
|
|
212
227
|
jobId: string;
|
|
213
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Result returned when dispatching multiple jobs at once.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* const { jobIds } = await SendEmailJob.dispatchMany(payloads)
|
|
235
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
interface DispatchManyResult {
|
|
239
|
+
/** Unique identifiers for all dispatched job instances */
|
|
240
|
+
jobIds: string[];
|
|
241
|
+
}
|
|
214
242
|
/**
|
|
215
243
|
* Internal representation of a job in the queue.
|
|
216
244
|
*
|
|
@@ -248,6 +276,34 @@ interface JobData {
|
|
|
248
276
|
* Number of times this job was recovered from stalled state.
|
|
249
277
|
*/
|
|
250
278
|
stalledCount?: number;
|
|
279
|
+
/**
|
|
280
|
+
* Optional group identifier for organizing related jobs.
|
|
281
|
+
*
|
|
282
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
283
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
284
|
+
* or bulk exports.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
|
|
289
|
+
* .group('newsletter-jan-2025')
|
|
290
|
+
* .run()
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
groupId?: string;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Record of a job's current state, including history for completed/failed jobs.
|
|
297
|
+
*/
|
|
298
|
+
interface JobRecord {
|
|
299
|
+
/** Current status of the job */
|
|
300
|
+
status: JobStatus;
|
|
301
|
+
/** Original job data */
|
|
302
|
+
data: JobData;
|
|
303
|
+
/** Timestamp when the job finished (for completed/failed jobs) */
|
|
304
|
+
finishedAt?: number;
|
|
305
|
+
/** Error message (for failed jobs) */
|
|
306
|
+
error?: string;
|
|
251
307
|
}
|
|
252
308
|
/**
|
|
253
309
|
* Static options for a Job class.
|
|
@@ -314,6 +370,8 @@ interface JobOptions {
|
|
|
314
370
|
* @default true
|
|
315
371
|
*/
|
|
316
372
|
failOnTimeout?: boolean;
|
|
373
|
+
removeOnComplete?: JobRetention;
|
|
374
|
+
removeOnFail?: JobRetention;
|
|
317
375
|
}
|
|
318
376
|
/**
|
|
319
377
|
* Context information available to a job during execution.
|
|
@@ -395,6 +453,7 @@ interface BackoffConfig {
|
|
|
395
453
|
interface QueueConfig {
|
|
396
454
|
adapter?: string;
|
|
397
455
|
retry?: any;
|
|
456
|
+
defaultJobOptions?: JobOptions;
|
|
398
457
|
}
|
|
399
458
|
interface WorkerConfig {
|
|
400
459
|
/**
|
|
@@ -541,6 +600,7 @@ interface QueueManagerConfig {
|
|
|
541
600
|
default: string;
|
|
542
601
|
adapters: Record<string, AdapterFactory>;
|
|
543
602
|
retry?: RetryConfig;
|
|
603
|
+
defaultJobOptions?: JobOptions;
|
|
544
604
|
queues?: Record<string, QueueConfig>;
|
|
545
605
|
worker?: WorkerConfig;
|
|
546
606
|
locations?: string[];
|
|
@@ -634,16 +694,18 @@ interface Adapter {
|
|
|
634
694
|
*
|
|
635
695
|
* @param jobId - The job ID to complete
|
|
636
696
|
* @param queue - The queue the job belongs to
|
|
697
|
+
* @param removeOnComplete - Optional retention policy for completed jobs
|
|
637
698
|
*/
|
|
638
|
-
completeJob(jobId: string, queue: string): Promise<void>;
|
|
699
|
+
completeJob(jobId: string, queue: string, removeOnComplete?: JobRetention): Promise<void>;
|
|
639
700
|
/**
|
|
640
701
|
* Mark a job as failed permanently and remove it from the queue.
|
|
641
702
|
*
|
|
642
703
|
* @param jobId - The job ID to fail
|
|
643
704
|
* @param queue - The queue the job belongs to
|
|
644
705
|
* @param error - Optional error that caused the failure
|
|
706
|
+
* @param removeOnFail - Optional retention policy for failed jobs
|
|
645
707
|
*/
|
|
646
|
-
failJob(jobId: string, queue: string, error?: Error): Promise<void>;
|
|
708
|
+
failJob(jobId: string, queue: string, error?: Error, removeOnFail?: JobRetention): Promise<void>;
|
|
647
709
|
/**
|
|
648
710
|
* Retry a job by moving it back to pending with incremented attempts.
|
|
649
711
|
*
|
|
@@ -652,6 +714,14 @@ interface Adapter {
|
|
|
652
714
|
* @param retryAt - Optional future date to delay the retry
|
|
653
715
|
*/
|
|
654
716
|
retryJob(jobId: string, queue: string, retryAt?: Date): Promise<void>;
|
|
717
|
+
/**
|
|
718
|
+
* Get a job record by id.
|
|
719
|
+
*
|
|
720
|
+
* @param jobId - The job ID to retrieve
|
|
721
|
+
* @param queue - The queue the job belongs to
|
|
722
|
+
* @returns The job record, or null if not found
|
|
723
|
+
*/
|
|
724
|
+
getJob(jobId: string, queue: string): Promise<JobRecord | null>;
|
|
655
725
|
/**
|
|
656
726
|
* Push a job to the default queue for immediate processing.
|
|
657
727
|
*
|
|
@@ -680,6 +750,25 @@ interface Adapter {
|
|
|
680
750
|
* @param delay - Delay in milliseconds before the job becomes available
|
|
681
751
|
*/
|
|
682
752
|
pushLaterOn(queue: string, jobData: JobData, delay: number): Promise<void>;
|
|
753
|
+
/**
|
|
754
|
+
* Push multiple jobs to the default queue for immediate processing.
|
|
755
|
+
*
|
|
756
|
+
* This is more efficient than calling push() multiple times as it
|
|
757
|
+
* batches the operations (e.g., Redis pipeline, SQL batch insert).
|
|
758
|
+
*
|
|
759
|
+
* @param jobs - Array of job data to push
|
|
760
|
+
*/
|
|
761
|
+
pushMany(jobs: JobData[]): Promise<void>;
|
|
762
|
+
/**
|
|
763
|
+
* Push multiple jobs to a specific queue for immediate processing.
|
|
764
|
+
*
|
|
765
|
+
* This is more efficient than calling pushOn() multiple times as it
|
|
766
|
+
* batches the operations (e.g., Redis pipeline, SQL batch insert).
|
|
767
|
+
*
|
|
768
|
+
* @param queue - The queue name to push to
|
|
769
|
+
* @param jobs - Array of job data to push
|
|
770
|
+
*/
|
|
771
|
+
pushManyOn(queue: string, jobs: JobData[]): Promise<void>;
|
|
683
772
|
/**
|
|
684
773
|
* Get the number of pending jobs in the default queue.
|
|
685
774
|
*
|
|
@@ -842,6 +931,25 @@ declare class JobDispatcher<T> {
|
|
|
842
931
|
* ```
|
|
843
932
|
*/
|
|
844
933
|
priority(priority: number): this;
|
|
934
|
+
/**
|
|
935
|
+
* Assign this job to a group.
|
|
936
|
+
*
|
|
937
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
938
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
939
|
+
* or bulk exports.
|
|
940
|
+
*
|
|
941
|
+
* @param groupId - Group identifier
|
|
942
|
+
* @returns This dispatcher for chaining
|
|
943
|
+
*
|
|
944
|
+
* @example
|
|
945
|
+
* ```typescript
|
|
946
|
+
* // Group newsletter jobs together
|
|
947
|
+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
|
|
948
|
+
* .group('newsletter-jan-2025')
|
|
949
|
+
* .run()
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
group(groupId: string): this;
|
|
845
953
|
/**
|
|
846
954
|
* Use a specific adapter for this job.
|
|
847
955
|
*
|
|
@@ -882,6 +990,127 @@ declare class JobDispatcher<T> {
|
|
|
882
990
|
then(onFulfilled?: (value: DispatchResult) => any, onRejected?: (reason: any) => any): Promise<any>;
|
|
883
991
|
}
|
|
884
992
|
|
|
993
|
+
/**
|
|
994
|
+
* Fluent builder for dispatching multiple jobs to the queue in a single batch.
|
|
995
|
+
*
|
|
996
|
+
* Provides a chainable API for configuring job options before dispatch.
|
|
997
|
+
* Usually created via `Job.dispatchMany()` rather than directly.
|
|
998
|
+
*
|
|
999
|
+
* ```
|
|
1000
|
+
* Job.dispatchMany(payloads)
|
|
1001
|
+
* .toQueue('emails') // optional: target queue
|
|
1002
|
+
* .priority(1) // optional: 1-10, lower = higher priority
|
|
1003
|
+
* .group('batch-123') // optional: group all jobs together
|
|
1004
|
+
* .with('redis') // optional: specific adapter
|
|
1005
|
+
* .run() // dispatch all jobs
|
|
1006
|
+
* ```
|
|
1007
|
+
*
|
|
1008
|
+
* @typeParam T - The payload type for these jobs
|
|
1009
|
+
*
|
|
1010
|
+
* @example
|
|
1011
|
+
* ```typescript
|
|
1012
|
+
* // Batch dispatch for newsletter
|
|
1013
|
+
* const { jobIds } = await SendEmailJob.dispatchMany([
|
|
1014
|
+
* { to: 'user1@example.com', subject: 'Newsletter' },
|
|
1015
|
+
* { to: 'user2@example.com', subject: 'Newsletter' },
|
|
1016
|
+
* ])
|
|
1017
|
+
* .group('newsletter-jan-2025')
|
|
1018
|
+
* .toQueue('emails')
|
|
1019
|
+
* .run()
|
|
1020
|
+
*
|
|
1021
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1022
|
+
* ```
|
|
1023
|
+
*/
|
|
1024
|
+
declare class JobBatchDispatcher<T> {
|
|
1025
|
+
#private;
|
|
1026
|
+
/**
|
|
1027
|
+
* Create a new batch job dispatcher.
|
|
1028
|
+
*
|
|
1029
|
+
* @param name - The job class name (used to locate the class at runtime)
|
|
1030
|
+
* @param payloads - Array of data to pass to each job
|
|
1031
|
+
*/
|
|
1032
|
+
constructor(name: string, payloads: T[]);
|
|
1033
|
+
/**
|
|
1034
|
+
* Set the target queue for all jobs.
|
|
1035
|
+
*
|
|
1036
|
+
* @param queue - Queue name (default: 'default')
|
|
1037
|
+
* @returns This dispatcher for chaining
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```typescript
|
|
1041
|
+
* await SendEmailJob.dispatchMany(payloads).toQueue('emails')
|
|
1042
|
+
* ```
|
|
1043
|
+
*/
|
|
1044
|
+
toQueue(queue: string): this;
|
|
1045
|
+
/**
|
|
1046
|
+
* Set the priority for all jobs.
|
|
1047
|
+
*
|
|
1048
|
+
* Lower numbers = higher priority. Jobs with lower priority values
|
|
1049
|
+
* are processed before jobs with higher values.
|
|
1050
|
+
*
|
|
1051
|
+
* @param priority - Priority level (1-10, default: 5)
|
|
1052
|
+
* @returns This dispatcher for chaining
|
|
1053
|
+
*
|
|
1054
|
+
* @example
|
|
1055
|
+
* ```typescript
|
|
1056
|
+
* await UrgentJob.dispatchMany(payloads).priority(1)
|
|
1057
|
+
* ```
|
|
1058
|
+
*/
|
|
1059
|
+
priority(priority: number): this;
|
|
1060
|
+
/**
|
|
1061
|
+
* Assign all jobs to a group.
|
|
1062
|
+
*
|
|
1063
|
+
* Jobs with the same groupId can be filtered and displayed together
|
|
1064
|
+
* in monitoring UIs. Useful for batch operations like newsletters
|
|
1065
|
+
* or bulk exports.
|
|
1066
|
+
*
|
|
1067
|
+
* @param groupId - Group identifier
|
|
1068
|
+
* @returns This dispatcher for chaining
|
|
1069
|
+
*
|
|
1070
|
+
* @example
|
|
1071
|
+
* ```typescript
|
|
1072
|
+
* await SendEmailJob.dispatchMany(recipients)
|
|
1073
|
+
* .group('newsletter-jan-2025')
|
|
1074
|
+
* .run()
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
group(groupId: string): this;
|
|
1078
|
+
/**
|
|
1079
|
+
* Use a specific adapter for these jobs.
|
|
1080
|
+
*
|
|
1081
|
+
* @param adapter - Adapter name or factory function
|
|
1082
|
+
* @returns This dispatcher for chaining
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
* ```typescript
|
|
1086
|
+
* await Job.dispatchMany(payloads).with('redis')
|
|
1087
|
+
* ```
|
|
1088
|
+
*/
|
|
1089
|
+
with(adapter: string | (() => Adapter)): this;
|
|
1090
|
+
/**
|
|
1091
|
+
* Dispatch all jobs to the queue.
|
|
1092
|
+
*
|
|
1093
|
+
* @returns A DispatchManyResult containing all jobIds
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* const { jobIds } = await SendEmailJob.dispatchMany(payloads).run()
|
|
1098
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1099
|
+
* ```
|
|
1100
|
+
*/
|
|
1101
|
+
run(): Promise<DispatchManyResult>;
|
|
1102
|
+
/**
|
|
1103
|
+
* Thenable implementation for auto-dispatch when awaited.
|
|
1104
|
+
*
|
|
1105
|
+
* Allows `await Job.dispatchMany(payloads)` without explicit `.run()`.
|
|
1106
|
+
*
|
|
1107
|
+
* @param onFulfilled - Success callback
|
|
1108
|
+
* @param onRejected - Error callback
|
|
1109
|
+
* @returns Promise resolving to the DispatchManyResult
|
|
1110
|
+
*/
|
|
1111
|
+
then(onFulfilled?: (value: DispatchManyResult) => any, onRejected?: (reason: any) => any): Promise<any>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
885
1114
|
/**
|
|
886
1115
|
* Fluent builder for creating job schedules.
|
|
887
1116
|
*
|
|
@@ -1103,6 +1332,34 @@ declare abstract class Job<Payload = any> {
|
|
|
1103
1332
|
* ```
|
|
1104
1333
|
*/
|
|
1105
1334
|
static dispatch<T extends Job>(this: new (...args: any[]) => T, payload: T extends Job<infer P> ? P : never): JobDispatcher<T extends Job<infer P> ? P : never>;
|
|
1335
|
+
/**
|
|
1336
|
+
* Dispatch multiple jobs to the queue in a single batch.
|
|
1337
|
+
*
|
|
1338
|
+
* Returns a JobBatchDispatcher for fluent configuration before dispatching.
|
|
1339
|
+
* The jobs are not actually dispatched until `.run()` is called or the
|
|
1340
|
+
* dispatcher is awaited.
|
|
1341
|
+
*
|
|
1342
|
+
* This is more efficient than calling `dispatch()` multiple times as it
|
|
1343
|
+
* uses batched operations (e.g., Redis pipeline, SQL batch insert).
|
|
1344
|
+
*
|
|
1345
|
+
* @param payloads - Array of data to pass to each job
|
|
1346
|
+
* @returns A JobBatchDispatcher for fluent configuration
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* ```typescript
|
|
1350
|
+
* // Batch dispatch for newsletter
|
|
1351
|
+
* const { jobIds } = await SendEmailJob.dispatchMany([
|
|
1352
|
+
* { to: 'user1@example.com', subject: 'Newsletter' },
|
|
1353
|
+
* { to: 'user2@example.com', subject: 'Newsletter' },
|
|
1354
|
+
* ])
|
|
1355
|
+
* .group('newsletter-jan-2025')
|
|
1356
|
+
* .toQueue('emails')
|
|
1357
|
+
* .run()
|
|
1358
|
+
*
|
|
1359
|
+
* console.log(`Dispatched ${jobIds.length} jobs`)
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
static dispatchMany<T extends Job>(this: new (...args: any[]) => T, payloads: (T extends Job<infer P> ? P : never)[]): JobBatchDispatcher<T extends Job<infer P> ? P : never>;
|
|
1106
1363
|
/**
|
|
1107
1364
|
* Create a schedule for this job.
|
|
1108
1365
|
*
|
|
@@ -1171,4 +1428,4 @@ declare abstract class Job<Payload = any> {
|
|
|
1171
1428
|
failed?(error: Error): Promise<void>;
|
|
1172
1429
|
}
|
|
1173
1430
|
|
|
1174
|
-
export { type Adapter as A, type BackoffStrategy as B, type Duration as D, type
|
|
1431
|
+
export { type Adapter as A, type BackoffStrategy as B, type Duration as D, type JobRetention as J, type Logger as L, type QueueManagerConfig as Q, type RetryConfig as R, type ScheduleConfig as S, type WorkerCycle as W, type AcquiredJob as a, type JobRecord as b, type JobData as c, type ScheduleData as d, type ScheduleListOptions as e, type JobFactory as f, type JobOptions as g, Job as h, type JobClass as i, type ScheduleStatus as j, ScheduleBuilder as k, JobBatchDispatcher as l, customBackoff as m, linearBackoff as n, exponentialBackoff as o, fixedBackoff as p, type JobStatus as q, type DispatchResult as r, type DispatchManyResult as s, type JobContext as t, type BackoffConfig as u, type QueueConfig as v, type WorkerConfig as w, type AdapterFactory as x, type ScheduleResult as y };
|
package/build/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig,
|
|
2
|
-
export {
|
|
1
|
+
import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig, f as JobFactory, g as JobOptions, h as Job, i as JobClass, d as ScheduleData, j as ScheduleStatus, e as ScheduleListOptions } from './index-BzPIqdx3.js';
|
|
2
|
+
export { l as JobBatchDispatcher, k as ScheduleBuilder, m as customBackoff, o as exponentialBackoff, p as fixedBackoff, n as linearBackoff } from './index-BzPIqdx3.js';
|
|
3
3
|
import * as _poppinss_utils from '@poppinss/utils';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -232,6 +232,10 @@ declare class QueueManagerSingleton {
|
|
|
232
232
|
* @returns The job factory function, or undefined if not configured
|
|
233
233
|
*/
|
|
234
234
|
getJobFactory(): JobFactory | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* Get the merged job options for a job (priority: job > queue > global).
|
|
237
|
+
*/
|
|
238
|
+
getMergedJobOptions(queue: string, jobOptions?: JobOptions): JobOptions;
|
|
235
239
|
/**
|
|
236
240
|
* Clean up all adapter instances and reset state.
|
|
237
241
|
*
|