@boringnode/queue 0.0.1-alpha.3 → 0.1.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
@@ -1,5 +1,15 @@
1
1
  # @boringnode/queue
2
2
 
3
+ <div align="center">
4
+
5
+ [![typescript-image]][typescript-url]
6
+ [![gh-workflow-image]][gh-workflow-url]
7
+ [![npm-image]][npm-url]
8
+ [![npm-download-image]][npm-download-url]
9
+ [![license-image]][license-url]
10
+
11
+ </div>
12
+
3
13
  A simple and efficient queue system for Node.js applications. Built for simplicity and ease of use, `@boringnode/queue` allows you to dispatch background jobs and process them asynchronously with support for multiple queue adapters.
4
14
 
5
15
  ## Installation
@@ -19,6 +29,7 @@ npm install @boringnode/queue
19
29
  - **Priority Queues**: Process high-priority jobs first
20
30
  - **Retry with Backoff**: Automatic retries with exponential, linear, or fixed backoff strategies
21
31
  - **Job Timeout**: Automatically fail or retry jobs that exceed a time limit
32
+ - **Scheduled Jobs**: Cron-based or interval-based job scheduling with pause/resume support
22
33
 
23
34
  ## Quick Start
24
35
 
@@ -28,7 +39,7 @@ Create a job by extending the `Job` class:
28
39
 
29
40
  ```typescript
30
41
  import { Job } from '@boringnode/queue'
31
- import type { JobOptions } from '@boringnode/queue/types/main'
42
+ import type { JobContext, JobOptions } from '@boringnode/queue/types'
32
43
 
33
44
  interface SendEmailPayload {
34
45
  to: string
@@ -42,7 +53,7 @@ export default class SendEmailJob extends Job<SendEmailPayload> {
42
53
  }
43
54
 
44
55
  async execute(): Promise<void> {
45
- console.log(`Sending email to: ${this.payload.to}`)
56
+ console.log(`[Attempt ${this.context.attempt}] Sending email to: ${this.payload.to}`)
46
57
  }
47
58
  }
48
59
  ```
