groupmq-plus 1.1.1 → 1.1.2
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/dist/index.cjs +91 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -6
- package/dist/index.d.ts +40 -6
- package/dist/index.js +91 -7
- package/dist/index.js.map +1 -1
- package/dist/lua/change-delay.lua +20 -13
- package/dist/lua/clean-status.lua +13 -4
- package/dist/lua/enqueue-flow.lua +4 -0
- package/dist/lua/remove.lua +13 -3
- package/dist/lua/reserve.lua +2 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -37,6 +37,7 @@ declare class Job<T = any> {
|
|
|
37
37
|
readonly timestamp: number;
|
|
38
38
|
readonly orderMs?: number;
|
|
39
39
|
readonly status: Status$1 | 'unknown';
|
|
40
|
+
readonly parentId?: string;
|
|
40
41
|
constructor(args: {
|
|
41
42
|
queue: Queue<T>;
|
|
42
43
|
id: string;
|
|
@@ -56,6 +57,7 @@ declare class Job<T = any> {
|
|
|
56
57
|
timestamp: number;
|
|
57
58
|
orderMs?: number;
|
|
58
59
|
status?: Status$1 | 'unknown';
|
|
60
|
+
parentId?: string;
|
|
59
61
|
});
|
|
60
62
|
getState(): Promise<Status$1 | 'stuck' | 'waiting-children' | 'prioritized' | 'unknown'>;
|
|
61
63
|
toJSON(): {
|
|
@@ -89,6 +91,26 @@ declare class Job<T = any> {
|
|
|
89
91
|
* @param timeoutMs Optional timeout in milliseconds (0 = no timeout)
|
|
90
92
|
*/
|
|
91
93
|
waitUntilFinished(timeoutMs?: number): Promise<unknown>;
|
|
94
|
+
/**
|
|
95
|
+
* Get all child jobs of this job (if it's a parent in a flow).
|
|
96
|
+
* @returns Array of child Job instances
|
|
97
|
+
*/
|
|
98
|
+
getChildren(): Promise<Job<any>[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Get the return values of all child jobs in a flow.
|
|
101
|
+
* @returns Object mapping child job IDs to their return values
|
|
102
|
+
*/
|
|
103
|
+
getChildrenValues(): Promise<Record<string, any>>;
|
|
104
|
+
/**
|
|
105
|
+
* Get the number of remaining child jobs that haven't completed yet.
|
|
106
|
+
* @returns Number of remaining dependencies, or null if not a parent job
|
|
107
|
+
*/
|
|
108
|
+
getDependenciesCount(): Promise<number | null>;
|
|
109
|
+
/**
|
|
110
|
+
* Get the parent job of this job (if it's a child in a flow).
|
|
111
|
+
* @returns Parent Job instance, or undefined if no parent or parent was deleted
|
|
112
|
+
*/
|
|
113
|
+
getParent(): Promise<Job<any> | undefined>;
|
|
92
114
|
static fromReserved<T = any>(queue: Queue<T>, reserved: ReservedJob<T>, meta?: {
|
|
93
115
|
processedOn?: number;
|
|
94
116
|
finishedOn?: number;
|
|
@@ -537,6 +559,18 @@ declare class Queue<T = any> {
|
|
|
537
559
|
* @returns An object mapping child job IDs to their results
|
|
538
560
|
*/
|
|
539
561
|
getFlowResults(parentId: string): Promise<Record<string, any>>;
|
|
562
|
+
/**
|
|
563
|
+
* Gets all child job IDs for a parent job in a flow.
|
|
564
|
+
* @param parentId The ID of the parent job
|
|
565
|
+
* @returns An array of child job IDs
|
|
566
|
+
*/
|
|
567
|
+
getFlowChildrenIds(parentId: string): Promise<string[]>;
|
|
568
|
+
/**
|
|
569
|
+
* Gets all child jobs for a parent job in a flow.
|
|
570
|
+
* @param parentId The ID of the parent job
|
|
571
|
+
* @returns An array of Job instances for all children
|
|
572
|
+
*/
|
|
573
|
+
getFlowChildren(parentId: string): Promise<Job<any>[]>;
|
|
540
574
|
private addSingle;
|
|
541
575
|
private flushBatch;
|
|
542
576
|
reserve(): Promise<ReservedJob<T> | null>;
|
|
@@ -967,10 +1001,10 @@ type WorkerOptions<T> = {
|
|
|
967
1001
|
name?: string;
|
|
968
1002
|
/**
|
|
969
1003
|
* The function that processes jobs. Must be async and handle job failures gracefully.
|
|
970
|
-
* @param job The
|
|
1004
|
+
* @param job The Job instance to process, with access to all Job methods
|
|
971
1005
|
* @returns Promise that resolves when job is complete
|
|
972
1006
|
*/
|
|
973
|
-
handler: (job:
|
|
1007
|
+
handler: (job: Job<T>) => Promise<unknown>;
|
|
974
1008
|
/**
|
|
975
1009
|
* Heartbeat interval in milliseconds to keep jobs alive during processing.
|
|
976
1010
|
* Prevents jobs from timing out during long-running operations.
|
|
@@ -987,9 +1021,9 @@ type WorkerOptions<T> = {
|
|
|
987
1021
|
/**
|
|
988
1022
|
* Error handler called when job processing fails or worker encounters errors
|
|
989
1023
|
* @param err The error that occurred
|
|
990
|
-
* @param job The
|
|
1024
|
+
* @param job The Job instance that failed (if applicable)
|
|
991
1025
|
*/
|
|
992
|
-
onError?: (err: unknown, job?:
|
|
1026
|
+
onError?: (err: unknown, job?: Job<T>) => void;
|
|
993
1027
|
/**
|
|
994
1028
|
* Maximum number of retry attempts for failed jobs at the worker level.
|
|
995
1029
|
* This overrides the queue's default maxAttempts setting.
|
|
@@ -1256,14 +1290,14 @@ declare class _Worker<T = any> extends TypedEventEmitter<WorkerEvents<T>> {
|
|
|
1256
1290
|
* For concurrency > 1, returns the oldest job in progress
|
|
1257
1291
|
*/
|
|
1258
1292
|
getCurrentJob(): {
|
|
1259
|
-
job:
|
|
1293
|
+
job: Job<T>;
|
|
1260
1294
|
processingTimeMs: number;
|
|
1261
1295
|
} | null;
|
|
1262
1296
|
/**
|
|
1263
1297
|
* Get information about all currently processing jobs
|
|
1264
1298
|
*/
|
|
1265
1299
|
getCurrentJobs(): Array<{
|
|
1266
|
-
job:
|
|
1300
|
+
job: Job<T>;
|
|
1267
1301
|
processingTimeMs: number;
|
|
1268
1302
|
}>;
|
|
1269
1303
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ declare class Job<T = any> {
|
|
|
37
37
|
readonly timestamp: number;
|
|
38
38
|
readonly orderMs?: number;
|
|
39
39
|
readonly status: Status$1 | 'unknown';
|
|
40
|
+
readonly parentId?: string;
|
|
40
41
|
constructor(args: {
|
|
41
42
|
queue: Queue<T>;
|
|
42
43
|
id: string;
|
|
@@ -56,6 +57,7 @@ declare class Job<T = any> {
|
|
|
56
57
|
timestamp: number;
|
|
57
58
|
orderMs?: number;
|
|
58
59
|
status?: Status$1 | 'unknown';
|
|
60
|
+
parentId?: string;
|
|
59
61
|
});
|
|
60
62
|
getState(): Promise<Status$1 | 'stuck' | 'waiting-children' | 'prioritized' | 'unknown'>;
|
|
61
63
|
toJSON(): {
|
|
@@ -89,6 +91,26 @@ declare class Job<T = any> {
|
|
|
89
91
|
* @param timeoutMs Optional timeout in milliseconds (0 = no timeout)
|
|
90
92
|
*/
|
|
91
93
|
waitUntilFinished(timeoutMs?: number): Promise<unknown>;
|
|
94
|
+
/**
|
|
95
|
+
* Get all child jobs of this job (if it's a parent in a flow).
|
|
96
|
+
* @returns Array of child Job instances
|
|
97
|
+
*/
|
|
98
|
+
getChildren(): Promise<Job<any>[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Get the return values of all child jobs in a flow.
|
|
101
|
+
* @returns Object mapping child job IDs to their return values
|
|
102
|
+
*/
|
|
103
|
+
getChildrenValues(): Promise<Record<string, any>>;
|
|
104
|
+
/**
|
|
105
|
+
* Get the number of remaining child jobs that haven't completed yet.
|
|
106
|
+
* @returns Number of remaining dependencies, or null if not a parent job
|
|
107
|
+
*/
|
|
108
|
+
getDependenciesCount(): Promise<number | null>;
|
|
109
|
+
/**
|
|
110
|
+
* Get the parent job of this job (if it's a child in a flow).
|
|
111
|
+
* @returns Parent Job instance, or undefined if no parent or parent was deleted
|
|
112
|
+
*/
|
|
113
|
+
getParent(): Promise<Job<any> | undefined>;
|
|
92
114
|
static fromReserved<T = any>(queue: Queue<T>, reserved: ReservedJob<T>, meta?: {
|
|
93
115
|
processedOn?: number;
|
|
94
116
|
finishedOn?: number;
|
|
@@ -537,6 +559,18 @@ declare class Queue<T = any> {
|
|
|
537
559
|
* @returns An object mapping child job IDs to their results
|
|
538
560
|
*/
|
|
539
561
|
getFlowResults(parentId: string): Promise<Record<string, any>>;
|
|
562
|
+
/**
|
|
563
|
+
* Gets all child job IDs for a parent job in a flow.
|
|
564
|
+
* @param parentId The ID of the parent job
|
|
565
|
+
* @returns An array of child job IDs
|
|
566
|
+
*/
|
|
567
|
+
getFlowChildrenIds(parentId: string): Promise<string[]>;
|
|
568
|
+
/**
|
|
569
|
+
* Gets all child jobs for a parent job in a flow.
|
|
570
|
+
* @param parentId The ID of the parent job
|
|
571
|
+
* @returns An array of Job instances for all children
|
|
572
|
+
*/
|
|
573
|
+
getFlowChildren(parentId: string): Promise<Job<any>[]>;
|
|
540
574
|
private addSingle;
|
|
541
575
|
private flushBatch;
|
|
542
576
|
reserve(): Promise<ReservedJob<T> | null>;
|
|
@@ -967,10 +1001,10 @@ type WorkerOptions<T> = {
|
|
|
967
1001
|
name?: string;
|
|
968
1002
|
/**
|
|
969
1003
|
* The function that processes jobs. Must be async and handle job failures gracefully.
|
|
970
|
-
* @param job The
|
|
1004
|
+
* @param job The Job instance to process, with access to all Job methods
|
|
971
1005
|
* @returns Promise that resolves when job is complete
|
|
972
1006
|
*/
|
|
973
|
-
handler: (job:
|
|
1007
|
+
handler: (job: Job<T>) => Promise<unknown>;
|
|
974
1008
|
/**
|
|
975
1009
|
* Heartbeat interval in milliseconds to keep jobs alive during processing.
|
|
976
1010
|
* Prevents jobs from timing out during long-running operations.
|
|
@@ -987,9 +1021,9 @@ type WorkerOptions<T> = {
|
|
|
987
1021
|
/**
|
|
988
1022
|
* Error handler called when job processing fails or worker encounters errors
|
|
989
1023
|
* @param err The error that occurred
|
|
990
|
-
* @param job The
|
|
1024
|
+
* @param job The Job instance that failed (if applicable)
|
|
991
1025
|
*/
|
|
992
|
-
onError?: (err: unknown, job?:
|
|
1026
|
+
onError?: (err: unknown, job?: Job<T>) => void;
|
|
993
1027
|
/**
|
|
994
1028
|
* Maximum number of retry attempts for failed jobs at the worker level.
|
|
995
1029
|
* This overrides the queue's default maxAttempts setting.
|
|
@@ -1256,14 +1290,14 @@ declare class _Worker<T = any> extends TypedEventEmitter<WorkerEvents<T>> {
|
|
|
1256
1290
|
* For concurrency > 1, returns the oldest job in progress
|
|
1257
1291
|
*/
|
|
1258
1292
|
getCurrentJob(): {
|
|
1259
|
-
job:
|
|
1293
|
+
job: Job<T>;
|
|
1260
1294
|
processingTimeMs: number;
|
|
1261
1295
|
} | null;
|
|
1262
1296
|
/**
|
|
1263
1297
|
* Get information about all currently processing jobs
|
|
1264
1298
|
*/
|
|
1265
1299
|
getCurrentJobs(): Array<{
|
|
1266
|
-
job:
|
|
1300
|
+
job: Job<T>;
|
|
1267
1301
|
processingTimeMs: number;
|
|
1268
1302
|
}>;
|
|
1269
1303
|
/**
|
package/dist/index.js
CHANGED
|
@@ -235,6 +235,7 @@ var Job = class Job {
|
|
|
235
235
|
this.timestamp = args.timestamp;
|
|
236
236
|
this.orderMs = args.orderMs;
|
|
237
237
|
this.status = args.status ?? "unknown";
|
|
238
|
+
this.parentId = args.parentId;
|
|
238
239
|
}
|
|
239
240
|
async getState() {
|
|
240
241
|
return this.status ?? "unknown";
|
|
@@ -283,6 +284,39 @@ var Job = class Job {
|
|
|
283
284
|
async waitUntilFinished(timeoutMs = 0) {
|
|
284
285
|
return this.queue.waitUntilFinished(this.id, timeoutMs);
|
|
285
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Get all child jobs of this job (if it's a parent in a flow).
|
|
289
|
+
* @returns Array of child Job instances
|
|
290
|
+
*/
|
|
291
|
+
async getChildren() {
|
|
292
|
+
return this.queue.getFlowChildren(this.id);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Get the return values of all child jobs in a flow.
|
|
296
|
+
* @returns Object mapping child job IDs to their return values
|
|
297
|
+
*/
|
|
298
|
+
async getChildrenValues() {
|
|
299
|
+
return this.queue.getFlowResults(this.id);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get the number of remaining child jobs that haven't completed yet.
|
|
303
|
+
* @returns Number of remaining dependencies, or null if not a parent job
|
|
304
|
+
*/
|
|
305
|
+
async getDependenciesCount() {
|
|
306
|
+
return this.queue.getFlowDependencies(this.id);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get the parent job of this job (if it's a child in a flow).
|
|
310
|
+
* @returns Parent Job instance, or undefined if no parent or parent was deleted
|
|
311
|
+
*/
|
|
312
|
+
async getParent() {
|
|
313
|
+
if (!this.parentId) return void 0;
|
|
314
|
+
try {
|
|
315
|
+
return await this.queue.getJob(this.parentId);
|
|
316
|
+
} catch (_e) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
286
320
|
static fromReserved(queue, reserved, meta) {
|
|
287
321
|
return new Job({
|
|
288
322
|
queue,
|
|
@@ -322,6 +356,7 @@ var Job = class Job {
|
|
|
322
356
|
const failedReason = (raw.failedReason ?? raw.lastErrorMessage) || void 0;
|
|
323
357
|
const stacktrace = (raw.stacktrace ?? raw.lastErrorStack) || void 0;
|
|
324
358
|
const returnvalue = raw.returnvalue ? safeJsonParse$1(raw.returnvalue) : void 0;
|
|
359
|
+
const parentId = raw.parentId || void 0;
|
|
325
360
|
return new Job({
|
|
326
361
|
queue,
|
|
327
362
|
id,
|
|
@@ -340,7 +375,8 @@ var Job = class Job {
|
|
|
340
375
|
returnvalue,
|
|
341
376
|
timestamp: timestampMs || Date.now(),
|
|
342
377
|
orderMs,
|
|
343
|
-
status: knownStatus ?? coerceStatus(raw.status)
|
|
378
|
+
status: knownStatus ?? coerceStatus(raw.status),
|
|
379
|
+
parentId
|
|
344
380
|
});
|
|
345
381
|
}
|
|
346
382
|
static async fromStore(queue, id) {
|
|
@@ -359,6 +395,7 @@ var Job = class Job {
|
|
|
359
395
|
const failedReason = (raw.failedReason ?? raw.lastErrorMessage) || void 0;
|
|
360
396
|
const stacktrace = (raw.stacktrace ?? raw.lastErrorStack) || void 0;
|
|
361
397
|
const returnvalue = raw.returnvalue ? safeJsonParse$1(raw.returnvalue) : void 0;
|
|
398
|
+
const parentId = raw.parentId || void 0;
|
|
362
399
|
const [inProcessing, inDelayed] = await Promise.all([queue.redis.zscore(`${queue.namespace}:processing`, id), queue.redis.zscore(`${queue.namespace}:delayed`, id)]);
|
|
363
400
|
let status = raw.status;
|
|
364
401
|
if (inProcessing !== null) status = "active";
|
|
@@ -384,7 +421,8 @@ var Job = class Job {
|
|
|
384
421
|
returnvalue,
|
|
385
422
|
timestamp: timestampMs || Date.now(),
|
|
386
423
|
orderMs,
|
|
387
|
-
status: coerceStatus(status)
|
|
424
|
+
status: coerceStatus(status),
|
|
425
|
+
parentId
|
|
388
426
|
});
|
|
389
427
|
}
|
|
390
428
|
};
|
|
@@ -632,6 +670,38 @@ var Queue = class {
|
|
|
632
670
|
}
|
|
633
671
|
return parsed;
|
|
634
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Gets all child job IDs for a parent job in a flow.
|
|
675
|
+
* @param parentId The ID of the parent job
|
|
676
|
+
* @returns An array of child job IDs
|
|
677
|
+
*/
|
|
678
|
+
async getFlowChildrenIds(parentId) {
|
|
679
|
+
return this.r.smembers(`${this.ns}:flow:children:${parentId}`);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Gets all child jobs for a parent job in a flow.
|
|
683
|
+
* @param parentId The ID of the parent job
|
|
684
|
+
* @returns An array of Job instances for all children
|
|
685
|
+
*/
|
|
686
|
+
async getFlowChildren(parentId) {
|
|
687
|
+
const ids = await this.getFlowChildrenIds(parentId);
|
|
688
|
+
if (ids.length === 0) return [];
|
|
689
|
+
const pipe = this.r.multi();
|
|
690
|
+
for (const id of ids) pipe.hgetall(`${this.ns}:job:${id}`);
|
|
691
|
+
const rows = await pipe.exec();
|
|
692
|
+
const jobs = [];
|
|
693
|
+
for (let i = 0; i < ids.length; i++) {
|
|
694
|
+
const id = ids[i];
|
|
695
|
+
const raw = rows?.[i]?.[1] || {};
|
|
696
|
+
if (!raw || Object.keys(raw).length === 0) {
|
|
697
|
+
this.logger.warn(`Skipping child job ${id} - not found (likely cleaned up)`);
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
const job = Job.fromRawHash(this, id, raw);
|
|
701
|
+
jobs.push(job);
|
|
702
|
+
}
|
|
703
|
+
return jobs;
|
|
704
|
+
}
|
|
635
705
|
async addSingle(opts) {
|
|
636
706
|
const now = Date.now();
|
|
637
707
|
let delayUntil = 0;
|
|
@@ -2515,7 +2585,10 @@ var _Worker = class extends TypedEventEmitter {
|
|
|
2515
2585
|
const oldest = Array.from(this.jobsInProgress)[0];
|
|
2516
2586
|
const now = Date.now();
|
|
2517
2587
|
return {
|
|
2518
|
-
job: oldest.job,
|
|
2588
|
+
job: Job.fromReserved(this.q, oldest.job, {
|
|
2589
|
+
processedOn: oldest.ts,
|
|
2590
|
+
status: "active"
|
|
2591
|
+
}),
|
|
2519
2592
|
processingTimeMs: now - oldest.ts
|
|
2520
2593
|
};
|
|
2521
2594
|
}
|
|
@@ -2525,7 +2598,10 @@ var _Worker = class extends TypedEventEmitter {
|
|
|
2525
2598
|
getCurrentJobs() {
|
|
2526
2599
|
const now = Date.now();
|
|
2527
2600
|
return Array.from(this.jobsInProgress).map((item) => ({
|
|
2528
|
-
job: item.job,
|
|
2601
|
+
job: Job.fromReserved(this.q, item.job, {
|
|
2602
|
+
processedOn: item.ts,
|
|
2603
|
+
status: "active"
|
|
2604
|
+
}),
|
|
2529
2605
|
processingTimeMs: now - item.ts
|
|
2530
2606
|
}));
|
|
2531
2607
|
}
|
|
@@ -2555,7 +2631,7 @@ var _Worker = class extends TypedEventEmitter {
|
|
|
2555
2631
|
} catch (e) {
|
|
2556
2632
|
const isConnErr = this.q.isConnectionError(e);
|
|
2557
2633
|
if (!isConnErr || !this.stopping) this.logger.error(`Heartbeat error for job ${job.id}:`, e instanceof Error ? e.message : String(e));
|
|
2558
|
-
this.onError?.(e, job);
|
|
2634
|
+
this.onError?.(e, Job.fromReserved(this.q, job, { status: "active" }));
|
|
2559
2635
|
if (!isConnErr || !this.stopping) this.emit("error", e instanceof Error ? e : new Error(String(e)));
|
|
2560
2636
|
}
|
|
2561
2637
|
}, minInterval);
|
|
@@ -2566,7 +2642,11 @@ var _Worker = class extends TypedEventEmitter {
|
|
|
2566
2642
|
heartbeatDelayTimer = setTimeout(() => {
|
|
2567
2643
|
startHeartbeat();
|
|
2568
2644
|
}, heartbeatThreshold);
|
|
2569
|
-
const
|
|
2645
|
+
const jobInstance = Job.fromReserved(this.q, job, {
|
|
2646
|
+
processedOn: jobStartWallTime,
|
|
2647
|
+
status: "active"
|
|
2648
|
+
});
|
|
2649
|
+
const handlerResult = await this.handler(jobInstance);
|
|
2570
2650
|
if (heartbeatDelayTimer) clearTimeout(heartbeatDelayTimer);
|
|
2571
2651
|
if (hbTimer) clearInterval(hbTimer);
|
|
2572
2652
|
const finishedAtWall = Date.now();
|
|
@@ -2590,7 +2670,11 @@ var _Worker = class extends TypedEventEmitter {
|
|
|
2590
2670
|
* Handle job failure: emit events, retry or dead-letter
|
|
2591
2671
|
*/
|
|
2592
2672
|
async handleJobFailure(err, job, jobStartWallTime) {
|
|
2593
|
-
this.
|
|
2673
|
+
const jobInstance = Job.fromReserved(this.q, job, {
|
|
2674
|
+
processedOn: jobStartWallTime,
|
|
2675
|
+
status: "active"
|
|
2676
|
+
});
|
|
2677
|
+
this.onError?.(err, jobInstance);
|
|
2594
2678
|
this.blockingStats.consecutiveEmptyReserves = 0;
|
|
2595
2679
|
this.emptyReserveBackoffMs = 0;
|
|
2596
2680
|
try {
|