@igniter-js/jobs 0.1.13 → 0.1.15
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/AGENTS.md +119 -243
- package/README.md +352 -158
- package/dist/{adapter-CXZxomI9.d.mts → adapter-DDyMVche.d.mts} +125 -20
- package/dist/{adapter-CXZxomI9.d.ts → adapter-DDyMVche.d.ts} +125 -20
- package/dist/adapters/bun.d.mts +101 -0
- package/dist/adapters/bun.d.ts +101 -0
- package/dist/adapters/bun.js +1048 -0
- package/dist/adapters/bun.js.map +1 -0
- package/dist/adapters/bun.mjs +1046 -0
- package/dist/adapters/bun.mjs.map +1 -0
- package/dist/adapters/{memory.adapter.d.ts → mock.d.mts} +7 -3
- package/dist/adapters/{memory.adapter.d.mts → mock.d.ts} +7 -3
- package/dist/adapters/{memory.adapter.js → mock.js} +122 -25
- package/dist/adapters/mock.js.map +1 -0
- package/dist/adapters/{memory.adapter.mjs → mock.mjs} +122 -25
- package/dist/adapters/mock.mjs.map +1 -0
- package/dist/adapters/{bullmq.adapter.d.mts → node.d.mts} +8 -3
- package/dist/adapters/{bullmq.adapter.d.ts → node.d.ts} +8 -3
- package/dist/adapters/{bullmq.adapter.js → node.js} +194 -40
- package/dist/adapters/node.js.map +1 -0
- package/dist/adapters/{bullmq.adapter.mjs → node.mjs} +194 -40
- package/dist/adapters/node.mjs.map +1 -0
- package/dist/index.d.mts +41 -38
- package/dist/index.d.ts +41 -38
- package/dist/index.js +145 -1856
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -1854
- package/dist/index.mjs.map +1 -1
- package/package.json +29 -41
- package/CHANGELOG.md +0 -13
- package/dist/adapters/bullmq.adapter.js.map +0 -1
- package/dist/adapters/bullmq.adapter.mjs.map +0 -1
- package/dist/adapters/index.d.mts +0 -143
- package/dist/adapters/index.d.ts +0 -143
- package/dist/adapters/index.js +0 -1891
- package/dist/adapters/index.js.map +0 -1
- package/dist/adapters/index.mjs +0 -1887
- package/dist/adapters/index.mjs.map +0 -1
- package/dist/adapters/memory.adapter.js.map +0 -1
- package/dist/adapters/memory.adapter.mjs.map +0 -1
|
@@ -33,6 +33,8 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
33
33
|
this.registeredJobs = /* @__PURE__ */ new Map();
|
|
34
34
|
this.registeredCrons = /* @__PURE__ */ new Map();
|
|
35
35
|
this.workers = /* @__PURE__ */ new Map();
|
|
36
|
+
this.streamRecords = /* @__PURE__ */ new Map();
|
|
37
|
+
this.streamSubscribers = /* @__PURE__ */ new Map();
|
|
36
38
|
this.subscribers = /* @__PURE__ */ new Map();
|
|
37
39
|
this.queues = {
|
|
38
40
|
list: async () => this.listQueues(),
|
|
@@ -358,25 +360,6 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
358
360
|
}
|
|
359
361
|
return retried;
|
|
360
362
|
}
|
|
361
|
-
async pauseJobType(queue, jobName) {
|
|
362
|
-
const jobIds = this.jobsByQueue.get(queue) ?? [];
|
|
363
|
-
for (const id of jobIds) {
|
|
364
|
-
const job = this.jobsById.get(id);
|
|
365
|
-
if (!job) continue;
|
|
366
|
-
if (job.name === jobName && job.status === "waiting")
|
|
367
|
-
job.status = "paused";
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
async resumeJobType(queue, jobName) {
|
|
371
|
-
const jobIds = this.jobsByQueue.get(queue) ?? [];
|
|
372
|
-
for (const id of jobIds) {
|
|
373
|
-
const job = this.jobsById.get(id);
|
|
374
|
-
if (!job) continue;
|
|
375
|
-
if (job.name === jobName && job.status === "paused")
|
|
376
|
-
job.status = "waiting";
|
|
377
|
-
}
|
|
378
|
-
void this.kickWorkers(queue);
|
|
379
|
-
}
|
|
380
363
|
async searchJobs(filter) {
|
|
381
364
|
const queue = filter?.queue;
|
|
382
365
|
const statuses = filter?.status;
|
|
@@ -440,9 +423,68 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
440
423
|
if (current.size === 0) this.subscribers.delete(channel);
|
|
441
424
|
};
|
|
442
425
|
}
|
|
426
|
+
async writeJobStreamEvent(params) {
|
|
427
|
+
const key = this.getStreamKey(params.queue, params.jobId);
|
|
428
|
+
const record = this.streamRecords.get(key) ?? { events: [], nextId: 1 };
|
|
429
|
+
const id = String(record.nextId++);
|
|
430
|
+
const event = {
|
|
431
|
+
...params.event,
|
|
432
|
+
id
|
|
433
|
+
};
|
|
434
|
+
if (params.persistence?.enabled) {
|
|
435
|
+
record.events.push(event);
|
|
436
|
+
const maxEvents = params.persistence.maxEvents;
|
|
437
|
+
if (typeof maxEvents === "number" && maxEvents > 0 && record.events.length > maxEvents) {
|
|
438
|
+
record.events.splice(0, record.events.length - maxEvents);
|
|
439
|
+
}
|
|
440
|
+
this.streamRecords.set(key, record);
|
|
441
|
+
} else if (!this.streamRecords.has(key)) {
|
|
442
|
+
this.streamRecords.set(key, record);
|
|
443
|
+
}
|
|
444
|
+
const handlers = this.streamSubscribers.get(key);
|
|
445
|
+
if (handlers?.size) {
|
|
446
|
+
await Promise.all(
|
|
447
|
+
Array.from(handlers).map(async (handler) => handler(event))
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
return id;
|
|
451
|
+
}
|
|
452
|
+
async readJobStream(params) {
|
|
453
|
+
const key = this.getStreamKey(params.queue, params.jobId);
|
|
454
|
+
const record = this.streamRecords.get(key);
|
|
455
|
+
if (!record) {
|
|
456
|
+
return { items: [], nextCursor: void 0, hasMore: false };
|
|
457
|
+
}
|
|
458
|
+
const after = params.after ? Number(params.after) : void 0;
|
|
459
|
+
const limit = params.limit ?? 100;
|
|
460
|
+
const filtered = record.events.filter(
|
|
461
|
+
(event) => typeof after === "number" ? Number(event.id) > after : true
|
|
462
|
+
);
|
|
463
|
+
const items = filtered.slice(0, limit);
|
|
464
|
+
const hasMore = filtered.length > items.length;
|
|
465
|
+
return {
|
|
466
|
+
items,
|
|
467
|
+
nextCursor: items.at(-1)?.id,
|
|
468
|
+
hasMore
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
async subscribeJobStream(params) {
|
|
472
|
+
const key = this.getStreamKey(params.queue, params.jobId);
|
|
473
|
+
const set = this.streamSubscribers.get(key) ?? /* @__PURE__ */ new Set();
|
|
474
|
+
set.add(params.handler);
|
|
475
|
+
this.streamSubscribers.set(key, set);
|
|
476
|
+
return async () => {
|
|
477
|
+
const current = this.streamSubscribers.get(key);
|
|
478
|
+
if (!current) return;
|
|
479
|
+
current.delete(params.handler);
|
|
480
|
+
if (current.size === 0) this.streamSubscribers.delete(key);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
443
483
|
async shutdown() {
|
|
444
484
|
this.workers.clear();
|
|
445
485
|
this.subscribers.clear();
|
|
486
|
+
this.streamSubscribers.clear();
|
|
487
|
+
this.streamRecords.clear();
|
|
446
488
|
}
|
|
447
489
|
toSearchResult(job) {
|
|
448
490
|
return {
|
|
@@ -463,6 +505,9 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
463
505
|
scope: job.scope
|
|
464
506
|
};
|
|
465
507
|
}
|
|
508
|
+
getStreamKey(queue, jobId) {
|
|
509
|
+
return `${queue}:${jobId}`;
|
|
510
|
+
}
|
|
466
511
|
toWorkerHandle(worker) {
|
|
467
512
|
return {
|
|
468
513
|
id: worker.id,
|
|
@@ -561,12 +606,61 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
561
606
|
name: job.name,
|
|
562
607
|
queue: job.queue,
|
|
563
608
|
attemptsMade: job.attemptsMade,
|
|
564
|
-
metadata: job.metadata
|
|
609
|
+
metadata: job.metadata,
|
|
610
|
+
updateProgress: async (progress, message) => {
|
|
611
|
+
job.progress = progress;
|
|
612
|
+
if (message) {
|
|
613
|
+
job.logs.push({
|
|
614
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
615
|
+
level: "info",
|
|
616
|
+
message
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
await definition.onProgress?.({
|
|
620
|
+
input: job.input,
|
|
621
|
+
context: {},
|
|
622
|
+
job: {
|
|
623
|
+
id: job.id,
|
|
624
|
+
name: job.name,
|
|
625
|
+
queue: job.queue,
|
|
626
|
+
attemptsMade: job.attemptsMade,
|
|
627
|
+
metadata: job.metadata
|
|
628
|
+
},
|
|
629
|
+
scope: job.scope,
|
|
630
|
+
progress,
|
|
631
|
+
message
|
|
632
|
+
});
|
|
633
|
+
}
|
|
565
634
|
},
|
|
566
635
|
scope: job.scope,
|
|
567
636
|
startedAt: job.startedAt
|
|
568
637
|
});
|
|
569
638
|
}
|
|
639
|
+
const updateProgress = async (progress, message) => {
|
|
640
|
+
job.progress = progress;
|
|
641
|
+
if (message) {
|
|
642
|
+
job.logs.push({
|
|
643
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
644
|
+
level: "info",
|
|
645
|
+
message
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
await definition.onProgress?.({
|
|
649
|
+
input: job.input,
|
|
650
|
+
context: {},
|
|
651
|
+
job: {
|
|
652
|
+
id: job.id,
|
|
653
|
+
name: job.name,
|
|
654
|
+
queue: job.queue,
|
|
655
|
+
attemptsMade: job.attemptsMade,
|
|
656
|
+
metadata: job.metadata,
|
|
657
|
+
updateProgress
|
|
658
|
+
},
|
|
659
|
+
scope: job.scope,
|
|
660
|
+
progress,
|
|
661
|
+
message
|
|
662
|
+
});
|
|
663
|
+
};
|
|
570
664
|
const result = await definition.handler({
|
|
571
665
|
input: job.input,
|
|
572
666
|
context: {},
|
|
@@ -575,7 +669,8 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
575
669
|
name: job.name,
|
|
576
670
|
queue: job.queue,
|
|
577
671
|
attemptsMade: job.attemptsMade,
|
|
578
|
-
metadata: job.metadata
|
|
672
|
+
metadata: job.metadata,
|
|
673
|
+
updateProgress
|
|
579
674
|
},
|
|
580
675
|
scope: job.scope
|
|
581
676
|
});
|
|
@@ -600,7 +695,8 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
600
695
|
name: job.name,
|
|
601
696
|
queue: job.queue,
|
|
602
697
|
attemptsMade: job.attemptsMade,
|
|
603
|
-
metadata: job.metadata
|
|
698
|
+
metadata: job.metadata,
|
|
699
|
+
updateProgress
|
|
604
700
|
},
|
|
605
701
|
scope: job.scope,
|
|
606
702
|
result,
|
|
@@ -634,7 +730,8 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
634
730
|
name: job.name,
|
|
635
731
|
queue: job.queue,
|
|
636
732
|
attemptsMade: job.attemptsMade,
|
|
637
|
-
metadata: job.metadata
|
|
733
|
+
metadata: job.metadata,
|
|
734
|
+
updateProgress: async () => void 0
|
|
638
735
|
},
|
|
639
736
|
scope: job.scope,
|
|
640
737
|
error,
|
|
@@ -655,5 +752,5 @@ var IgniterJobsMemoryAdapter = class _IgniterJobsMemoryAdapter {
|
|
|
655
752
|
};
|
|
656
753
|
|
|
657
754
|
export { IgniterJobsMemoryAdapter };
|
|
658
|
-
//# sourceMappingURL=
|
|
659
|
-
//# sourceMappingURL=
|
|
755
|
+
//# sourceMappingURL=mock.mjs.map
|
|
756
|
+
//# sourceMappingURL=mock.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/id-generator.ts","../../src/errors/jobs.error.ts","../../src/adapters/memory.adapter.ts"],"names":[],"mappings":"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","file":"mock.mjs","sourcesContent":["/**\n * Generates consistent identifiers for jobs, workers, and schedules.\n */\nexport class IgniterJobsIdGenerator {\n /**\n * Generates a unique identifier with a prefix.\n *\n * @example\n * ```typescript\n * const jobId = IgniterJobsIdGenerator.generate('job')\n * ```\n */\n public static generate(prefix: string): string {\n const now = Date.now().toString(36)\n const random = Math.random().toString(36).slice(2, 8)\n return `${prefix}_${now}_${random}`\n }\n}\n","import { IgniterError } from \"@igniter-js/common\";\n\n/**\n * Canonical error codes for `@igniter-js/jobs`.\n */\nexport const IGNITER_JOBS_ERROR_CODES = {\n JOBS_ADAPTER_REQUIRED: 'JOBS_ADAPTER_REQUIRED',\n JOBS_SERVICE_REQUIRED: 'JOBS_SERVICE_REQUIRED',\n JOBS_CONTEXT_REQUIRED: 'JOBS_CONTEXT_REQUIRED',\n JOBS_CONFIGURATION_INVALID: 'JOBS_CONFIGURATION_INVALID',\n JOBS_QUEUE_NOT_FOUND: 'JOBS_QUEUE_NOT_FOUND',\n JOBS_QUEUE_DUPLICATE: 'JOBS_QUEUE_DUPLICATE',\n JOBS_QUEUE_OPERATION_FAILED: 'JOBS_QUEUE_OPERATION_FAILED',\n JOBS_INVALID_DEFINITION: 'JOBS_INVALID_DEFINITION',\n JOBS_HANDLER_REQUIRED: 'JOBS_HANDLER_REQUIRED',\n JOBS_DUPLICATE_JOB: 'JOBS_DUPLICATE_JOB',\n JOBS_NOT_FOUND: 'JOBS_NOT_FOUND',\n JOBS_NOT_REGISTERED: 'JOBS_NOT_REGISTERED',\n JOBS_EXECUTION_FAILED: 'JOBS_EXECUTION_FAILED',\n JOBS_TIMEOUT: 'JOBS_TIMEOUT',\n JOBS_CONTEXT_FACTORY_FAILED: 'JOBS_CONTEXT_FACTORY_FAILED',\n JOBS_VALIDATION_FAILED: 'JOBS_VALIDATION_FAILED',\n JOBS_INVALID_INPUT: 'JOBS_INVALID_INPUT',\n JOBS_INVALID_CRON: 'JOBS_INVALID_CRON',\n JOBS_INVALID_SCHEDULE: 'JOBS_INVALID_SCHEDULE',\n JOBS_SCOPE_ALREADY_DEFINED: 'JOBS_SCOPE_ALREADY_DEFINED',\n JOBS_WORKER_FAILED: 'JOBS_WORKER_FAILED',\n JOBS_ADAPTER_ERROR: 'JOBS_ADAPTER_ERROR',\n JOBS_ADAPTER_CONNECTION_FAILED: 'JOBS_ADAPTER_CONNECTION_FAILED',\n JOBS_SUBSCRIBE_FAILED: 'JOBS_SUBSCRIBE_FAILED',\n} as const\n\nexport type IgniterJobsErrorCode = keyof typeof IGNITER_JOBS_ERROR_CODES\n\nexport interface IgniterJobsErrorOptions {\n /** Error code scoped to Igniter Jobs. */\n code: IgniterJobsErrorCode\n /** Human-readable message. */\n message: string\n /** HTTP-like status code hint (default: 500). */\n statusCode?: number\n /** Optional structured details for debugging and clients. */\n details?: unknown\n /** Optional metadata for logs and tracing. */\n metadata?: Record<string, unknown>\n /** Optional causer tag used by some Igniter tooling. */\n causer?: string\n /** Underlying cause for debugging (optional). */\n cause?: Error\n /** Optional logger passthrough to align with other Igniter errors. */\n logger?: any\n}\n\n/**\n * Typed error class for the Jobs package.\n *\n * @example\n * ```typescript\n * throw new IgniterJobsError({\n * code: 'JOBS_INVALID_INPUT',\n * message: 'Input payload failed validation',\n * })\n * ```\n */\nexport class IgniterJobsError extends IgniterError {\n constructor(options: IgniterJobsErrorOptions) {\n super(options)\n }\n}\n","/**\n * @fileoverview In-memory adapter for @igniter-js/jobs (tests/dev only)\n * @module @igniter-js/jobs/adapters/memory\n */\n\nimport type {\n IgniterJobsAdapterJobStreamReadParams,\n IgniterJobsAdapterJobStreamSubscribeParams,\n IgniterJobsAdapterJobStreamWriteParams,\n IgniterCronDefinition,\n IgniterJobCounts,\n IgniterJobDefinition,\n IgniterJobSearchResult,\n IgniterJobStatus,\n IgniterJobsAdapter,\n IgniterJobsAdapterDispatchParams,\n IgniterJobsAdapterScheduleParams,\n IgniterJobsEventHandler,\n IgniterJobsJobLog,\n IgniterJobsQueueCleanOptions,\n IgniterJobsQueueInfo,\n IgniterJobsQueueManager,\n IgniterJobsWorkerBuilderConfig,\n IgniterJobsWorkerHandle,\n IgniterJobsWorkerMetrics,\n} from \"../types\";\nimport type {\n IgniterJobsJobStreamEvent,\n IgniterJobsJobStreamReadResult,\n} from \"../types/stream\";\nimport { IgniterJobsIdGenerator } from \"../utils/id-generator\";\nimport { IgniterJobsError } from \"../errors\";\n\ntype MemoryJob = {\n id: string;\n name: string;\n queue: string;\n input: unknown;\n status: IgniterJobStatus;\n progress: number;\n attemptsMade: number;\n maxAttempts: number;\n priority: number;\n createdAt: Date;\n startedAt?: Date;\n completedAt?: Date;\n result?: unknown;\n error?: string;\n metadata?: Record<string, unknown>;\n scope?: unknown;\n logs: IgniterJobsJobLog[];\n};\n\ntype MemoryWorkerState = {\n id: string;\n queues: string[];\n concurrency: number;\n paused: boolean;\n closed: boolean;\n startedAt: Date;\n metrics: {\n processed: number;\n failed: number;\n totalDuration: number;\n };\n handlers?: IgniterJobsWorkerBuilderConfig[\"handlers\"];\n};\n\ntype MemoryStreamRecord = {\n events: IgniterJobsJobStreamEvent<string, unknown>[];\n nextId: number;\n};\n\n/**\n * Lightweight in-memory adapter used for unit tests and local development.\n *\n * This adapter is not suitable for production use.\n */\nexport class IgniterJobsMemoryAdapter implements IgniterJobsAdapter {\n public readonly client = {\n type: \"memory\" as const,\n };\n\n private readonly jobsById = new Map<string, MemoryJob>();\n private readonly jobsByQueue = new Map<string, string[]>();\n private readonly registeredJobs = new Map<\n string,\n Map<string, IgniterJobDefinition<any, any, any>>\n >();\n private readonly registeredCrons = new Map<\n string,\n Map<string, IgniterCronDefinition<any, any>>\n >();\n\n private readonly workers = new Map<string, MemoryWorkerState>();\n private readonly streamRecords = new Map<string, MemoryStreamRecord>();\n private readonly streamSubscribers = new Map<\n string,\n Set<\n (\n event: IgniterJobsJobStreamEvent<string, unknown>,\n ) => void | Promise<void>\n >\n >();\n\n private readonly subscribers = new Map<\n string,\n Set<IgniterJobsEventHandler>\n >();\n\n public readonly queues: IgniterJobsQueueManager = {\n list: async () => this.listQueues(),\n get: async (name) => this.getQueueInfo(name),\n getJobCounts: async (name) => this.getQueueJobCounts(name),\n getJobs: async (name, filter) => {\n const statuses = filter?.status;\n const limit = filter?.limit ?? 100;\n const offset = filter?.offset ?? 0;\n const results = await this.searchJobs({\n queue: name,\n status: statuses,\n limit,\n offset,\n } as any);\n return results;\n },\n pause: async (name) => this.pauseQueue(name),\n resume: async (name) => this.resumeQueue(name),\n isPaused: async (name) => {\n // Queue-level pause is stored as a special marker job list state.\n // For memory adapter, we model it by a metadata flag in queue info.\n const info = await this.getQueueInfo(name);\n return info?.isPaused ?? false;\n },\n drain: async (name) => this.drainQueue(name),\n clean: async (name, options) => this.cleanQueue(name, options),\n obliterate: async (name, options) => this.obliterateQueue(name, options),\n };\n\n private readonly pausedQueues = new Set<string>();\n\n public static create(): IgniterJobsAdapter {\n return new IgniterJobsMemoryAdapter();\n }\n\n public registerJob(\n queueName: string,\n jobName: string,\n definition: IgniterJobDefinition<any, any, any>,\n ): void {\n const queueJobs =\n this.registeredJobs.get(queueName) ??\n new Map<string, IgniterJobDefinition<any, any, any>>();\n if (queueJobs.has(jobName)) {\n throw new IgniterJobsError({\n code: \"JOBS_DUPLICATE_JOB\",\n message: `Job \"${jobName}\" already registered for queue \"${queueName}\".`,\n });\n }\n queueJobs.set(jobName, definition);\n this.registeredJobs.set(queueName, queueJobs);\n }\n\n public registerCron(\n queueName: string,\n cronName: string,\n definition: IgniterCronDefinition<any, any>,\n ): void {\n const queueCrons =\n this.registeredCrons.get(queueName) ??\n new Map<string, IgniterCronDefinition<any, any>>();\n if (queueCrons.has(cronName)) {\n throw new IgniterJobsError({\n code: \"JOBS_INVALID_CRON\",\n message: `Cron \"${cronName}\" already registered for queue \"${queueName}\".`,\n });\n }\n queueCrons.set(cronName, definition);\n this.registeredCrons.set(queueName, queueCrons);\n }\n\n public async dispatch(\n params: IgniterJobsAdapterDispatchParams,\n ): Promise<string> {\n const jobId = params.jobId ?? IgniterJobsIdGenerator.generate(\"job\");\n const maxAttempts = params.attempts ?? 1;\n\n const metadata = params.metadata ?? {};\n\n const job: MemoryJob = {\n id: jobId,\n name: params.jobName,\n queue: params.queue,\n input: params.input,\n status: this.pausedQueues.has(params.queue)\n ? \"paused\"\n : params.delay && params.delay > 0\n ? \"delayed\"\n : \"waiting\",\n progress: 0,\n attemptsMade: 0,\n maxAttempts,\n priority: params.priority ?? 0,\n createdAt: new Date(),\n metadata: metadata as Record<string, unknown>,\n scope: params.scope,\n logs: [],\n };\n\n this.jobsById.set(jobId, job);\n const queueList = this.jobsByQueue.get(params.queue) ?? [];\n queueList.push(jobId);\n this.jobsByQueue.set(params.queue, queueList);\n\n if (params.delay && params.delay > 0) {\n setTimeout(() => {\n const stored = this.jobsById.get(jobId);\n if (!stored) return;\n if (!this.pausedQueues.has(params.queue)) stored.status = \"waiting\";\n void this.kickWorkers(params.queue);\n }, params.delay);\n return jobId;\n }\n\n void this.kickWorkers(params.queue);\n return jobId;\n }\n\n public async schedule(\n params: IgniterJobsAdapterScheduleParams,\n ): Promise<string> {\n if (params.at) {\n const delay = params.at.getTime() - Date.now();\n if (delay <= 0) {\n throw new IgniterJobsError({\n code: \"JOBS_INVALID_SCHEDULE\",\n message: \"Scheduled time must be in the future.\",\n });\n }\n return this.dispatch({ ...params, delay });\n }\n if (params.cron || params.every) {\n // Memory adapter does not implement a cron engine. It stores the job as delayed and relies on tests\n // to invoke dispatch manually if needed.\n return this.dispatch({ ...params, delay: params.delay ?? 0 });\n }\n return this.dispatch(params);\n }\n\n public async getJob(\n jobId: string,\n queue?: string,\n ): Promise<IgniterJobSearchResult | null> {\n const job = this.jobsById.get(jobId);\n if (!job) return null;\n if (queue && job.queue !== queue) return null;\n return this.toSearchResult(job);\n }\n\n public async getJobState(\n jobId: string,\n queue?: string,\n ): Promise<IgniterJobStatus | null> {\n const job = this.jobsById.get(jobId);\n if (!job) return null;\n if (queue && job.queue !== queue) return null;\n return job.status;\n }\n\n public async getJobLogs(\n jobId: string,\n queue?: string,\n ): Promise<IgniterJobsJobLog[]> {\n const job = this.jobsById.get(jobId);\n if (!job) return [];\n if (queue && job.queue !== queue) return [];\n return job.logs;\n }\n\n public async getJobProgress(jobId: string, queue?: string): Promise<number> {\n const job = this.jobsById.get(jobId);\n if (!job) return 0;\n if (queue && job.queue !== queue) return 0;\n return job.progress;\n }\n\n public async retryJob(jobId: string, queue?: string): Promise<void> {\n const job = this.jobsById.get(jobId);\n if (!job) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found.`,\n });\n }\n if (queue && job.queue !== queue) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found in queue \"${queue}\".`,\n });\n }\n job.status = \"waiting\";\n job.error = undefined;\n job.completedAt = undefined;\n job.progress = 0;\n void this.kickWorkers(job.queue);\n }\n\n public async removeJob(jobId: string, queue?: string): Promise<void> {\n const job = this.jobsById.get(jobId);\n if (!job) return;\n if (queue && job.queue !== queue) return;\n this.jobsById.delete(jobId);\n const list = this.jobsByQueue.get(job.queue);\n if (list)\n this.jobsByQueue.set(\n job.queue,\n list.filter((id) => id !== jobId),\n );\n }\n\n public async promoteJob(jobId: string, queue?: string): Promise<void> {\n const job = this.jobsById.get(jobId);\n if (!job) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found.`,\n });\n }\n if (queue && job.queue !== queue) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found in queue \"${queue}\".`,\n });\n }\n if (job.status === \"delayed\" || job.status === \"paused\") {\n job.status = this.pausedQueues.has(job.queue) ? \"paused\" : \"waiting\";\n void this.kickWorkers(job.queue);\n }\n }\n\n public async moveJobToFailed(\n jobId: string,\n reason: string,\n queue?: string,\n ): Promise<void> {\n const job = this.jobsById.get(jobId);\n if (!job) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found.`,\n });\n }\n if (queue && job.queue !== queue) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_FOUND\",\n message: `Job \"${jobId}\" not found in queue \"${queue}\".`,\n });\n }\n job.status = \"failed\";\n job.error = reason;\n job.completedAt = new Date();\n }\n\n public async retryManyJobs(jobIds: string[], queue?: string): Promise<void> {\n await Promise.all(jobIds.map((id) => this.retryJob(id, queue)));\n }\n\n public async removeManyJobs(jobIds: string[], queue?: string): Promise<void> {\n await Promise.all(jobIds.map((id) => this.removeJob(id, queue)));\n }\n\n public async getQueueInfo(\n queue: string,\n ): Promise<IgniterJobsQueueInfo | null> {\n const counts = await this.getQueueJobCounts(queue);\n return {\n name: queue,\n isPaused: this.pausedQueues.has(queue),\n jobCounts: counts,\n };\n }\n\n public async getQueueJobCounts(queue: string): Promise<IgniterJobCounts> {\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n const counts: IgniterJobCounts = {\n waiting: 0,\n active: 0,\n completed: 0,\n failed: 0,\n delayed: 0,\n paused: 0,\n };\n for (const id of jobIds) {\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (job.status in counts) {\n (counts as any)[job.status]++;\n }\n }\n return counts;\n }\n\n public async listQueues(): Promise<IgniterJobsQueueInfo[]> {\n const queues = Array.from(\n new Set([\n ...this.jobsByQueue.keys(),\n ...this.registeredJobs.keys(),\n ...this.registeredCrons.keys(),\n ]),\n );\n const result: IgniterJobsQueueInfo[] = [];\n for (const q of queues) {\n result.push((await this.getQueueInfo(q))!);\n }\n return result;\n }\n\n public async pauseQueue(queue: string): Promise<void> {\n this.pausedQueues.add(queue);\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n for (const id of jobIds) {\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (job.status === \"waiting\") job.status = \"paused\";\n }\n }\n\n public async resumeQueue(queue: string): Promise<void> {\n this.pausedQueues.delete(queue);\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n for (const id of jobIds) {\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (job.status === \"paused\") job.status = \"waiting\";\n }\n void this.kickWorkers(queue);\n }\n\n public async drainQueue(queue: string): Promise<number> {\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n let removed = 0;\n for (const id of jobIds) {\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (job.status === \"waiting\" || job.status === \"paused\") {\n this.jobsById.delete(id);\n removed++;\n }\n }\n this.jobsByQueue.set(\n queue,\n jobIds.filter((id) => this.jobsById.has(id)),\n );\n return removed;\n }\n\n public async cleanQueue(\n queue: string,\n options: IgniterJobsQueueCleanOptions,\n ): Promise<number> {\n const statuses = Array.isArray(options.status)\n ? options.status\n : [options.status];\n const olderThan = options.olderThan ?? 0;\n const limit = options.limit ?? Number.POSITIVE_INFINITY;\n\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n const now = Date.now();\n let cleaned = 0;\n\n for (const id of [...jobIds]) {\n if (cleaned >= limit) break;\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (!statuses.includes(job.status)) continue;\n const ageMs = now - job.createdAt.getTime();\n if (ageMs < olderThan) continue;\n this.jobsById.delete(id);\n cleaned++;\n }\n\n this.jobsByQueue.set(\n queue,\n jobIds.filter((id) => this.jobsById.has(id)),\n );\n return cleaned;\n }\n\n public async obliterateQueue(\n queue: string,\n options?: { force?: boolean },\n ): Promise<void> {\n void options;\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n for (const id of jobIds) this.jobsById.delete(id);\n this.jobsByQueue.delete(queue);\n this.registeredJobs.delete(queue);\n this.registeredCrons.delete(queue);\n this.pausedQueues.delete(queue);\n }\n\n public async retryAllInQueue(queue: string): Promise<number> {\n const jobIds = this.jobsByQueue.get(queue) ?? [];\n let retried = 0;\n for (const id of jobIds) {\n const job = this.jobsById.get(id);\n if (!job) continue;\n if (job.status === \"failed\") {\n await this.retryJob(id, queue);\n retried++;\n }\n }\n return retried;\n }\n\n public async searchJobs(filter: any): Promise<IgniterJobSearchResult[]> {\n const queue = filter?.queue as string | undefined;\n const statuses: IgniterJobStatus[] | undefined = filter?.status;\n const limit = filter?.limit ?? 100;\n const offset = filter?.offset ?? 0;\n\n const all = Array.from(this.jobsById.values())\n .filter((j) => (queue ? j.queue === queue : true))\n .filter((j) => (statuses ? statuses.includes(j.status) : true))\n .sort(\n (a, b) =>\n b.priority - a.priority ||\n a.createdAt.getTime() - b.createdAt.getTime(),\n );\n\n return all.slice(offset, offset + limit).map((j) => this.toSearchResult(j));\n }\n\n public async searchQueues(filter: any): Promise<IgniterJobsQueueInfo[]> {\n const name = filter?.name as string | undefined;\n const isPaused = filter?.isPaused as boolean | undefined;\n const all = await this.listQueues();\n return all\n .filter((q) => (name ? q.name.includes(name) : true))\n .filter((q) =>\n typeof isPaused === \"boolean\" ? q.isPaused === isPaused : true,\n );\n }\n\n public async searchWorkers(filter: any): Promise<IgniterJobsWorkerHandle[]> {\n const queue = filter?.queue as string | undefined;\n const isRunning = filter?.isRunning as boolean | undefined;\n return Array.from(this.workers.values())\n .filter((w) => (queue ? w.queues.includes(queue) : true))\n .filter((w) =>\n typeof isRunning === \"boolean\"\n ? isRunning\n ? !w.closed\n : w.closed\n : true,\n )\n .map((w) => this.toWorkerHandle(w));\n }\n\n public async createWorker(\n config: IgniterJobsWorkerBuilderConfig,\n ): Promise<IgniterJobsWorkerHandle> {\n const workerId = IgniterJobsIdGenerator.generate(\"worker\");\n const state: MemoryWorkerState = {\n id: workerId,\n queues: config.queues ?? [],\n concurrency: config.concurrency ?? 1,\n paused: false,\n closed: false,\n startedAt: new Date(),\n metrics: { processed: 0, failed: 0, totalDuration: 0 },\n handlers: config.handlers,\n };\n this.workers.set(workerId, state);\n\n // Kick initial processing.\n for (const q of state.queues) void this.kickWorkers(q);\n\n return this.toWorkerHandle(state);\n }\n\n public getWorkers(): Map<string, IgniterJobsWorkerHandle> {\n const out = new Map<string, IgniterJobsWorkerHandle>();\n for (const [id, state] of this.workers)\n out.set(id, this.toWorkerHandle(state));\n return out;\n }\n\n public async publishEvent(channel: string, payload: unknown): Promise<void> {\n const handlers = this.subscribers.get(channel);\n if (!handlers) return;\n await Promise.all(Array.from(handlers).map(async (h) => h(payload as any)));\n }\n\n public async subscribeEvent(\n channel: string,\n handler: IgniterJobsEventHandler,\n ): Promise<() => Promise<void>> {\n const set =\n this.subscribers.get(channel) ?? new Set<IgniterJobsEventHandler>();\n set.add(handler);\n this.subscribers.set(channel, set);\n\n return async () => {\n const current = this.subscribers.get(channel);\n if (!current) return;\n current.delete(handler);\n if (current.size === 0) this.subscribers.delete(channel);\n };\n }\n\n public async writeJobStreamEvent(\n params: IgniterJobsAdapterJobStreamWriteParams,\n ): Promise<string> {\n const key = this.getStreamKey(params.queue, params.jobId);\n const record = this.streamRecords.get(key) ?? { events: [], nextId: 1 };\n const id = String(record.nextId++);\n const event: IgniterJobsJobStreamEvent<string, unknown> = {\n ...params.event,\n id,\n };\n\n if (params.persistence?.enabled) {\n record.events.push(event);\n const maxEvents = params.persistence.maxEvents;\n if (\n typeof maxEvents === \"number\" &&\n maxEvents > 0 &&\n record.events.length > maxEvents\n ) {\n record.events.splice(0, record.events.length - maxEvents);\n }\n this.streamRecords.set(key, record);\n } else if (!this.streamRecords.has(key)) {\n this.streamRecords.set(key, record);\n }\n\n const handlers = this.streamSubscribers.get(key);\n if (handlers?.size) {\n await Promise.all(\n Array.from(handlers).map(async (handler) => handler(event)),\n );\n }\n\n return id;\n }\n\n public async readJobStream(\n params: IgniterJobsAdapterJobStreamReadParams,\n ): Promise<\n IgniterJobsJobStreamReadResult<IgniterJobsJobStreamEvent<string, unknown>>\n > {\n const key = this.getStreamKey(params.queue, params.jobId);\n const record = this.streamRecords.get(key);\n if (!record) {\n return { items: [], nextCursor: undefined, hasMore: false };\n }\n\n const after = params.after ? Number(params.after) : undefined;\n const limit = params.limit ?? 100;\n const filtered = record.events.filter((event) =>\n typeof after === \"number\" ? Number(event.id) > after : true,\n );\n const items = filtered.slice(0, limit);\n const hasMore = filtered.length > items.length;\n\n return {\n items,\n nextCursor: items.at(-1)?.id,\n hasMore,\n };\n }\n\n public async subscribeJobStream(\n params: IgniterJobsAdapterJobStreamSubscribeParams,\n ): Promise<() => Promise<void>> {\n const key = this.getStreamKey(params.queue, params.jobId);\n const set = this.streamSubscribers.get(key) ?? new Set();\n set.add(params.handler);\n this.streamSubscribers.set(key, set);\n\n return async () => {\n const current = this.streamSubscribers.get(key);\n if (!current) return;\n current.delete(params.handler);\n if (current.size === 0) this.streamSubscribers.delete(key);\n };\n }\n\n public async shutdown(): Promise<void> {\n this.workers.clear();\n this.subscribers.clear();\n this.streamSubscribers.clear();\n this.streamRecords.clear();\n }\n\n private toSearchResult(job: MemoryJob): IgniterJobSearchResult {\n return {\n id: job.id,\n name: job.name,\n queue: job.queue,\n status: job.status,\n input: job.input,\n result: job.result,\n error: job.error,\n progress: job.progress,\n attemptsMade: job.attemptsMade,\n priority: job.priority,\n createdAt: job.createdAt,\n startedAt: job.startedAt,\n completedAt: job.completedAt,\n metadata: job.metadata,\n scope: job.scope as any,\n };\n }\n\n private getStreamKey(queue: string, jobId: string): string {\n return `${queue}:${jobId}`;\n }\n\n private toWorkerHandle(worker: MemoryWorkerState): IgniterJobsWorkerHandle {\n return {\n id: worker.id,\n queues: worker.queues,\n pause: async () => {\n worker.paused = true;\n },\n resume: async () => {\n worker.paused = false;\n for (const q of worker.queues) void this.kickWorkers(q);\n },\n close: async () => {\n worker.closed = true;\n },\n isRunning: () => !worker.closed && !worker.paused,\n isPaused: () => worker.paused,\n isClosed: () => worker.closed,\n getMetrics: async () => this.toWorkerMetrics(worker),\n };\n }\n\n private toWorkerMetrics(worker: MemoryWorkerState): IgniterJobsWorkerMetrics {\n const uptime = Date.now() - worker.startedAt.getTime();\n const processed = worker.metrics.processed;\n return {\n processed,\n failed: worker.metrics.failed,\n avgDuration: processed > 0 ? worker.metrics.totalDuration / processed : 0,\n concurrency: worker.concurrency,\n uptime,\n };\n }\n\n private async kickWorkers(queue: string): Promise<void> {\n if (this.pausedQueues.has(queue)) return;\n const relevant = Array.from(this.workers.values()).filter(\n (w) =>\n !w.closed &&\n !w.paused &&\n (w.queues.length === 0 || w.queues.includes(queue)),\n );\n if (relevant.length === 0) return;\n\n for (const w of relevant) {\n void this.processLoop(w, queue);\n }\n }\n\n private async processLoop(\n worker: MemoryWorkerState,\n queue: string,\n ): Promise<void> {\n if (worker.closed || worker.paused) return;\n const concurrency = Math.max(1, worker.concurrency);\n\n const running = (worker as any).__running as number | undefined;\n const currentRunning = running ?? 0;\n if (currentRunning >= concurrency) return;\n (worker as any).__running = currentRunning + 1;\n\n try {\n const next = this.nextJob(queue);\n if (!next) return;\n await this.processJob(worker, next);\n } finally {\n (worker as any).__running = ((worker as any).__running as number) - 1;\n // Continue draining if more work exists.\n if (this.nextJob(queue)) void this.processLoop(worker, queue);\n else if (worker.handlers?.onIdle) await worker.handlers.onIdle();\n }\n }\n\n private nextJob(queue: string): MemoryJob | null {\n const ids = this.jobsByQueue.get(queue) ?? [];\n const candidates = ids\n .map((id) => this.jobsById.get(id))\n .filter((j): j is MemoryJob => Boolean(j))\n .filter((j) => j.status === \"waiting\")\n .sort(\n (a, b) =>\n b.priority - a.priority ||\n a.createdAt.getTime() - b.createdAt.getTime(),\n );\n return candidates[0] ?? null;\n }\n\n private async processJob(\n worker: MemoryWorkerState,\n job: MemoryJob,\n ): Promise<void> {\n if (this.pausedQueues.has(job.queue)) {\n job.status = \"paused\";\n return;\n }\n\n job.status = \"active\";\n job.startedAt = new Date();\n job.attemptsMade += 1;\n job.logs.push({\n timestamp: new Date(),\n level: \"info\",\n message: \"Job started\",\n });\n\n if (worker.handlers?.onActive)\n await worker.handlers.onActive({ job: this.toSearchResult(job) });\n\n const start = Date.now();\n\n try {\n const definition = this.registeredJobs.get(job.queue)?.get(job.name);\n if (!definition) {\n throw new IgniterJobsError({\n code: \"JOBS_NOT_REGISTERED\",\n message: `Job \"${job.name}\" is not registered for queue \"${job.queue}\".`,\n });\n }\n\n if (definition.onStart) {\n await definition.onStart({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n updateProgress: async (progress: number, message?: string) => {\n job.progress = progress;\n if (message) {\n job.logs.push({\n timestamp: new Date(),\n level: \"info\",\n message,\n });\n }\n await definition.onProgress?.({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n },\n scope: job.scope as any,\n progress,\n message,\n } as any);\n },\n },\n scope: job.scope as any,\n startedAt: job.startedAt,\n } as any);\n }\n\n const updateProgress = async (progress: number, message?: string) => {\n job.progress = progress;\n if (message) {\n job.logs.push({\n timestamp: new Date(),\n level: \"info\",\n message,\n });\n }\n\n await definition.onProgress?.({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n updateProgress,\n },\n scope: job.scope as any,\n progress,\n message,\n } as any);\n };\n\n const result = await definition.handler({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n updateProgress,\n },\n scope: job.scope as any,\n } as any);\n\n const duration = Date.now() - start;\n job.status = \"completed\";\n job.completedAt = new Date();\n job.result = result;\n job.progress = 100;\n job.logs.push({\n timestamp: new Date(),\n level: \"info\",\n message: `Job completed in ${duration}ms`,\n });\n\n worker.metrics.processed += 1;\n worker.metrics.totalDuration += duration;\n\n if (definition.onSuccess) {\n await definition.onSuccess({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n updateProgress,\n },\n scope: job.scope as any,\n result,\n duration,\n } as any);\n }\n\n if (worker.handlers?.onSuccess)\n await worker.handlers.onSuccess({\n job: this.toSearchResult(job),\n result,\n });\n } catch (error: any) {\n const duration = Date.now() - start;\n job.error = error?.message ?? String(error);\n job.logs.push({\n timestamp: new Date(),\n level: \"error\",\n message: job.error ?? \"Unknown error\",\n });\n\n const isFinalAttempt = job.attemptsMade >= job.maxAttempts;\n if (isFinalAttempt) {\n job.status = \"failed\";\n job.completedAt = new Date();\n worker.metrics.failed += 1;\n\n const definition = this.registeredJobs.get(job.queue)?.get(job.name);\n if (definition?.onFailure) {\n await definition.onFailure({\n input: job.input as any,\n context: {} as any,\n job: {\n id: job.id,\n name: job.name,\n queue: job.queue,\n attemptsMade: job.attemptsMade,\n metadata: job.metadata,\n updateProgress: async () => undefined,\n },\n scope: job.scope as any,\n error,\n isFinalAttempt: true,\n } as any);\n }\n\n if (worker.handlers?.onFailure)\n await worker.handlers.onFailure({\n job: this.toSearchResult(job),\n error,\n });\n } else {\n job.status = \"waiting\";\n void this.kickWorkers(job.queue);\n }\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as IgniterJobsAdapter, X as IgniterJobsQueueManager, C as IgniterJobsBullMQAdapterOptions, c as IgniterJobDefinition, r as IgniterCronDefinition, x as IgniterJobsAdapterDispatchParams, B as IgniterJobsAdapterScheduleParams, g as IgniterJobSearchResult, m as IgniterJobStatus, Q as IgniterJobsJobLog, h as IgniterJobsQueueInfo, l as IgniterJobsQueueCleanOptions, i as IgniterJobsWorkerHandle, d as IgniterJobsWorkerBuilderConfig, f as IgniterJobsEventHandler, A as IgniterJobsAdapterJobStreamWriteParams, y as IgniterJobsAdapterJobStreamReadParams, V as IgniterJobsJobStreamReadResult, S as IgniterJobsJobStreamEvent, z as IgniterJobsAdapterJobStreamSubscribeParams } from '../adapter-DDyMVche.mjs';
|
|
2
2
|
import 'ioredis';
|
|
3
3
|
import '@igniter-js/common';
|
|
4
4
|
|
|
@@ -52,8 +52,6 @@ declare class IgniterJobsBullMQAdapter implements IgniterJobsAdapter {
|
|
|
52
52
|
force?: boolean;
|
|
53
53
|
}): Promise<void>;
|
|
54
54
|
retryAllInQueue(queue: string): Promise<number>;
|
|
55
|
-
pauseJobType(queue: string, jobName: string): Promise<void>;
|
|
56
|
-
resumeJobType(queue: string, jobName: string): Promise<void>;
|
|
57
55
|
searchJobs(filter: any): Promise<IgniterJobSearchResult[]>;
|
|
58
56
|
searchQueues(filter: any): Promise<IgniterJobsQueueInfo[]>;
|
|
59
57
|
searchWorkers(filter: any): Promise<IgniterJobsWorkerHandle[]>;
|
|
@@ -61,10 +59,17 @@ declare class IgniterJobsBullMQAdapter implements IgniterJobsAdapter {
|
|
|
61
59
|
getWorkers(): Map<string, IgniterJobsWorkerHandle>;
|
|
62
60
|
publishEvent(channel: string, payload: unknown): Promise<void>;
|
|
63
61
|
subscribeEvent(channel: string, handler: IgniterJobsEventHandler): Promise<() => Promise<void>>;
|
|
62
|
+
writeJobStreamEvent(params: IgniterJobsAdapterJobStreamWriteParams): Promise<string>;
|
|
63
|
+
readJobStream(params: IgniterJobsAdapterJobStreamReadParams): Promise<IgniterJobsJobStreamReadResult<IgniterJobsJobStreamEvent<string, unknown>>>;
|
|
64
|
+
subscribeJobStream(params: IgniterJobsAdapterJobStreamSubscribeParams): Promise<() => Promise<void>>;
|
|
64
65
|
shutdown(): Promise<void>;
|
|
65
66
|
private core;
|
|
66
67
|
private executor;
|
|
67
68
|
private toCoreQueueName;
|
|
69
|
+
private getJobStreamChannel;
|
|
70
|
+
private getJobStreamListKey;
|
|
71
|
+
private getJobStreamSequenceKey;
|
|
72
|
+
private parseJobStreamRow;
|
|
68
73
|
private mapQueueInfo;
|
|
69
74
|
private fromCoreQueueName;
|
|
70
75
|
private mapJob;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as IgniterJobsAdapter, X as IgniterJobsQueueManager, C as IgniterJobsBullMQAdapterOptions, c as IgniterJobDefinition, r as IgniterCronDefinition, x as IgniterJobsAdapterDispatchParams, B as IgniterJobsAdapterScheduleParams, g as IgniterJobSearchResult, m as IgniterJobStatus, Q as IgniterJobsJobLog, h as IgniterJobsQueueInfo, l as IgniterJobsQueueCleanOptions, i as IgniterJobsWorkerHandle, d as IgniterJobsWorkerBuilderConfig, f as IgniterJobsEventHandler, A as IgniterJobsAdapterJobStreamWriteParams, y as IgniterJobsAdapterJobStreamReadParams, V as IgniterJobsJobStreamReadResult, S as IgniterJobsJobStreamEvent, z as IgniterJobsAdapterJobStreamSubscribeParams } from '../adapter-DDyMVche.js';
|
|
2
2
|
import 'ioredis';
|
|
3
3
|
import '@igniter-js/common';
|
|
4
4
|
|
|
@@ -52,8 +52,6 @@ declare class IgniterJobsBullMQAdapter implements IgniterJobsAdapter {
|
|
|
52
52
|
force?: boolean;
|
|
53
53
|
}): Promise<void>;
|
|
54
54
|
retryAllInQueue(queue: string): Promise<number>;
|
|
55
|
-
pauseJobType(queue: string, jobName: string): Promise<void>;
|
|
56
|
-
resumeJobType(queue: string, jobName: string): Promise<void>;
|
|
57
55
|
searchJobs(filter: any): Promise<IgniterJobSearchResult[]>;
|
|
58
56
|
searchQueues(filter: any): Promise<IgniterJobsQueueInfo[]>;
|
|
59
57
|
searchWorkers(filter: any): Promise<IgniterJobsWorkerHandle[]>;
|
|
@@ -61,10 +59,17 @@ declare class IgniterJobsBullMQAdapter implements IgniterJobsAdapter {
|
|
|
61
59
|
getWorkers(): Map<string, IgniterJobsWorkerHandle>;
|
|
62
60
|
publishEvent(channel: string, payload: unknown): Promise<void>;
|
|
63
61
|
subscribeEvent(channel: string, handler: IgniterJobsEventHandler): Promise<() => Promise<void>>;
|
|
62
|
+
writeJobStreamEvent(params: IgniterJobsAdapterJobStreamWriteParams): Promise<string>;
|
|
63
|
+
readJobStream(params: IgniterJobsAdapterJobStreamReadParams): Promise<IgniterJobsJobStreamReadResult<IgniterJobsJobStreamEvent<string, unknown>>>;
|
|
64
|
+
subscribeJobStream(params: IgniterJobsAdapterJobStreamSubscribeParams): Promise<() => Promise<void>>;
|
|
64
65
|
shutdown(): Promise<void>;
|
|
65
66
|
private core;
|
|
66
67
|
private executor;
|
|
67
68
|
private toCoreQueueName;
|
|
69
|
+
private getJobStreamChannel;
|
|
70
|
+
private getJobStreamListKey;
|
|
71
|
+
private getJobStreamSequenceKey;
|
|
72
|
+
private parseJobStreamRow;
|
|
68
73
|
private mapQueueInfo;
|
|
69
74
|
private fromCoreQueueName;
|
|
70
75
|
private mapJob;
|