@@ -72,7 +83,7 @@ const config = {
72
83
 
73
84
  worker: {
74
85
  concurrency: 5,
75
- pollingInterval: '10ms',
86
+ idleDelay: '2s',
76
87
  },
77
88
 
78
89
  locations: ['./app/jobs/**/*.ts'],
@@ -121,7 +132,7 @@ interface QueueManagerConfig {
121
132
  // Worker configuration
122
133
  worker: {
123
134
  concurrency: number
124
- pollingInterval: string
135
+ idleDelay: Duration
125
136
  }
126
137
 
127
138
  // Job discovery locations
@@ -227,10 +238,10 @@ Schedule jobs to run in the future:
227
238
 
228
239
  ```typescript
229
240
  // Various time formats
230
- await SendEmailJob.dispatch(payload).in('30s') // 30 seconds
231
- await SendEmailJob.dispatch(payload).in('5m') // 5 minutes
232
- await SendEmailJob.dispatch(payload).in('2h') // 2 hours
233
- await SendEmailJob.dispatch(payload).in('1d') // 1 day
241
+ 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
234
245
  ```
235
246
 
236
247
  ## Priority
@@ -242,7 +253,7 @@ export default class UrgentJob extends Job<Payload> {
242
253
  static readonly jobName = 'UrgentJob'
243
254
 
244
255
  static options: JobOptions = {
245
- priority: 1, // Processed before default priority (5)
256
+ priority: 1, // Processed before default priority (5)
246
257
  }
247
258
 
248
259
  async execute(): Promise<void> {
@@ -264,12 +275,13 @@ export default class ReliableJob extends Job<Payload> {
264
275
  static options: JobOptions = {
265
276
  maxRetries: 5,
266
277
  retry: {
267
- backoff: () => exponentialBackoff({
268
- baseDelay: '1s',
269
- maxDelay: '1m',
270
- multiplier: 2,
271
- jitter: true,
272
- }),
278
+ backoff: () =>
279
+ exponentialBackoff({
280
+ baseDelay: '1s',
281
+ maxDelay: '1m',
282
+ multiplier: 2,
283
+ jitter: true,
284
+ }),
273
285
  },
274
286
  }
275
287
 
@@ -294,7 +306,7 @@ export default class LimitedJob extends Job<Payload> {
294
306
  static readonly jobName = 'LimitedJob'
295
307
 
296
308
  static options: JobOptions = {
297
- timeout: '30s', // Maximum execution time
309
+ timeout: '30s', // Maximum execution time
298
310
  failOnTimeout: false, // Retry on timeout (default)
299
311
  }
300
312
 
@@ -309,48 +321,245 @@ You can also set a global timeout in the worker configuration:
309
321
  ```typescript
310
322
  const config = {
311
323
  worker: {
312
- timeout: '1m', // Default timeout for all jobs
324
+ timeout: '1m', // Default timeout for all jobs
313
325
  },
314
326
  }
315
327
  ```
316
328
 
329
+ ## Job Context
330
+
331
+ Every job has access to execution context via `this.context`. This provides metadata about the current job execution:
332
+
333
+ ```typescript
334
+ import { Job } from '@boringnode/queue'
335
+ import type { JobContext } from '@boringnode/queue'
336
+
337
+ export default class MyJob extends Job<Payload> {
338
+ constructor(payload: Payload, context: JobContext) {
339
+ super(payload, context)
340
+ }
341
+
342
+ async execute(): Promise<void> {
343
+ console.log(`Job ID: ${this.context.jobId}`)
344
+ console.log(`Attempt: ${this.context.attempt}`) // 1, 2, 3...
345
+ console.log(`Queue: ${this.context.queue}`)
346
+ console.log(`Priority: ${this.context.priority}`)
347
+ console.log(`Acquired at: ${this.context.acquiredAt}`)
348
+
349
+ if (this.context.attempt > 1) {
350
+ console.log('This is a retry!')
351
+ }
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### Context Properties
357
+
358
+ | Property | Type | Description |
359
+ |----------------|--------|-------------------------------------------------|
360
+ | `jobId` | string | Unique identifier for this job |
361
+ | `name` | string | Job class name |
362
+ | `attempt` | number | Current attempt number (1-based) |
363
+ | `queue` | string | Queue name this job is being processed from |
364
+ | `priority` | number | Job priority (lower = higher priority) |
365
+ | `acquiredAt` | Date | When this job was acquired by the worker |
366
+ | `stalledCount` | number | Times this job was recovered from stalled state |
367
+
368
+ ## Dependency Injection
369
+
370
+ Use the `jobFactory` option to integrate with IoC containers for dependency injection. This allows your jobs to receive injected services in their constructor.
371
+
372
+ ```typescript
373
+ import { QueueManager } from '@boringnode/queue'
374
+
375
+ await QueueManager.init({
376
+ default: 'redis',
377
+ adapters: { redis: redis(connection) },
378
+ jobFactory: async (JobClass, payload, context) => {
379
+ // Use your IoC container to instantiate jobs
380
+ return app.container.make(JobClass, [payload, context])
381
+ },
382
+ })
383
+ ```
384
+
385
+ Example with injected dependencies:
386
+
387
+ ```typescript
388
+ import { Job } from '@boringnode/queue'
389
+ import type { JobContext } from '@boringnode/queue'
390
+
391
+ interface SendEmailPayload {
392
+ to: string
393
+ subject: string
394
+ }
395
+
396
+ export default class SendEmailJob extends Job<SendEmailPayload> {
397
+ static readonly jobName = 'SendEmailJob'
398
+
399
+ constructor(
400
+ payload: SendEmailPayload,
401
+ context: JobContext,
402
+ private mailer: MailerService, // Injected by IoC container
403
+ private logger: Logger // Injected by IoC container
404
+ ) {
405
+ super(payload, context)
406
+ }
407
+
408
+ async execute(): Promise<void> {
409
+ this.logger.info(`[Attempt ${this.context.attempt}] Sending email to ${this.payload.to}`)
410
+ await this.mailer.send(this.payload)
411
+ }
412
+ }
413
+ ```
414
+
415
+ Without a `jobFactory`, jobs are instantiated with `new JobClass(payload, context)`.
416
+
417
+ ## Scheduled Jobs
418
+
419
+ Schedule jobs to run on a recurring basis using cron expressions or fixed intervals. Schedules are persisted and survive worker restarts.
420
+
421
+ ### Creating a Schedule
422
+
423
+ ```typescript
424
+ import { Schedule } from '@boringnode/queue'
425
+
426
+ // Run every 10 seconds (uses job name as schedule ID by default)
427
+ const { scheduleId } = await MetricsJob.schedule({ endpoint: '/api/health' }).every('10s').run()
428
+
429
+ // Run on a cron schedule with custom ID
430
+ await CleanupJob.schedule({ days: 30 })
431
+ .id('daily-cleanup') // Custom ID (optional, defaults to job name)
432
+ .cron('0 * * * *') // Every hour at minute 0
433
+ .timezone('Europe/Paris') // Optional timezone (default: UTC)
434
+ .run()
435
+
436
+ // Schedule with constraints
437
+ await ReportJob.schedule({ type: 'weekly' })
438
+ .id('weekly-report')
439
+ .cron('0 9 * * MON') // Every Monday at 9am
440
+ .from(new Date('2024-01-01')) // Start date
441
+ .to(new Date('2024-12-31')) // End date
442
+ .limit(52) // Maximum 52 runs
443
+ .run()
444
+ ```
445
+
446
+ ### Managing Schedules
447
+
448
+ ```typescript
449
+ import { Schedule } from '@boringnode/queue'
450
+
451
+ // Find a schedule by ID
452
+ const schedule = await Schedule.find('health-check')
453
+
454
+ if (schedule) {
455
+ console.log(`Status: ${schedule.status}`) // 'active' or 'paused'
456
+ console.log(`Run count: ${schedule.runCount}`)
457
+ console.log(`Next run: ${schedule.nextRunAt}`)
458
+ console.log(`Last run: ${schedule.lastRunAt}`)
459
+
460
+ // Pause the schedule
461
+ await schedule.pause()
462
+
463
+ // Resume the schedule
464
+ await schedule.resume()
465
+
466
+ // Trigger an immediate run (outside of the normal schedule)
467
+ await schedule.trigger()
468
+
469
+ // Delete the schedule
470
+ await schedule.delete()
471
+ }
472
+ ```
473
+
474
+ ### Listing Schedules
475
+
476
+ ```typescript
477
+ import { Schedule } from '@boringnode/queue'
478
+
479
+ // List all schedules
480
+ const all = await Schedule.list()
481
+
482
+ // Filter by status
483
+ const active = await Schedule.list({ status: 'active' })
484
+ const paused = await Schedule.list({ status: 'paused' })
485
+ ```
486
+
487
+ ### Schedule Options
488
+
489
+ | Method | Description |
490
+ |----------------------|-------------------------------------------------|
491
+ | `.id(string)` | Unique identifier (defaults to job name) |
492
+ | `.every(duration)` | Run at fixed intervals ('5s', '1m', '1h', '1d') |
493
+ | `.cron(expression)` | Run on a cron schedule |
494
+ | `.timezone(tz)` | Timezone for cron expressions (default: 'UTC') |
495
+ | `.from(date)` | Don't run before this date |
496
+ | `.to(date)` | Don't run after this date |
497
+ | `.between(from, to)` | Shorthand for `.from().to()` |
498
+ | `.limit(n)` | Maximum number of runs |
499
+
500
+ ### How Scheduling Works
501
+
502
+ - Schedules are **persisted** in the database (via the adapter)
503
+ - The **Worker** polls for due schedules and dispatches jobs automatically
504
+ - Each schedule run creates a **new job** with a unique ID
505
+ - Multiple workers can run concurrently - only one will claim each due schedule
506
+ - Failed jobs do **not** affect the schedule (the next run will still occur)
507
+
317
508
  ## Job Discovery
318
509
 
319
510
  The queue manager automatically discovers and registers jobs from the specified locations:
320
511
 
321
512
  ```typescript
322
513
  const config = {
323
- locations: [
324
- './app/jobs/**/*.ts',
325
- './modules/**/jobs/**/*.ts',
326
- ],
514
+ locations: ['./app/jobs/**/*.ts', './modules/**/jobs/**/*.ts'],
327
515
  }
328
516
  ```
329
517
 
330
518
  Jobs must:
519
+
331
520
  - Extend the `Job` class
332
521
  - Have a static `jobName` property
333
522
  - Implement the `execute` method
334
523
  - Be exported as default
335
524
 
525
+ ## Logging
526
+
527
+ 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.
528
+
529
+ ```typescript
530
+ import { pino } from 'pino'
531
+
532
+ const config = {
533
+ default: 'redis',
534
+ adapters: {
535
+ /* ... */
536
+ },
537
+ logger: pino(),
538
+ }
539
+
540
+ await QueueManager.init(config)
541
+ ```
542
+
543
+ By default, a simple console logger is used that only outputs warnings and errors.
544
+
336
545
  ## Benchmarks
337
546
 
338
547
  Performance comparison with BullMQ using realistic jobs (5ms simulated work per job):
339
548
 
340
- | Jobs | Concurrency | @boringnode/queue | BullMQ | Diff |
341
- |------|-------------|-------------------|--------|--------------|
342
- | 100 | 1 | 562ms | 596ms | 5.7% faster |
343
- | 100 | 5 | 116ms | 117ms | ~same |
344
- | 100 | 10 | 62ms | 62ms | ~same |
345
- | 500 | 1 | 2728ms | 2798ms | 2.5% faster |
346
- | 500 | 5 | 565ms | 565ms | ~same |
347
- | 500 | 10 | 287ms | 288ms | ~same |
348
- | 1000 | 1 | 5450ms | 5547ms | 1.7% faster |
349
- | 1000 | 5 | 1096ms | 1116ms | 1.8% faster |
350
- | 1000 | 10 | 565ms | 579ms | 2.4% faster |
351
- | 100K | 5 | 110.5s | 112.3s | 1.5% faster |
352
- | 100K | 10 | 56.2s | 57.5s | 2.1% faster |
353
- | 100K | 20 | 29.1s | 29.6s | 1.7% faster |
549
+ | Jobs | Concurrency | @boringnode/queue | BullMQ | Diff |
550
+ |------|-------------|-------------------|--------|-------------|
551
+ | 100 | 1 | 562ms | 596ms | 5.7% faster |
552
+ | 100 | 5 | 116ms | 117ms | ~same |
553
+ | 100 | 10 | 62ms | 62ms | ~same |
554
+ | 500 | 1 | 2728ms | 2798ms | 2.5% faster |
555
+ | 500 | 5 | 565ms | 565ms | ~same |
556
+ | 500 | 10 | 287ms | 288ms | ~same |
557
+ | 1000 | 1 | 5450ms | 5547ms | 1.7% faster |
558
+ | 1000 | 5 | 1096ms | 1116ms | 1.8% faster |
559
+ | 1000 | 10 | 565ms | 579ms | 2.4% faster |
560
+ | 100K | 5 | 110.5s | 112.3s | 1.5% faster |
561
+ | 100K | 10 | 56.2s | 57.5s | 2.1% faster |
562
+ | 100K | 20 | 29.1s | 29.6s | 1.7% faster |
354
563
 
355
564
  Run benchmarks yourself:
356
565
 
@@ -364,3 +573,14 @@ npm run benchmark
364
573
  # Custom job duration
365
574
  npm run benchmark -- --duration=10
366
575
  ```
576
+
577
+ [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/boringnode/queue/checks.yml?branch=main&style=for-the-badge
578
+ [gh-workflow-url]: https://github.com/boringnode/queue/actions/workflows/checks.yml
579
+ [npm-image]: https://img.shields.io/npm/v/@boringnode/queue.svg?style=for-the-badge&logo=npm
580
+ [npm-url]: https://www.npmjs.com/package/@boringnode/queue
581
+ [npm-download-image]: https://img.shields.io/npm/dm/@boringnode/queue?style=for-the-badge
582
+ [npm-download-url]: https://www.npmjs.com/package/@boringnode/queue
583
+ [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
584
+ [typescript-url]: https://www.typescriptlang.org
585
+ [license-image]: https://img.shields.io/npm/l/@boringnode/queue?color=blueviolet&style=for-the-badge
586
+ [license-url]: LICENSE.md
@@ -0,0 +1,26 @@
1
+ import {
2
+ E_INVALID_DURATION_EXPRESSION,
3
+ PRIORITY_SCORE_MULTIPLIER
4
+ } from "./chunk-SMOKFZ46.js";
5
+
6
+ // src/utils.ts
7
+ import { parse as parseDuration } from "@lukeed/ms";
8
+ function parse(duration) {
9
+ if (typeof duration === "number") {
10
+ return duration;
11
+ }
12
+ const milliseconds = parseDuration(duration);
13
+ if (typeof milliseconds === "undefined") {
14
+ throw new E_INVALID_DURATION_EXPRESSION([duration]);
15
+ }
16
+ return milliseconds;
17
+ }
18
+ function calculateScore(priority, timestamp) {
19
+ return priority * PRIORITY_SCORE_MULTIPLIER + timestamp;
20
+ }
21
+
22
+ export {
23
+ parse,
24
+ calculateScore
25
+ };
26
+ //# sourceMappingURL=chunk-NPQKBCCY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { parse as parseDuration } from '@lukeed/ms'\nimport type { Duration } from './types/main.js'\nimport * as errors from './exceptions.js'\nimport { PRIORITY_SCORE_MULTIPLIER } from './constants.js'\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;AAKhC,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":[]}
@@ -0,0 +1,117 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/exceptions.ts
8
+ var exceptions_exports = {};
9
+ __export(exceptions_exports, {
10
+ E_ADAPTER_INIT_ERROR: () => E_ADAPTER_INIT_ERROR,
11
+ E_CONFIGURATION_ERROR: () => E_CONFIGURATION_ERROR,
12
+ E_INVALID_BASE_DELAY: () => E_INVALID_BASE_DELAY,
13
+ E_INVALID_CRON_EXPRESSION: () => E_INVALID_CRON_EXPRESSION,
14
+ E_INVALID_DURATION_EXPRESSION: () => E_INVALID_DURATION_EXPRESSION,
15
+ E_INVALID_MAX_DELAY: () => E_INVALID_MAX_DELAY,
16
+ E_INVALID_MULTIPLIER: () => E_INVALID_MULTIPLIER,
17
+ E_INVALID_SCHEDULE_CONFIG: () => E_INVALID_SCHEDULE_CONFIG,
18
+ E_JOB_MAX_ATTEMPTS_REACHED: () => E_JOB_MAX_ATTEMPTS_REACHED,
19
+ E_JOB_NOT_FOUND: () => E_JOB_NOT_FOUND,
20
+ E_JOB_TIMEOUT: () => E_JOB_TIMEOUT,
21
+ E_NO_JOBS_FOUND: () => E_NO_JOBS_FOUND,
22
+ E_QUEUE_NOT_INITIALIZED: () => E_QUEUE_NOT_INITIALIZED
23
+ });
24
+ import { createError } from "@poppinss/utils";
25
+ var E_INVALID_DURATION_EXPRESSION = createError(
26
+ 'Invalid duration expression: "%s"',
27
+ "E_INVALID_DURATION_EXPRESSION",
28
+ 500
29
+ );
30
+ var E_INVALID_BASE_DELAY = createError(
31
+ "Invalid base delay. Reason: %s",
32
+ "E_INVALID_BASE_DELAY",
33
+ 500
34
+ );
35
+ var E_INVALID_MAX_DELAY = createError(
36
+ "Invalid max delay. Reason: %s",
37
+ "E_INVALID_MAX_DELAY",
38
+ 500
39
+ );
40
+ var E_INVALID_MULTIPLIER = createError(
41
+ "Invalid multiplier. Reason: %s",
42
+ "E_INVALID_MULTIPLIER",
43
+ 500
44
+ );
45
+ var E_CONFIGURATION_ERROR = createError(
46
+ "Configuration error. Reason: %s",
47
+ "E_CONFIGURATION_ERROR",
48
+ 500
49
+ );
50
+ var E_JOB_NOT_FOUND = createError(
51
+ 'Requested job "%s" is not registered',
52
+ "E_JOB_NOT_FOUND"
53
+ );
54
+ var E_JOB_MAX_ATTEMPTS_REACHED = createError(
55
+ 'The job "%s" has reached the maximum number of retry attempts',
56
+ "E_JOB_MAX_ATTEMPTS_REACHED"
57
+ );
58
+ var E_JOB_TIMEOUT = createError(
59
+ 'The job "%s" has exceeded the timeout of %dms',
60
+ "E_JOB_TIMEOUT"
61
+ );
62
+ var E_QUEUE_NOT_INITIALIZED = createError(
63
+ "QueueManager is not initialized. Call QueueManager.init() before using it.",
64
+ "E_QUEUE_NOT_INITIALIZED",
65
+ 500
66
+ );
67
+ var E_ADAPTER_INIT_ERROR = createError(
68
+ 'Failed to initialize adapter "%s". Reason: %s',
69
+ "E_ADAPTER_INIT_ERROR",
70
+ 500
71
+ );
72
+ var E_NO_JOBS_FOUND = createError(
73
+ "No jobs found for the specified locations: %s. Verify your glob patterns match your job files.",
74
+ "E_NO_JOBS_FOUND",
75
+ 500
76
+ );
77
+ var E_INVALID_CRON_EXPRESSION = createError(
78
+ 'Invalid cron expression "%s": %s',
79
+ "E_INVALID_CRON_EXPRESSION",
80
+ 500
81
+ );
82
+ var E_INVALID_SCHEDULE_CONFIG = createError(
83
+ "Invalid schedule configuration: %s",
84
+ "E_INVALID_SCHEDULE_CONFIG",
85
+ 500
86
+ );
87
+
88
+ // src/constants.ts
89
+ var DEFAULT_PRIORITY = 5;
90
+ var PRIORITY_SCORE_MULTIPLIER = 1e13;
91
+ var DEFAULT_IDLE_DELAY = "2s";
92
+ var DEFAULT_STALLED_INTERVAL = "30s";
93
+ var DEFAULT_STALLED_THRESHOLD = "30s";
94
+ var DEFAULT_ERROR_RETRY_DELAY = "5s";
95
+
96
+ export {
97
+ E_INVALID_DURATION_EXPRESSION,
98
+ E_INVALID_BASE_DELAY,
99
+ E_INVALID_MAX_DELAY,
100
+ E_INVALID_MULTIPLIER,
101
+ E_CONFIGURATION_ERROR,
102
+ E_JOB_NOT_FOUND,
103
+ E_JOB_MAX_ATTEMPTS_REACHED,
104
+ E_JOB_TIMEOUT,
105
+ E_QUEUE_NOT_INITIALIZED,
106
+ E_ADAPTER_INIT_ERROR,
107
+ E_INVALID_CRON_EXPRESSION,
108
+ E_INVALID_SCHEDULE_CONFIG,
109
+ exceptions_exports,
110
+ DEFAULT_PRIORITY,
111
+ PRIORITY_SCORE_MULTIPLIER,
112
+ DEFAULT_IDLE_DELAY,
113
+ DEFAULT_STALLED_INTERVAL,
114
+ DEFAULT_STALLED_THRESHOLD,
115
+ DEFAULT_ERROR_RETRY_DELAY
116
+ };
117
+ //# sourceMappingURL=chunk-SMOKFZ46.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/exceptions.ts","../src/constants.ts"],"sourcesContent":["import { createError } from '@poppinss/utils'\n\nexport const E_INVALID_DURATION_EXPRESSION = createError(\n 'Invalid duration expression: \"%s\"',\n 'E_INVALID_DURATION_EXPRESSION',\n 500\n)\n\nexport const E_INVALID_BASE_DELAY = createError<[reason: string]>(\n 'Invalid base delay. Reason: %s',\n 'E_INVALID_BASE_DELAY',\n 500\n)\n\nexport const E_INVALID_MAX_DELAY = createError<[reason: string]>(\n 'Invalid max delay. Reason: %s',\n 'E_INVALID_MAX_DELAY',\n 500\n)\n\nexport const E_INVALID_MULTIPLIER = createError<[reason: string]>(\n 'Invalid multiplier. Reason: %s',\n 'E_INVALID_MULTIPLIER',\n 500\n)\n\nexport const E_CONFIGURATION_ERROR = createError<[reason: string]>(\n 'Configuration error. Reason: %s',\n 'E_CONFIGURATION_ERROR',\n 500\n)\n\nexport const E_JOB_NOT_FOUND = createError<[jobName: string]>(\n 'Requested job \"%s\" is not registered',\n 'E_JOB_NOT_FOUND'\n)\n\nexport const E_JOB_MAX_ATTEMPTS_REACHED = createError<[jobName: string]>(\n 'The job \"%s\" has reached the maximum number of retry attempts',\n 'E_JOB_MAX_ATTEMPTS_REACHED'\n)\n\nexport const E_JOB_TIMEOUT = createError<[jobName: string, timeout: number]>(\n 'The job \"%s\" has exceeded the timeout of %dms',\n 'E_JOB_TIMEOUT'\n)\n\nexport const E_QUEUE_NOT_INITIALIZED = createError(\n 'QueueManager is not initialized. Call QueueManager.init() before using it.',\n 'E_QUEUE_NOT_INITIALIZED',\n 500\n)\n\nexport const E_ADAPTER_INIT_ERROR = createError<[adapterName: string, originalMessage: string]>(\n 'Failed to initialize adapter \"%s\". Reason: %s',\n 'E_ADAPTER_INIT_ERROR',\n 500\n)\n\nexport const E_NO_JOBS_FOUND = createError<[patterns: string]>(\n 'No jobs found for the specified locations: %s. Verify your glob patterns match your job files.',\n 'E_NO_JOBS_FOUND',\n 500\n)\n\nexport const E_INVALID_CRON_EXPRESSION = createError<[expression: string, reason: string]>(\n 'Invalid cron expression \"%s\": %s',\n 'E_INVALID_CRON_EXPRESSION',\n 500\n)\n\nexport const E_INVALID_SCHEDULE_CONFIG = createError<[reason: string]>(\n 'Invalid schedule configuration: %s',\n 'E_INVALID_SCHEDULE_CONFIG',\n 500\n)\n","/**\n * Default job priority (1-10 scale, lower = higher priority)\n */\nexport const DEFAULT_PRIORITY = 5\n\n/**\n * Multiplier used in score calculation: priority * multiplier + timestamp\n *\n * This ensures higher priority jobs are processed first,\n * while preserving FIFO order within the same priority.\n * The value (1e13) leaves room for ~300 years of millisecond timestamps.\n */\nexport const PRIORITY_SCORE_MULTIPLIER = 1e13\n\n/**\n * Default delay when the worker is idle (no jobs in queue)\n */\nexport const DEFAULT_IDLE_DELAY = '2s'\n\n/**\n * Default interval between stalled job checks\n */\nexport const DEFAULT_STALLED_INTERVAL = '30s'\n\n/**\n * Default threshold after which a job is considered stalled\n */\nexport const DEFAULT_STALLED_THRESHOLD = '30s'\n\n/**\n * Default delay before retrying after an error\n */\nexport const DEFAULT_ERROR_RETRY_DELAY = '5s'\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;AAErB,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AACF;AAEO,IAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AACF;AAEO,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AACF;AAEO,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF;;;ACxEO,IAAM,mBAAmB;AASzB,IAAM,4BAA4B;AAKlC,IAAM,qBAAqB;AAK3B,IAAM,2BAA2B;AAKjC,IAAM,4BAA4B;AAKlC,IAAM,4BAA4B;","names":[]}