@boringnode/queue 0.1.0 → 0.2.0

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 CHANGED
@@ -39,15 +39,13 @@ Create a job by extending the `Job` class:
39
39
 
40
40
  ```typescript
41
41
  import { Job } from '@boringnode/queue'
42
- import type { JobContext, JobOptions } from '@boringnode/queue/types'
42
+ import type { JobOptions } from '@boringnode/queue/types'
43
43
 
44
44
  interface SendEmailPayload {
45
45
  to: string
46
46
  }
47
47
 
48
48
  export default class SendEmailJob extends Job<SendEmailPayload> {
49
- static readonly jobName = 'SendEmailJob'
50
-
51
49
  static options: JobOptions = {
52
50
  queue: 'email',
53
51
  }
@@ -58,6 +56,10 @@ export default class SendEmailJob extends Job<SendEmailPayload> {
58
56
  }
59
57
  ```
60
58
 
59
+ > **Note**: The job name defaults to the class name (`SendEmailJob`). You can override it with `name: 'CustomName'` in options if needed.
60
+ >
61
+ > **Warning**: If you minify your code in production, class names may be mangled. In that case, always specify `name` explicitly in your job options.
62
+
61
63
  ### 2. Configure the Queue Manager
62
64
 
63
65
  ```typescript
@@ -239,9 +241,9 @@ Schedule jobs to run in the future:
239
241
  ```typescript
240
242
  // Various time formats
241
243
  await SendEmailJob.dispatch(payload).in('30s') // 30 seconds
242
- await SendEmailJob.dispatch(payload).in('5m') // 5 minutes
243
- await SendEmailJob.dispatch(payload).in('2h') // 2 hours
244
- await SendEmailJob.dispatch(payload).in('1d') // 1 day
244
+ await SendEmailJob.dispatch(payload).in('5m') // 5 minutes
245
+ await SendEmailJob.dispatch(payload).in('2h') // 2 hours
246
+ await SendEmailJob.dispatch(payload).in('1d') // 1 day
245
247
  ```
246
248
 
247
249
  ## Priority
@@ -250,8 +252,6 @@ Jobs with lower priority numbers are processed first:
250
252
 
251
253
  ```typescript
