bunqueue 1.4.0 → 1.6.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/dist/application/dlqManager.d.ts +21 -4
- package/dist/application/dlqManager.d.ts.map +1 -1
- package/dist/application/dlqManager.js +168 -26
- package/dist/application/dlqManager.js.map +1 -1
- package/dist/application/operations/ack.js +1 -1
- package/dist/application/operations/ack.js.map +1 -1
- package/dist/application/operations/jobManagement.js +1 -1
- package/dist/application/operations/jobManagement.js.map +1 -1
- package/dist/application/operations/push.js +2 -2
- package/dist/application/operations/push.js.map +1 -1
- package/dist/application/queueManager.d.ts +18 -0
- package/dist/application/queueManager.d.ts.map +1 -1
- package/dist/application/queueManager.js +135 -1
- package/dist/application/queueManager.js.map +1 -1
- package/dist/cli/dashboard.d.ts +32 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +183 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/domain/queue/shard.d.ts +54 -13
- package/dist/domain/queue/shard.d.ts.map +1 -1
- package/dist/domain/queue/shard.js +163 -53
- package/dist/domain/queue/shard.js.map +1 -1
- package/dist/domain/types/dlq.d.ts +120 -0
- package/dist/domain/types/dlq.d.ts.map +1 -0
- package/dist/domain/types/dlq.js +77 -0
- package/dist/domain/types/dlq.js.map +1 -0
- package/dist/domain/types/stall.d.ts +49 -0
- package/dist/domain/types/stall.d.ts.map +1 -0
- package/dist/domain/types/stall.js +77 -0
- package/dist/domain/types/stall.js.map +1 -0
- package/dist/infrastructure/scheduler/cronScheduler.d.ts +8 -3
- package/dist/infrastructure/scheduler/cronScheduler.d.ts.map +1 -1
- package/dist/infrastructure/scheduler/cronScheduler.js +49 -26
- package/dist/infrastructure/scheduler/cronScheduler.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/shared/lru.d.ts +24 -4
- package/dist/shared/lru.d.ts.map +1 -1
- package/dist/shared/lru.js +187 -66
- package/dist/shared/lru.js.map +1 -1
- package/dist/shared/skipList.d.ts +95 -0
- package/dist/shared/skipList.d.ts.map +1 -0
- package/dist/shared/skipList.js +277 -0
- package/dist/shared/skipList.js.map +1 -0
- package/dist/shared/version.d.ts +2 -2
- package/dist/shared/version.d.ts.map +1 -1
- package/dist/shared/version.js +27 -2
- package/dist/shared/version.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Letter Queue Types
|
|
3
|
+
* Enhanced DLQ with metadata, auto-retry, and lifecycle management
|
|
4
|
+
*/
|
|
5
|
+
import type { Job } from './job';
|
|
6
|
+
/** Failure reason categories */
|
|
7
|
+
export declare const enum FailureReason {
|
|
8
|
+
/** Job explicitly failed via fail() call */
|
|
9
|
+
ExplicitFail = "explicit_fail",
|
|
10
|
+
/** Job exceeded max attempts */
|
|
11
|
+
MaxAttemptsExceeded = "max_attempts_exceeded",
|
|
12
|
+
/** Job timed out during processing */
|
|
13
|
+
Timeout = "timeout",
|
|
14
|
+
/** Job stalled (no heartbeat) */
|
|
15
|
+
Stalled = "stalled",
|
|
16
|
+
/** Job TTL expired */
|
|
17
|
+
TtlExpired = "ttl_expired",
|
|
18
|
+
/** Worker crashed/disconnected */
|
|
19
|
+
WorkerLost = "worker_lost",
|
|
20
|
+
/** Unknown/other reason */
|
|
21
|
+
Unknown = "unknown"
|
|
22
|
+
}
|
|
23
|
+
/** Single attempt record */
|
|
24
|
+
export interface AttemptRecord {
|
|
25
|
+
/** Attempt number (1-based) */
|
|
26
|
+
readonly attempt: number;
|
|
27
|
+
/** When this attempt started */
|
|
28
|
+
readonly startedAt: number;
|
|
29
|
+
/** When this attempt failed */
|
|
30
|
+
readonly failedAt: number;
|
|
31
|
+
/** Failure reason for this attempt */
|
|
32
|
+
readonly reason: FailureReason;
|
|
33
|
+
/** Error message if any */
|
|
34
|
+
readonly error: string | null;
|
|
35
|
+
/** Duration of this attempt in ms */
|
|
36
|
+
readonly duration: number;
|
|
37
|
+
}
|
|
38
|
+
/** DLQ Entry with full metadata */
|
|
39
|
+
export interface DlqEntry {
|
|
40
|
+
/** Original job */
|
|
41
|
+
readonly job: Job;
|
|
42
|
+
/** When first moved to DLQ */
|
|
43
|
+
readonly enteredAt: number;
|
|
44
|
+
/** Last failure reason */
|
|
45
|
+
readonly reason: FailureReason;
|
|
46
|
+
/** Last error message */
|
|
47
|
+
readonly error: string | null;
|
|
48
|
+
/** Full attempt history */
|
|
49
|
+
readonly attempts: AttemptRecord[];
|
|
50
|
+
/** Number of times retried from DLQ */
|
|
51
|
+
retryCount: number;
|
|
52
|
+
/** Last retry attempt from DLQ */
|
|
53
|
+
lastRetryAt: number | null;
|
|
54
|
+
/** Next scheduled auto-retry (null = no auto-retry) */
|
|
55
|
+
nextRetryAt: number | null;
|
|
56
|
+
/** Expires at (for auto-purge) */
|
|
57
|
+
readonly expiresAt: number | null;
|
|
58
|
+
}
|
|
59
|
+
/** DLQ configuration per queue */
|
|
60
|
+
export interface DlqConfig {
|
|
61
|
+
/** Enable auto-retry from DLQ */
|
|
62
|
+
autoRetry: boolean;
|
|
63
|
+
/** Auto-retry interval in ms (default: 1 hour) */
|
|
64
|
+
autoRetryInterval: number;
|
|
65
|
+
/** Max auto-retries before giving up (default: 3) */
|
|
66
|
+
maxAutoRetries: number;
|
|
67
|
+
/** Max age in ms before auto-purge (default: 7 days, null = never) */
|
|
68
|
+
maxAge: number | null;
|
|
69
|
+
/** Max entries per queue (default: 10000) */
|
|
70
|
+
maxEntries: number;
|
|
71
|
+
}
|
|
72
|
+
/** Default DLQ configuration */
|
|
73
|
+
export declare const DEFAULT_DLQ_CONFIG: DlqConfig;
|
|
74
|
+
/** Create a DLQ entry from a failed job */
|
|
75
|
+
export declare function createDlqEntry(job: Job, reason: FailureReason, error: string | null, config?: DlqConfig): DlqEntry;
|
|
76
|
+
/** Add attempt record to existing DLQ entry */
|
|
77
|
+
export declare function addAttemptRecord(entry: DlqEntry, reason: FailureReason, error: string | null): void;
|
|
78
|
+
/** Check if DLQ entry is expired */
|
|
79
|
+
export declare function isDlqEntryExpired(entry: DlqEntry, now?: number): boolean;
|
|
80
|
+
/** Check if DLQ entry can be auto-retried */
|
|
81
|
+
export declare function canAutoRetry(entry: DlqEntry, config: DlqConfig, now?: number): boolean;
|
|
82
|
+
/** Schedule next auto-retry */
|
|
83
|
+
export declare function scheduleNextRetry(entry: DlqEntry, config: DlqConfig): void;
|
|
84
|
+
/** DLQ filter options */
|
|
85
|
+
export interface DlqFilter {
|
|
86
|
+
/** Filter by failure reason */
|
|
87
|
+
reason?: FailureReason;
|
|
88
|
+
/** Filter by queue */
|
|
89
|
+
queue?: string;
|
|
90
|
+
/** Only entries older than this timestamp */
|
|
91
|
+
olderThan?: number;
|
|
92
|
+
/** Only entries newer than this timestamp */
|
|
93
|
+
newerThan?: number;
|
|
94
|
+
/** Only entries that can be retried */
|
|
95
|
+
retriable?: boolean;
|
|
96
|
+
/** Only entries that are expired */
|
|
97
|
+
expired?: boolean;
|
|
98
|
+
/** Limit results */
|
|
99
|
+
limit?: number;
|
|
100
|
+
/** Offset for pagination */
|
|
101
|
+
offset?: number;
|
|
102
|
+
}
|
|
103
|
+
/** DLQ statistics */
|
|
104
|
+
export interface DlqStats {
|
|
105
|
+
/** Total entries */
|
|
106
|
+
total: number;
|
|
107
|
+
/** Entries by reason */
|
|
108
|
+
byReason: Record<FailureReason, number>;
|
|
109
|
+
/** Entries by queue */
|
|
110
|
+
byQueue: Record<string, number>;
|
|
111
|
+
/** Entries awaiting auto-retry */
|
|
112
|
+
pendingRetry: number;
|
|
113
|
+
/** Expired entries (awaiting cleanup) */
|
|
114
|
+
expired: number;
|
|
115
|
+
/** Oldest entry timestamp */
|
|
116
|
+
oldestEntry: number | null;
|
|
117
|
+
/** Newest entry timestamp */
|
|
118
|
+
newestEntry: number | null;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=dlq.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dlq.d.ts","sourceRoot":"","sources":["../../../src/domain/types/dlq.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Letter Queue Types
|
|
3
|
+
* Enhanced DLQ with metadata, auto-retry, and lifecycle management
|
|
4
|
+
*/
|
|
5
|
+
/** Default DLQ configuration */
|
|
6
|
+
export const DEFAULT_DLQ_CONFIG = {
|
|
7
|
+
autoRetry: false,
|
|
8
|
+
autoRetryInterval: 60 * 60 * 1000, // 1 hour
|
|
9
|
+
maxAutoRetries: 3,
|
|
10
|
+
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
11
|
+
maxEntries: 10000,
|
|
12
|
+
};
|
|
13
|
+
/** Create a DLQ entry from a failed job */
|
|
14
|
+
export function createDlqEntry(job, reason, error, config = DEFAULT_DLQ_CONFIG) {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
const attemptRecord = {
|
|
17
|
+
attempt: job.attempts,
|
|
18
|
+
startedAt: job.startedAt ?? job.createdAt,
|
|
19
|
+
failedAt: now,
|
|
20
|
+
reason,
|
|
21
|
+
error,
|
|
22
|
+
duration: job.startedAt ? now - job.startedAt : 0,
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
job,
|
|
26
|
+
enteredAt: now,
|
|
27
|
+
reason,
|
|
28
|
+
error,
|
|
29
|
+
attempts: [attemptRecord],
|
|
30
|
+
retryCount: 0,
|
|
31
|
+
lastRetryAt: null,
|
|
32
|
+
nextRetryAt: config.autoRetry ? now + config.autoRetryInterval : null,
|
|
33
|
+
expiresAt: config.maxAge ? now + config.maxAge : null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Add attempt record to existing DLQ entry */
|
|
37
|
+
export function addAttemptRecord(entry, reason, error) {
|
|
38
|
+
const job = entry.job;
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
entry.attempts.push({
|
|
41
|
+
attempt: job.attempts,
|
|
42
|
+
startedAt: job.startedAt ?? now,
|
|
43
|
+
failedAt: now,
|
|
44
|
+
reason,
|
|
45
|
+
error,
|
|
46
|
+
duration: job.startedAt ? now - job.startedAt : 0,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** Check if DLQ entry is expired */
|
|
50
|
+
export function isDlqEntryExpired(entry, now = Date.now()) {
|
|
51
|
+
return entry.expiresAt !== null && now >= entry.expiresAt;
|
|
52
|
+
}
|
|
53
|
+
/** Check if DLQ entry can be auto-retried */
|
|
54
|
+
export function canAutoRetry(entry, config, now = Date.now()) {
|
|
55
|
+
if (!config.autoRetry)
|
|
56
|
+
return false;
|
|
57
|
+
if (entry.retryCount >= config.maxAutoRetries)
|
|
58
|
+
return false;
|
|
59
|
+
if (entry.nextRetryAt === null)
|
|
60
|
+
return false;
|
|
61
|
+
return now >= entry.nextRetryAt;
|
|
62
|
+
}
|
|
63
|
+
/** Schedule next auto-retry */
|
|
64
|
+
export function scheduleNextRetry(entry, config) {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
entry.retryCount++;
|
|
67
|
+
entry.lastRetryAt = now;
|
|
68
|
+
if (entry.retryCount < config.maxAutoRetries) {
|
|
69
|
+
// Exponential backoff for DLQ retries
|
|
70
|
+
const backoffMultiplier = Math.pow(2, entry.retryCount - 1);
|
|
71
|
+
entry.nextRetryAt = now + config.autoRetryInterval * backoffMultiplier;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
entry.nextRetryAt = null; // No more retries
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=dlq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dlq.js","sourceRoot":"","sources":["../../../src/domain/types/dlq.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stall Detection Types
|
|
3
|
+
* Configuration and handling for stalled jobs
|
|
4
|
+
*/
|
|
5
|
+
import type { Job } from './job';
|
|
6
|
+
/** Stall detection configuration per queue */
|
|
7
|
+
export interface StallConfig {
|
|
8
|
+
/** Enable stall detection (default: true) */
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/** Stall timeout in ms - job is stalled if no heartbeat (default: 30s) */
|
|
11
|
+
stallInterval: number;
|
|
12
|
+
/** Max stalls before moving to DLQ (default: 3) */
|
|
13
|
+
maxStalls: number;
|
|
14
|
+
/** Grace period after job start before stall detection (default: 5s) */
|
|
15
|
+
gracePeriod: number;
|
|
16
|
+
}
|
|
17
|
+
/** Default stall configuration */
|
|
18
|
+
export declare const DEFAULT_STALL_CONFIG: StallConfig;
|
|
19
|
+
/** Stall check result */
|
|
20
|
+
export interface StallCheckResult {
|
|
21
|
+
/** Is the job stalled? */
|
|
22
|
+
isStalled: boolean;
|
|
23
|
+
/** Time since last heartbeat in ms */
|
|
24
|
+
stalledFor: number;
|
|
25
|
+
/** Should move to DLQ? (exceeded max stalls) */
|
|
26
|
+
shouldMoveToDlq: boolean;
|
|
27
|
+
/** Stall count after this check */
|
|
28
|
+
newStallCount: number;
|
|
29
|
+
}
|
|
30
|
+
/** Check if a job is stalled */
|
|
31
|
+
export declare function checkStall(job: Job, config?: StallConfig, now?: number): StallCheckResult;
|
|
32
|
+
/** Stalled job action */
|
|
33
|
+
export declare const enum StallAction {
|
|
34
|
+
/** Retry the job */
|
|
35
|
+
Retry = "retry",
|
|
36
|
+
/** Move to DLQ */
|
|
37
|
+
MoveToDlq = "move_to_dlq",
|
|
38
|
+
/** Keep active (still within grace) */
|
|
39
|
+
Keep = "keep"
|
|
40
|
+
}
|
|
41
|
+
/** Determine action for stalled job */
|
|
42
|
+
export declare function getStallAction(job: Job, config?: StallConfig, now?: number): StallAction;
|
|
43
|
+
/** Update job heartbeat */
|
|
44
|
+
export declare function updateHeartbeat(job: Job, now?: number): void;
|
|
45
|
+
/** Reset stall count (after successful retry) */
|
|
46
|
+
export declare function resetStallCount(job: Job): void;
|
|
47
|
+
/** Increment stall count */
|
|
48
|
+
export declare function incrementStallCount(job: Job): number;
|
|
49
|
+
//# sourceMappingURL=stall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stall.d.ts","sourceRoot":"","sources":["../../../src/domain/types/stall.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,kCAAkC;AAClC,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAEF,yBAAyB;AACzB,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,eAAe,EAAE,OAAO,CAAC;IACzB,mCAAmC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CACxB,GAAG,EAAE,GAAG,EACR,MAAM,GAAE,WAAkC,EAC1C,GAAG,GAAE,MAAmB,GACvB,gBAAgB,CA4ClB;AAED,yBAAyB;AACzB,0BAAkB,WAAW;IAC3B,oBAAoB;IACpB,KAAK,UAAU;IACf,kBAAkB;IAClB,SAAS,gBAAgB;IACzB,uCAAuC;IACvC,IAAI,SAAS;CACd;AAED,uCAAuC;AACvC,wBAAgB,cAAc,CAC5B,GAAG,EAAE,GAAG,EACR,MAAM,GAAE,WAAkC,EAC1C,GAAG,GAAE,MAAmB,GACvB,WAAW,CAYb;AAED,2BAA2B;AAC3B,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAExE;AAED,iDAAiD;AACjD,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAE9C;AAED,4BAA4B;AAC5B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAGpD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stall Detection Types
|
|
3
|
+
* Configuration and handling for stalled jobs
|
|
4
|
+
*/
|
|
5
|
+
/** Default stall configuration */
|
|
6
|
+
export const DEFAULT_STALL_CONFIG = {
|
|
7
|
+
enabled: true,
|
|
8
|
+
stallInterval: 30_000, // 30 seconds
|
|
9
|
+
maxStalls: 3,
|
|
10
|
+
gracePeriod: 5_000, // 5 seconds
|
|
11
|
+
};
|
|
12
|
+
/** Check if a job is stalled */
|
|
13
|
+
export function checkStall(job, config = DEFAULT_STALL_CONFIG, now = Date.now()) {
|
|
14
|
+
// Not processing = not stalled
|
|
15
|
+
if (job.startedAt === null) {
|
|
16
|
+
return {
|
|
17
|
+
isStalled: false,
|
|
18
|
+
stalledFor: 0,
|
|
19
|
+
shouldMoveToDlq: false,
|
|
20
|
+
newStallCount: job.stallCount,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// Grace period - don't check immediately after start
|
|
24
|
+
if (now - job.startedAt < config.gracePeriod) {
|
|
25
|
+
return {
|
|
26
|
+
isStalled: false,
|
|
27
|
+
stalledFor: 0,
|
|
28
|
+
shouldMoveToDlq: false,
|
|
29
|
+
newStallCount: job.stallCount,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Use job-specific or default stall timeout
|
|
33
|
+
const stallInterval = job.stallTimeout ?? config.stallInterval;
|
|
34
|
+
const stalledFor = now - job.lastHeartbeat;
|
|
35
|
+
const isStalled = stalledFor > stallInterval;
|
|
36
|
+
if (!isStalled) {
|
|
37
|
+
return {
|
|
38
|
+
isStalled: false,
|
|
39
|
+
stalledFor,
|
|
40
|
+
shouldMoveToDlq: false,
|
|
41
|
+
newStallCount: job.stallCount,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const newStallCount = job.stallCount + 1;
|
|
45
|
+
const shouldMoveToDlq = newStallCount >= config.maxStalls;
|
|
46
|
+
return {
|
|
47
|
+
isStalled: true,
|
|
48
|
+
stalledFor,
|
|
49
|
+
shouldMoveToDlq,
|
|
50
|
+
newStallCount,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Determine action for stalled job */
|
|
54
|
+
export function getStallAction(job, config = DEFAULT_STALL_CONFIG, now = Date.now()) {
|
|
55
|
+
const result = checkStall(job, config, now);
|
|
56
|
+
if (!result.isStalled) {
|
|
57
|
+
return "keep" /* StallAction.Keep */;
|
|
58
|
+
}
|
|
59
|
+
if (result.shouldMoveToDlq) {
|
|
60
|
+
return "move_to_dlq" /* StallAction.MoveToDlq */;
|
|
61
|
+
}
|
|
62
|
+
return "retry" /* StallAction.Retry */;
|
|
63
|
+
}
|
|
64
|
+
/** Update job heartbeat */
|
|
65
|
+
export function updateHeartbeat(job, now = Date.now()) {
|
|
66
|
+
job.lastHeartbeat = now;
|
|
67
|
+
}
|
|
68
|
+
/** Reset stall count (after successful retry) */
|
|
69
|
+
export function resetStallCount(job) {
|
|
70
|
+
job.stallCount = 0;
|
|
71
|
+
}
|
|
72
|
+
/** Increment stall count */
|
|
73
|
+
export function incrementStallCount(job) {
|
|
74
|
+
job.stallCount++;
|
|
75
|
+
return job.stallCount;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=stall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stall.js","sourceRoot":"","sources":["../../../src/domain/types/stall.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,kCAAkC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,MAAM,EAAE,aAAa;IACpC,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,KAAK,EAAE,YAAY;CACjC,CAAC;AAcF,gCAAgC;AAChC,MAAM,UAAU,UAAU,CACxB,GAAQ,EACR,SAAsB,oBAAoB,EAC1C,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,+BAA+B;IAC/B,IAAI,GAAG,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,UAAU,EAAE,CAAC;YACb,eAAe,EAAE,KAAK;YACtB,aAAa,EAAE,GAAG,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,IAAI,GAAG,GAAG,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAC7C,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,UAAU,EAAE,CAAC;YACb,eAAe,EAAE,KAAK;YACtB,aAAa,EAAE,GAAG,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,aAAa,CAAC;IAC/D,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC;IAC3C,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;IAE7C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,UAAU;YACV,eAAe,EAAE,KAAK;YACtB,aAAa,EAAE,GAAG,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;IACzC,MAAM,eAAe,GAAG,aAAa,IAAI,MAAM,CAAC,SAAS,CAAC;IAE1D,OAAO;QACL,SAAS,EAAE,IAAI;QACf,UAAU;QACV,eAAe;QACf,aAAa;KACd,CAAC;AACJ,CAAC;AAYD,uCAAuC;AACvC,MAAM,UAAU,cAAc,CAC5B,GAAQ,EACR,SAAsB,oBAAoB,EAC1C,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAE5C,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,qCAAwB;IAC1B,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,iDAA6B;IAC/B,CAAC;IAED,uCAAyB;AAC3B,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,eAAe,CAAC,GAAQ,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAChE,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC;AAC1B,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,eAAe,CAAC,GAAQ;IACtC,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,4BAA4B;AAC5B,MAAM,UAAU,mBAAmB,CAAC,GAAQ;IAC1C,GAAG,CAAC,UAAU,EAAE,CAAC;IACjB,OAAO,GAAG,CAAC,UAAU,CAAC;AACxB,CAAC"}
|
|
@@ -15,13 +15,16 @@ export type PushJobCallback = (queue: string, input: JobInput) => Promise<void>;
|
|
|
15
15
|
* Cron Scheduler
|
|
16
16
|
* Periodically checks and executes due cron jobs
|
|
17
17
|
* Optimized with min-heap for O(k log n) tick where k = due crons
|
|
18
|
+
* Uses lazy deletion with generation numbers for O(1) remove
|
|
18
19
|
*/
|
|
19
20
|
export declare class CronScheduler {
|
|
20
21
|
private readonly config;
|
|
21
|
-
/** Map for O(1) lookup by name */
|
|
22
|
+
/** Map for O(1) lookup by name with generation tracking */
|
|
22
23
|
private readonly cronJobs;
|
|
23
24
|
/** Min-heap ordered by nextRun for O(k log n) tick */
|
|
24
25
|
private readonly cronHeap;
|
|
26
|
+
/** Current generation counter */
|
|
27
|
+
private generation;
|
|
25
28
|
private checkInterval;
|
|
26
29
|
private pushJob;
|
|
27
30
|
constructor(config?: CronSchedulerConfig);
|
|
@@ -42,7 +45,8 @@ export declare class CronScheduler {
|
|
|
42
45
|
*/
|
|
43
46
|
add(input: CronJobInput): CronJob;
|
|
44
47
|
/**
|
|
45
|
-
* Remove a cron job
|
|
48
|
+
* Remove a cron job - O(1) with lazy deletion
|
|
49
|
+
* The heap entry becomes stale and will be skipped in tick()
|
|
46
50
|
*/
|
|
47
51
|
remove(name: string): boolean;
|
|
48
52
|
/**
|
|
@@ -60,11 +64,12 @@ export declare class CronScheduler {
|
|
|
60
64
|
/**
|
|
61
65
|
* Check and execute due cron jobs
|
|
62
66
|
* O(k log n) where k = number of due crons, instead of O(n) full scan
|
|
67
|
+
* Skips stale entries (lazy deletion) automatically
|
|
63
68
|
*/
|
|
64
69
|
private tick;
|
|
65
70
|
/**
|
|
66
71
|
* Get scheduler stats
|
|
67
|
-
* O(1) for nextRun using min-heap peek
|
|
72
|
+
* O(1) for nextRun using min-heap peek (skips stale entries)
|
|
68
73
|
*/
|
|
69
74
|
getStats(): {
|
|
70
75
|
total: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cronScheduler.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/scheduler/cronScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAA4B,MAAM,yBAAyB,CAAC;AACpG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAUvD,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,6BAA6B;AAC7B,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cronScheduler.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/scheduler/cronScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAA4B,MAAM,yBAAyB,CAAC;AACpG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAUvD,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,6BAA6B;AAC7B,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQhF;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4D;IACrF,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyE;IAClG,iCAAiC;IACjC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,OAAO,CAAgC;gBAEnC,MAAM,GAAE,mBAAwB;IAI5C;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAIhD;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAoCjC;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU7B;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAItC;;OAEG;IACH,IAAI,IAAI,OAAO,EAAE;IAIjB;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI;IAY5B;;;;OAIG;YACW,IAAI;IA2ElB;;;OAGG;IACH,QAAQ,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CA4BvE"}
|
|
@@ -14,13 +14,16 @@ const DEFAULT_CONFIG = {
|
|
|
14
14
|
* Cron Scheduler
|
|
15
15
|
* Periodically checks and executes due cron jobs
|
|
16
16
|
* Optimized with min-heap for O(k log n) tick where k = due crons
|
|
17
|
+
* Uses lazy deletion with generation numbers for O(1) remove
|
|
17
18
|
*/
|
|
18
19
|
export class CronScheduler {
|
|
19
20
|
config;
|
|
20
|
-
/** Map for O(1) lookup by name */
|
|
21
|
+
/** Map for O(1) lookup by name with generation tracking */
|
|
21
22
|
cronJobs = new Map();
|
|
22
23
|
/** Min-heap ordered by nextRun for O(k log n) tick */
|
|
23
|
-
cronHeap = new MinHeap((a, b) => a.nextRun - b.nextRun);
|
|
24
|
+
cronHeap = new MinHeap((a, b) => a.cron.nextRun - b.cron.nextRun);
|
|
25
|
+
/** Current generation counter */
|
|
26
|
+
generation = 0;
|
|
24
27
|
checkInterval = null;
|
|
25
28
|
pushJob = null;
|
|
26
29
|
constructor(config = {}) {
|
|
@@ -78,23 +81,24 @@ export class CronScheduler {
|
|
|
78
81
|
else {
|
|
79
82
|
nextRun = getNextIntervalRun(input.repeatEvery, now);
|
|
80
83
|
}
|
|
81
|
-
// Create cron job
|
|
84
|
+
// Create cron job with generation tracking
|
|
82
85
|
const cron = createCronJob(input, nextRun);
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
86
|
+
const gen = this.generation++;
|
|
87
|
+
this.cronJobs.set(cron.name, { cron, generation: gen });
|
|
88
|
+
this.cronHeap.push({ cron, generation: gen });
|
|
85
89
|
cronLog.info('Added job', { name: cron.name, nextRun: new Date(nextRun).toISOString() });
|
|
86
90
|
return cron;
|
|
87
91
|
}
|
|
88
92
|
/**
|
|
89
|
-
* Remove a cron job
|
|
93
|
+
* Remove a cron job - O(1) with lazy deletion
|
|
94
|
+
* The heap entry becomes stale and will be skipped in tick()
|
|
90
95
|
*/
|
|
91
96
|
remove(name) {
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
97
|
+
const entry = this.cronJobs.get(name);
|
|
98
|
+
if (!entry)
|
|
94
99
|
return false;
|
|
100
|
+
// Just remove from map - heap entry becomes stale (lazy deletion)
|
|
95
101
|
this.cronJobs.delete(name);
|
|
96
|
-
// Remove from heap - O(n) but rare operation
|
|
97
|
-
this.cronHeap.removeWhere((c) => c.name === name);
|
|
98
102
|
cronLog.info('Removed job', { name });
|
|
99
103
|
return true;
|
|
100
104
|
}
|
|
@@ -102,28 +106,32 @@ export class CronScheduler {
|
|
|
102
106
|
* Get a cron job by name
|
|
103
107
|
*/
|
|
104
108
|
get(name) {
|
|
105
|
-
return this.cronJobs.get(name);
|
|
109
|
+
return this.cronJobs.get(name)?.cron;
|
|
106
110
|
}
|
|
107
111
|
/**
|
|
108
112
|
* List all cron jobs
|
|
109
113
|
*/
|
|
110
114
|
list() {
|
|
111
|
-
return Array.from(this.cronJobs.values());
|
|
115
|
+
return Array.from(this.cronJobs.values()).map((e) => e.cron);
|
|
112
116
|
}
|
|
113
117
|
/**
|
|
114
118
|
* Load cron jobs from storage
|
|
115
119
|
*/
|
|
116
120
|
load(crons) {
|
|
121
|
+
const entries = [];
|
|
117
122
|
for (const cron of crons) {
|
|
118
|
-
this.
|
|
123
|
+
const gen = this.generation++;
|
|
124
|
+
this.cronJobs.set(cron.name, { cron, generation: gen });
|
|
125
|
+
entries.push({ cron, generation: gen });
|
|
119
126
|
}
|
|
120
127
|
// Rebuild heap from loaded crons - O(n)
|
|
121
|
-
this.cronHeap.buildFrom(
|
|
128
|
+
this.cronHeap.buildFrom(entries);
|
|
122
129
|
cronLog.info('Loaded jobs', { count: crons.length });
|
|
123
130
|
}
|
|
124
131
|
/**
|
|
125
132
|
* Check and execute due cron jobs
|
|
126
133
|
* O(k log n) where k = number of due crons, instead of O(n) full scan
|
|
134
|
+
* Skips stale entries (lazy deletion) automatically
|
|
127
135
|
*/
|
|
128
136
|
async tick() {
|
|
129
137
|
if (!this.pushJob)
|
|
@@ -133,11 +141,18 @@ export class CronScheduler {
|
|
|
133
141
|
const toRemove = [];
|
|
134
142
|
// Process only due crons from heap - O(k log n)
|
|
135
143
|
while (!this.cronHeap.isEmpty) {
|
|
136
|
-
const
|
|
137
|
-
if (!
|
|
144
|
+
const entry = this.cronHeap.peek();
|
|
145
|
+
if (!entry || entry.cron.nextRun > now)
|
|
138
146
|
break;
|
|
139
147
|
// Remove from heap
|
|
140
148
|
this.cronHeap.pop();
|
|
149
|
+
// Check if stale (cron was removed or updated)
|
|
150
|
+
const current = this.cronJobs.get(entry.cron.name);
|
|
151
|
+
if (current?.generation !== entry.generation) {
|
|
152
|
+
// Stale entry, skip
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const cron = entry.cron;
|
|
141
156
|
// Check if at limit
|
|
142
157
|
if (isAtLimit(cron)) {
|
|
143
158
|
cronLog.info('Job reached execution limit', { name: cron.name });
|
|
@@ -160,8 +175,8 @@ export class CronScheduler {
|
|
|
160
175
|
else if (cron.repeatEvery) {
|
|
161
176
|
cron.nextRun = getNextIntervalRun(cron.repeatEvery, now);
|
|
162
177
|
}
|
|
163
|
-
// Re-insert with
|
|
164
|
-
toReinsert.push(
|
|
178
|
+
// Re-insert with same generation (not stale)
|
|
179
|
+
toReinsert.push(entry);
|
|
165
180
|
cronLog.info('Executed job', {
|
|
166
181
|
name: cron.name,
|
|
167
182
|
executions: cron.executions,
|
|
@@ -171,12 +186,12 @@ export class CronScheduler {
|
|
|
171
186
|
catch (err) {
|
|
172
187
|
cronLog.error('Failed to execute job', { name: cron.name, error: String(err) });
|
|
173
188
|
// Re-insert even on failure to retry next tick
|
|
174
|
-
toReinsert.push(
|
|
189
|
+
toReinsert.push(entry);
|
|
175
190
|
}
|
|
176
191
|
}
|
|
177
192
|
// Re-insert processed crons with updated nextRun
|
|
178
|
-
for (const
|
|
179
|
-
this.cronHeap.push(
|
|
193
|
+
for (const entry of toReinsert) {
|
|
194
|
+
this.cronHeap.push(entry);
|
|
180
195
|
}
|
|
181
196
|
// Remove limit-reached crons from map
|
|
182
197
|
for (const name of toRemove) {
|
|
@@ -185,15 +200,23 @@ export class CronScheduler {
|
|
|
185
200
|
}
|
|
186
201
|
/**
|
|
187
202
|
* Get scheduler stats
|
|
188
|
-
* O(1) for nextRun using min-heap peek
|
|
203
|
+
* O(1) for nextRun using min-heap peek (skips stale entries)
|
|
189
204
|
*/
|
|
190
205
|
getStats() {
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
206
|
+
// Find first non-stale entry for nextRun
|
|
207
|
+
let nextRun = null;
|
|
208
|
+
// Peek and skip stale entries to find valid nextRun
|
|
209
|
+
// This is typically O(1) as stale entries are cleaned during tick()
|
|
210
|
+
const entry = this.cronHeap.peek();
|
|
211
|
+
if (entry) {
|
|
212
|
+
const current = this.cronJobs.get(entry.cron.name);
|
|
213
|
+
if (current?.generation === entry.generation && !isAtLimit(entry.cron)) {
|
|
214
|
+
nextRun = entry.cron.nextRun;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
194
217
|
// Count pending (crons not at limit) - still O(n) but called rarely
|
|
195
218
|
let pending = 0;
|
|
196
|
-
for (const cron of this.cronJobs.values()) {
|
|
219
|
+
for (const { cron } of this.cronJobs.values()) {
|
|
197
220
|
if (!isAtLimit(cron)) {
|
|
198
221
|
pending++;
|
|
199
222
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cronScheduler.js","sourceRoot":"","sources":["../../../src/infrastructure/scheduler/cronScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAmC,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAO/C,MAAM,cAAc,GAAkC;IACpD,eAAe,EAAE,IAAI;CACtB,CAAC;
|
|
1
|
+
{"version":3,"file":"cronScheduler.js","sourceRoot":"","sources":["../../../src/infrastructure/scheduler/cronScheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/main.js
CHANGED
|
@@ -72,7 +72,7 @@ ${cyan} / /_/ / /_/ / / / / /_/ / /_/ / __/ /_/ / __/ ${reset}
|
|
|
72
72
|
${cyan}/_____/\\__,_/_/ /_/\\___\\_\\__,_/\\___/\\__,_/\\___/ ${reset}
|
|
73
73
|
${dim} v${VERSION}${reset}
|
|
74
74
|
|
|
75
|
-
${bold}High-performance job queue server
|
|
75
|
+
${bold}High-performance job queue server written in TypeScript${reset}
|
|
76
76
|
|
|
77
77
|
${dim}─────────────────────────────────────────────────${reset}
|
|
78
78
|
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|