252
254
  export default class UrgentJob extends Job<Payload> {
253
- static readonly jobName = 'UrgentJob'
254
-
255
255
  static options: JobOptions = {
256
256
  priority: 1, // Processed before default priority (5)
257
257
  }
@@ -270,8 +270,6 @@ Configure automatic retries with backoff strategies:
270
270
  import { exponentialBackoff, linearBackoff, fixedBackoff } from '@boringnode/queue'
271
271
 
272
272
  export default class ReliableJob extends Job<Payload> {
273
- static readonly jobName = 'ReliableJob'
274
-
275
273
  static options: JobOptions = {
276
274
  maxRetries: 5,
277
275
  retry: {
@@ -303,8 +301,6 @@ Set a maximum execution time for jobs:
303
301
 
304
302
  ```typescript
305
303
  export default class LimitedJob extends Job<Payload> {
306
- static readonly jobName = 'LimitedJob'
307
-
308
304
  static options: JobOptions = {
309
305
  timeout: '30s', // Maximum execution time
310
306
  failOnTimeout: false, // Retry on timeout (default)
@@ -326,19 +322,42 @@ const config = {
326
322
  }
327
323
  ```
328
324
 
325
+ ### Handling Timeout Gracefully
326
+
327
+ Jobs have access to an abort signal via `this.signal` to handle timeouts gracefully:
328
+
329
+ ```typescript
330
+ export default class LongRunningJob extends Job<Payload> {
331
+ static options: JobOptions = {
332
+ timeout: '30s',
333
+ }
334
+
335
+ async execute(): Promise<void> {
336
+ for (const item of this.payload.items) {
337
+ // Check if the job has been aborted
338
+ if (this.signal?.aborted) {
339
+ throw new Error('Job timed out')
340
+ }
341
+
342
+ await this.processItem(item)
343
+ }
344
+ }
345
+
346
+ private async processItem(item: any): Promise<void> {
347
+ // Pass the signal to fetch or other async operations
348
+ await fetch(item.url, { signal: this.signal })
349
+ }
350
+ }
351
+ ```
352
+
329
353
  ## Job Context
330
354
 
331
355
  Every job has access to execution context via `this.context`. This provides metadata about the current job execution:
332
356
 
333
357
  ```typescript
334
358
  import { Job } from '@boringnode/queue'
335
- import type { JobContext } from '@boringnode/queue'
336
359
 
337
360
  export default class MyJob extends Job<Payload> {
338
- constructor(payload: Payload, context: JobContext) {
339
- super(payload, context)
340
- }
341
-
342
361
  async execute(): Promise<void> {
343
362
  console.log(`Job ID: ${this.context.jobId}`)
344
363
  console.log(`Attempt: ${this.context.attempt}`) // 1, 2, 3...
@@ -367,7 +386,7 @@ export default class MyJob extends Job<Payload> {
367
386
 
368
387
  ## Dependency Injection
369
388
 
370
- Use the `jobFactory` option to integrate with IoC containers for dependency injection. This allows your jobs to receive injected services in their constructor.
389
+ Use the `jobFactory` option to integrate with IoC containers for dependency injection. The constructor is reserved for injecting dependencies - payload and context are provided separately by the worker.
371
390
 
372
391
  ```typescript
373
392
  import { QueueManager } from '@boringnode/queue'
@@ -375,9 +394,9 @@ import { QueueManager } from '@boringnode/queue'
375
394
  await QueueManager.init({
376
395
  default: 'redis',
377
396
  adapters: { redis: redis(connection) },
378
- jobFactory: async (JobClass, payload, context) => {
397
+ jobFactory: async (JobClass) => {
379
398
  // Use your IoC container to instantiate jobs
380
- return app.container.make(JobClass, [payload, context])
399
+ return app.container.make(JobClass)
381
400
  },
382
401
  })
383
402
  ```
@@ -386,7 +405,6 @@ Example with injected dependencies:
386
405
 
387
406
  ```typescript
388
407
  import { Job } from '@boringnode/queue'
389
- import type { JobContext } from '@boringnode/queue'
390
408
 
391
409
  interface SendEmailPayload {
392
410
  to: string
@@ -394,15 +412,11 @@ interface SendEmailPayload {
394
412
  }
395
413
 
396
414
  export default class SendEmailJob extends Job<SendEmailPayload> {
397
- static readonly jobName = 'SendEmailJob'
398
-
399
415
  constructor(
400
- payload: SendEmailPayload,
401
- context: JobContext,
402
416
  private mailer: MailerService, // Injected by IoC container
403
417
  private logger: Logger // Injected by IoC container
404
418
  ) {
405
- super(payload, context)
419
+ super()
406
420
  }
407
421
 
408
422
  async execute(): Promise<void> {
@@ -412,7 +426,7 @@ export default class SendEmailJob extends Job<SendEmailPayload> {
412
426
  }
413
427
  ```
414
428
 
415
- Without a `jobFactory`, jobs are instantiated with `new JobClass(payload, context)`.
429
+ Without a `jobFactory`, jobs are instantiated with `new JobClass()`.
416
430
 
417
431
  ## Scheduled Jobs
418
432
 
@@ -518,10 +532,11 @@ const config = {
518
532
  Jobs must:
519
533
 
520
534
  - Extend the `Job` class
521
- - Have a static `jobName` property
522
535
  - Implement the `execute` method
523
536
  - Be exported as default
524
537
 
538
+ The job name is automatically derived from the class name, or can be explicitly set via `static options = { name: 'CustomName' }`.
539
+
525
540
  ## Logging
526
541
 
527
542
  You can pass a logger to the queue manager for debugging or monitoring. The logger must be compatible with the [pino](https://github.com/pinojs/pino) interface.
@@ -57,8 +57,9 @@ var LocatorSingleton = class {
57
57
  const absolutePath = resolve(file);
58
58
  const module = await import(`file://${absolutePath}`);
59
59
  const JobClass = module.default;
60
- if (JobClass && typeof JobClass === "function" && JobClass.name) {
61
- this.register(JobClass.name, JobClass);
60
+ if (JobClass && typeof JobClass === "function") {
61
+ const jobName = JobClass.options?.name || JobClass.name;
62
+ this.register(jobName, JobClass);
62
63
  registered++;
63
64
  }
64
65
  } catch (error) {
@@ -354,4 +355,4 @@ export {
354
355
  Locator,
355
356
  QueueManager
356
357
  };
357
- //# sourceMappingURL=chunk-US7THLSZ.js.map
358
+ //# sourceMappingURL=chunk-RIXMQXYJ.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 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 #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.#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 #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":[]}
@@ -185,6 +185,18 @@ interface Logger {
185
185
  child(obj: LogObject): Logger;
186
186
  }
187
187
 
188
+ /**
189
+ * Duration can be specified as milliseconds (number) or as a human-readable string.
190
+ *
191
+ * Supported string formats: '1s', '5m', '2h', '1d', etc.
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * const timeout: Duration = '30s' // 30 seconds
196
+ * const delay: Duration = 5000 // 5000 milliseconds
197
+ * const interval: Duration = '5m' // 5 minutes
198
+ * ```
199
+ */
188
200
  type Duration = number | string;
189
201
  /**
190
202
  * Result returned when dispatching a job.
@@ -199,22 +211,108 @@ interface DispatchResult {
199
211
  /** Unique identifier for this specific job instance */
200
212
  jobId: string;
201
213
  }
214
+ /**
215
+ * Internal representation of a job in the queue.
216
+ *
217
+ * This is used by adapters to store and retrieve job data.
218
+ * Not typically used directly by application code.
219
+ */
202
220
  interface JobData {
221
+ /**
222
+ * Unique identifier for this job.
223
+ */
203
224
  id: string;
225
+ /**
226
+ * Job class name.
227
+ */
204
228
  name: string;
229
+ /**
230
+ * Serialized job payload.
231
+ */
205
232
  payload: any;
233
+ /**
234
+ * Number of execution attempts so far.
235
+ */
206
236
  attempts: number;
237
+ /**
238
+ * Job priority (lower = higher priority).
239
+ *
240
+ * @default 0
241
+ */
207
242
  priority?: number;
243
+ /**
244
+ * When to retry this job next (for failed jobs).
245
+ */
208
246
  nextRetryAt?: Date;
247
+ /**
248
+ * Number of times this job was recovered from stalled state.
249
+ */
209
250
  stalledCount?: number;
210
251
  }
252
+ /**
253
+ * Static options for a Job class.
254
+ *
255
+ * Define these as a static property on your Job class to configure
256
+ * default behavior for all instances.
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * class SendEmailJob extends Job<EmailPayload> {
261
+ * static options: JobOptions = {
262
+ * name: 'SendEmailJob',
263
+ * queue: 'emails',
264
+ * maxRetries: 3,
265
+ * timeout: '30s',
266
+ * }
267
+ * }
268
+ * ```
269
+ */
211
270
  interface JobOptions {
271
+ /**
272
+ * Unique name for this job class.
273
+ *
274
+ * Used to identify the job when dispatching and processing.
275
+ *
276
+ * @default constructor.name
277
+ */
278
+ name?: string;
279
+ /**
280
+ * Queue name for this job.
281
+ *
282
+ * @default 'default'
283
+ */
212
284
  queue?: string;
285
+ /**
286
+ * Adapter name or factory to use for this job.
287
+ */
213
288
  adapter?: string | (() => Adapter);
289
+ /**
290
+ * Maximum retry attempts before permanent failure.
291
+ *
292
+ * @default 3
293
+ */
214
294
  maxRetries?: number;
295
+ /**
296
+ * Job priority (lower = higher priority).
297
+ *
298
+ * @default 0
299
+ */
215
300
  priority?: number;
301
+ /**
302
+ * Retry configuration (backoff strategy, delays, etc.).
303
+ */
216
304
  retry?: RetryConfig;
305
+ /**
306
+ * Maximum execution time before timeout.
307
+ *
308
+ * @default undefined (no timeout)
309
+ */
217
310
  timeout?: Duration;
311
+ /**
312
+ * Whether to mark job as failed on timeout.
313
+ *
314
+ * @default true
315
+ */
218
316
  failOnTimeout?: boolean;
219
317
  }
220
318
  /**
@@ -249,34 +347,39 @@ interface JobContext {
249
347
  /** Number of times this job has been recovered from stalled state */
250
348
  stalledCount: number;
251
349
  }
252
- type JobClass<T extends Job = Job> = (new (payload: any, context: JobContext) => T) & {
350
+ /**
351
+ * Type representing a Job class constructor.
352
+ *
353
+ * The constructor accepts any arguments for dependency injection.
354
+ * Payload and context are provided separately via `$hydrate()`.
355
+ */
356
+ type JobClass<T extends Job = Job> = (new (...args: any[]) => T) & {
253
357
  options?: JobOptions;
254
358
  };
255
359
  /**
256
360
  * Factory function for custom job instantiation.
257
361
  *
258
362
  * Use this to integrate with IoC containers for dependency injection.
259
- * The factory receives the job class, payload, and context, and must return
260
- * a job instance (or a Promise that resolves to one).
363
+ * The factory receives only the job class and should return an instance
364
+ * with all dependencies injected. The worker will call `$hydrate()` separately
365
+ * to provide payload, context, and signal.
261
366
  *
262
367
  * @param JobClass - The job class to instantiate
263
- * @param payload - The payload data for the job
264
- * @param context - The job execution context (jobId, attempt, queue, etc.)
265
368
  * @returns The job instance, or a Promise resolving to the instance
266
369
  *
267
370
  * @example
268
371
  * ```typescript
269
372
  * // With AdonisJS IoC container
270
- * const worker = new Worker({
271
- * worker: {
272
- * jobFactory: async (JobClass, payload, context) => {
273
- * return app.container.make(JobClass, [payload, context])
274
- * }
373
+ * await QueueManager.init({
374
+ * default: 'redis',
375
+ * adapters: { redis: redis() },
376
+ * jobFactory: async (JobClass) => {
377
+ * return app.container.make(JobClass)
275
378
  * }
276
379
  * })
277
380
  * ```
278
381
  */
279
- type JobFactory = (JobClass: JobClass, payload: any, context: JobContext) => Job | Promise<Job>;
382
+ type JobFactory = (JobClass: JobClass) => Job | Promise<Job>;
280
383
  interface RetryConfig {
281
384
  maxRetries?: number;
282
385
  backoff?: () => BackoffStrategy$1;
@@ -370,7 +473,7 @@ interface ScheduleConfig {
370
473
  /** Optional ID for the schedule (UUID if not set). Used for upsert. */
371
474
  id?: string;
372
475
  /** Job class name */
373
- jobName: string;
476
+ name: string;
374
477
  /** Job payload */
375
478
  payload: any;
376
479
  /** Cron expression (mutually exclusive with everyMs) */
@@ -394,7 +497,7 @@ interface ScheduleData {
394
497
  /** Unique identifier */
395
498
  id: string;
396
499
  /** Job class name */
397
- jobName: string;
500
+ name: string;
398
501
  /** Job payload */
399
502
  payload: any;
400
503
  /** Cron expression (null if using interval) */
@@ -446,15 +549,17 @@ interface QueueManagerConfig {
446
549
  * Custom factory function for job instantiation.
447
550
  *
448
551
  * Use this to integrate with IoC containers for dependency injection.
449
- * When provided, this factory is called instead of `new JobClass(payload, context)`.
552
+ * When provided, this factory is called instead of `new JobClass()`.
553
+ * The worker will call `$hydrate()` on the returned instance to provide
554
+ * payload, context, and signal.
450
555
  *
451
556
  * @example
452
557
  * ```typescript
453
558
  * await QueueManager.init({
454
559
  * default: 'redis',
455
560
  * adapters: { redis: redis() },
456
- * jobFactory: async (JobClass, payload, context) => {
457
- * return app.container.make(JobClass, [payload, context])
561
+ * jobFactory: async (JobClass) => {
562
+ * return app.container.make(JobClass)
458
563
  * }
459
564
  * })
460
565
  * ```
@@ -797,7 +902,7 @@ declare class JobDispatcher<T> {
797
902
  */
798
903
  declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
799
904
  #private;
800
- constructor(jobName: string, payload: any);
905
+ constructor(name: string, payload: any);
801
906
  /**
802
907
  * Set a custom schedule ID.
803
908
  * If not specified, defaults to the job name.
@@ -854,12 +959,14 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
854
959
  * Extend this class to create your own jobs. Each job must implement
855
960
  * the `execute()` method which contains the job's business logic.
856
961
  *
962
+ * The constructor is reserved for dependency injection. Payload and context
963
+ * are provided separately via the `$hydrate()` method (called by the worker).
964
+ *
857
965
  * @typeParam Payload - The type of data this job receives
858
966
  *
859
967
  * @example
860
968
  * ```typescript
861
969
  * import { Job } from '@boringnode/queue'
862
- * import type { JobContext } from '@boringnode/queue'
863
970
  *
864
971
  * interface SendEmailPayload {
865
972
  * to: string
@@ -873,13 +980,14 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
873
980
  * maxRetries: 3,
874
981
  * }
875
982
  *
876
- * constructor(payload: SendEmailPayload, context: JobContext) {
877
- * super(payload, context)
983
+ * // Constructor is for dependency injection only
984
+ * constructor(private mailer: MailerService) {
985
+ * super()
878
986
  * }
879
987
  *
880
988
  * async execute() {
881
989
  * console.log(`Attempt ${this.context.attempt} for job ${this.context.jobId}`)
882
- * await sendEmail(this.payload.to, this.payload.subject, this.payload.body)
990
+ * await this.mailer.send(this.payload.to, this.payload.subject, this.payload.body)
883
991
  * }
884
992
  *
885
993
  * async failed(error: Error) {
@@ -890,9 +998,38 @@ declare class ScheduleBuilder implements PromiseLike<ScheduleResult> {
890
998
  */
891
999
  declare abstract class Job<Payload = any> {
892
1000
  #private;
893
- /** Static options for this job class (queue, retries, timeout, etc.) */
1001
+ /**
1002
+ * Static options for this job class.
1003
+ *
1004
+ * Override this property in subclasses to configure job behavior
1005
+ * such as queue name, retry policy, timeout, and more.
1006
+ *
1007
+ * @example
1008
+ * ```typescript
1009
+ * class SendEmailJob extends Job<SendEmailPayload> {
1010
+ * static options = {
1011
+ * queue: 'emails',
1012
+ * maxRetries: 3,
1013
+ * timeout: '30s',
1014
+ * }
1015
+ * }
1016
+ * ```
1017
+ */
894
1018
  static options: JobOptions;
895
- /** The payload data passed to this job instance */
1019
+ /**
1020
+ * The payload data passed to this job instance.
1021
+ *
1022
+ * Contains the data provided when the job was dispatched.
1023
+ * Available after the job has been hydrated by the worker.
1024
+ *
1025
+ * @example
1026
+ * ```typescript
1027
+ * async execute() {
1028
+ * const { to, subject, body } = this.payload
1029
+ * await sendEmail(to, subject, body)
1030
+ * }
1031
+ * ```
1032
+ */
896
1033
  get payload(): Payload;
897
1034
  /**
898
1035
  * Context information for the current job execution.
@@ -912,12 +1049,36 @@ declare abstract class Job<Payload = any> {
912
1049
  */
913
1050
  get context(): JobContext;
914
1051
  /**
915
- * Create a new job instance.
1052
+ * The abort signal for timeout handling.
1053
+ *
1054
+ * Check `signal.aborted` in long-running operations to handle timeouts gracefully.
1055
+ *
1056
+ * @example
1057
+ * ```typescript
1058
+ * async execute() {
1059
+ * for (const item of this.payload.items) {
1060
+ * if (this.signal?.aborted) {
1061
+ * throw new Error('Job timed out')
1062
+ * }
1063
+ * await processItem(item)
1064
+ * }
1065
+ * }
1066
+ * ```
1067
+ */
1068
+ get signal(): AbortSignal | undefined;
1069
+ /**
1070
+ * Hydrate the job with payload, context, and optional abort signal.
1071
+ *
1072
+ * This method is called by the worker after instantiation to provide
1073
+ * the job's runtime data. It should not be called directly by user code.
916
1074
  *
917
1075
  * @param payload - The data to be processed by this job
918
- * @param context - The job execution context (provided by the worker)
1076
+ * @param context - The job execution context
1077
+ * @param signal - Optional abort signal for timeout handling
1078
+ *
1079
+ * @internal
919
1080
  */
920
- constructor(payload: Payload, context: JobContext);
1081
+ $hydrate(payload: Payload, context: JobContext, signal?: AbortSignal): void;
921
1082
  /**
922
1083
  * Dispatch this job to the queue.
923
1084
  *
@@ -941,7 +1102,7 @@ declare abstract class Job<Payload = any> {
941
1102
  * .run()
942
1103
  * ```
943
1104
  */
944
- static dispatch<T extends Job>(this: new (payload: any, context: JobContext) => T, payload: T extends Job<infer P> ? P : never): JobDispatcher<T extends Job<infer P> ? P : never>;
1105
+ 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>;
945
1106
  /**
946
1107
  * Create a schedule for this job.
947
1108
  *
@@ -967,22 +1128,22 @@ declare abstract class Job<Payload = any> {
967
1128
  * .run()
968
1129
  * ```
969
1130
  */
970
- static schedule<T extends Job>(this: new (payload: any, context: JobContext) => T, payload: T extends Job<infer P> ? P : never): ScheduleBuilder;
1131
+ static schedule<T extends Job>(this: new (...args: any[]) => T, payload: T extends Job<infer P> ? P : never): ScheduleBuilder;
971
1132
  /**
972
1133
  * Execute the job's business logic.
973
1134
  *
974
1135
  * This method is called by the worker when processing the job.
975
1136
  * Implement your job's logic here.
976
1137
  *
977
- * @param signal - Optional AbortSignal for timeout handling.
978
- * Check `signal.aborted` for long-running operations.
1138
+ * For timeout handling, use `this.signal` which is available after hydration.
1139
+ *
979
1140
  * @throws Any error thrown will trigger retry logic (if configured)
980
1141
  *
981
1142
  * @example
982
1143
  * ```typescript
983
- * async execute(signal?: AbortSignal) {
1144
+ * async execute() {
984
1145
  * for (const item of this.payload.items) {
985
- * if (signal?.aborted) {
1146
+ * if (this.signal?.aborted) {
986
1147
  * throw new Error('Job timed out')
987
1148
  * }
988
1149
  * await processItem(item)
@@ -990,7 +1151,7 @@ declare abstract class Job<Payload = any> {
990
1151
  * }
991
1152
  * ```
992
1153
  */
993
- abstract execute(signal?: AbortSignal): Promise<void>;
1154
+ abstract execute(): Promise<void>;
994
1155
  /**
995
1156
  * Called when the job has permanently failed (after all retries exhausted).
996
1157
  *
package/build/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig, d as JobFactory, e as Job, f as JobClass, b as ScheduleData, g as ScheduleStatus, c as ScheduleListOptions } from './index-2Ng_OpVK.js';
2
- export { h as ScheduleBuilder, i as customBackoff, j as exponentialBackoff, k as fixedBackoff, l as linearBackoff } from './index-2Ng_OpVK.js';
1
+ import { Q as QueueManagerConfig, W as WorkerCycle, A as Adapter, R as RetryConfig, d as JobFactory, e as Job, f as JobClass, b as ScheduleData, g as ScheduleStatus, c as ScheduleListOptions } from './index-C0Xg6F4E.js';
2
+ export { h as ScheduleBuilder, i as customBackoff, j as exponentialBackoff, k as fixedBackoff, l as linearBackoff } from './index-C0Xg6F4E.js';
3
3
  import * as _poppinss_utils from '@poppinss/utils';
4
4
 
5
5
  /**
@@ -368,7 +368,7 @@ declare class Schedule {
368
368
  #private;
369
369
  constructor(data: ScheduleData);
370
370
  get id(): string;
371
- get jobName(): string;
371
+ get name(): string;
372
372
  get payload(): any;
373
373
  get cronExpression(): string | null;
374
374
  get everyMs(): number | null;