@bitclaw/jobs 1.2.0 → 1.3.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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/queue.d.ts +12 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +57 -7
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +7 -5
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts +2 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +18 -17
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { JobQueue } from './queue';
|
|
|
4
4
|
export { SlidingWindowRateLimiter } from './rate-limiter';
|
|
5
5
|
export { Scheduler } from './scheduler';
|
|
6
6
|
export { applyPragmas, initializeSchema } from './schema';
|
|
7
|
-
export type { AddJobOptions, AddScheduleOptions, BatchOptions, FailedJob, Job, JobBatch, JobContext, JobMap, JobStats, JobStatus, ListJobsOptions, PaginatedResult, PurgeOptions, RateLimit, Schedule, WorkerOptions } from './types';
|
|
7
|
+
export type { AddJobOptions, AddScheduleOptions, BackoffConfig, BatchOptions, FailedJob, Job, JobBatch, JobContext, JobMap, JobStats, JobStatus, ListJobsOptions, PaginatedResult, PurgeOptions, RateLimit, Schedule, WorkerOptions } from './types';
|
|
8
8
|
export { NonRetryableError } from './types';
|
|
9
9
|
export { JobWorker } from './worker';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,GAAG,EACH,QAAQ,EACR,UAAU,EACV,MAAM,EACN,QAAQ,EACR,SAAS,EACT,eAAe,EACf,eAAe,EACf,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,GAAG,EACH,QAAQ,EACR,UAAU,EACV,MAAM,EACN,QAAQ,EACR,SAAS,EACT,eAAe,EACf,eAAe,EACf,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/queue.d.ts
CHANGED
|
@@ -57,6 +57,18 @@ export declare class JobQueue<TMap extends JobMap = Record<string, unknown>> {
|
|
|
57
57
|
type: K;
|
|
58
58
|
}): JobWorker<TMap, K>;
|
|
59
59
|
private insertJob;
|
|
60
|
+
/**
|
|
61
|
+
* Reset stuck `processing` jobs back to `pending`. Call at startup to recover
|
|
62
|
+
* from server crashes that left jobs claimed but never completed.
|
|
63
|
+
* @param thresholdMs Jobs processing longer than this (ms) are reset. Default 5min.
|
|
64
|
+
* @returns Number of jobs reset.
|
|
65
|
+
*/
|
|
66
|
+
reconcileStaleJobs(thresholdMs?: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* Look up a pending or processing job by its uniqueKey.
|
|
69
|
+
* Returns null if no such job exists (completed, dead-lettered, or never queued).
|
|
70
|
+
*/
|
|
71
|
+
getJobByUniqueKey(type: string, uniqueKey: string): Job | null;
|
|
60
72
|
close(): void;
|
|
61
73
|
private unblockDependents;
|
|
62
74
|
private handleBatchJobComplete;
|
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,OAAO,KAAK,EACV,aAAa,
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
|
package/dist/queue.js
CHANGED
|
@@ -89,8 +89,8 @@ export class JobQueue {
|
|
|
89
89
|
applyPragmas(this.db);
|
|
90
90
|
initializeSchema(this.db);
|
|
91
91
|
this.insertJobStmt = this.db.query(`
|
|
92
|
-
INSERT OR IGNORE INTO jobs (type, data, status, priority, max_retries, run_at, batch_id, unique_key)
|
|
93
|
-
VALUES ($type, $data, $status, $priority, $maxRetries, $runAt, $batchId, $uniqueKey)
|
|
92
|
+
INSERT OR IGNORE INTO jobs (type, data, status, priority, max_retries, run_at, batch_id, unique_key, backoff_config)
|
|
93
|
+
VALUES ($type, $data, $status, $priority, $maxRetries, $runAt, $batchId, $uniqueKey, $backoffConfig)
|
|
94
94
|
`);
|
|
95
95
|
this.selectDedupedJobStmt = this.db.query(`
|
|
96
96
|
SELECT id FROM jobs
|
|
@@ -121,6 +121,7 @@ export class JobQueue {
|
|
|
121
121
|
SET status = 'pending',
|
|
122
122
|
retry_count = retry_count + 1,
|
|
123
123
|
error = $error,
|
|
124
|
+
run_at = $runAt,
|
|
124
125
|
updated_at = $now
|
|
125
126
|
WHERE id = $id
|
|
126
127
|
`);
|
|
@@ -287,7 +288,8 @@ export class JobQueue {
|
|
|
287
288
|
$maxRetries: row.max_retries,
|
|
288
289
|
$runAt: now,
|
|
289
290
|
$batchId: null,
|
|
290
|
-
$uniqueKey: null
|
|
291
|
+
$uniqueKey: null,
|
|
292
|
+
$backoffConfig: null
|
|
291
293
|
});
|
|
292
294
|
const newJobId = this.lastInsertRowIdStmt.get();
|
|
293
295
|
this.db
|
|
@@ -390,7 +392,22 @@ export class JobQueue {
|
|
|
390
392
|
}
|
|
391
393
|
}
|
|
392
394
|
else {
|
|
393
|
-
|
|
395
|
+
const backoff = row.backoff_config
|
|
396
|
+
? JSON.parse(row.backoff_config)
|
|
397
|
+
: null;
|
|
398
|
+
let retryRunAt = now;
|
|
399
|
+
if (backoff) {
|
|
400
|
+
const delayMs = backoff.type === 'exponential'
|
|
401
|
+
? Math.min(backoff.delayMs * 2 ** row.retry_count, 3_600_000)
|
|
402
|
+
: backoff.delayMs;
|
|
403
|
+
retryRunAt = new Date(Date.now() + delayMs).toISOString();
|
|
404
|
+
}
|
|
405
|
+
this.markFailedStmt.run({
|
|
406
|
+
$id: id,
|
|
407
|
+
$error: error,
|
|
408
|
+
$runAt: retryRunAt,
|
|
409
|
+
$now: now
|
|
410
|
+
});
|
|
394
411
|
}
|
|
395
412
|
})();
|
|
396
413
|
}
|
|
@@ -446,7 +463,8 @@ export class JobQueue {
|
|
|
446
463
|
$maxRetries: options?.maxRetries ?? 3,
|
|
447
464
|
$runAt: runAt,
|
|
448
465
|
$batchId: batchId,
|
|
449
|
-
$uniqueKey: options?.uniqueKey ?? null
|
|
466
|
+
$uniqueKey: options?.uniqueKey ?? null,
|
|
467
|
+
$backoffConfig: options?.backoff ? JSON.stringify(options.backoff) : null
|
|
450
468
|
});
|
|
451
469
|
// INSERT OR IGNORE: if a pending/processing job with same (type, uniqueKey)
|
|
452
470
|
// already exists, the insert is a no-op. Return the existing job id.
|
|
@@ -472,6 +490,36 @@ export class JobQueue {
|
|
|
472
490
|
}
|
|
473
491
|
return jobId.id;
|
|
474
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Reset stuck `processing` jobs back to `pending`. Call at startup to recover
|
|
495
|
+
* from server crashes that left jobs claimed but never completed.
|
|
496
|
+
* @param thresholdMs Jobs processing longer than this (ms) are reset. Default 5min.
|
|
497
|
+
* @returns Number of jobs reset.
|
|
498
|
+
*/
|
|
499
|
+
reconcileStaleJobs(thresholdMs = 300_000) {
|
|
500
|
+
const cutoff = new Date(Date.now() - thresholdMs).toISOString();
|
|
501
|
+
const result = this.db
|
|
502
|
+
.query(`UPDATE jobs
|
|
503
|
+
SET status = 'pending',
|
|
504
|
+
error = 'stale: worker crash or restart — reset for retry',
|
|
505
|
+
updated_at = $now
|
|
506
|
+
WHERE status = 'processing' AND updated_at < $cutoff`)
|
|
507
|
+
.run({ $now: nowISO(), $cutoff: cutoff });
|
|
508
|
+
return result.changes;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Look up a pending or processing job by its uniqueKey.
|
|
512
|
+
* Returns null if no such job exists (completed, dead-lettered, or never queued).
|
|
513
|
+
*/
|
|
514
|
+
getJobByUniqueKey(type, uniqueKey) {
|
|
515
|
+
const row = this.db
|
|
516
|
+
.query(`SELECT * FROM jobs
|
|
517
|
+
WHERE type = $type AND unique_key = $uniqueKey
|
|
518
|
+
AND status IN ('pending', 'processing')
|
|
519
|
+
LIMIT 1`)
|
|
520
|
+
.get({ $type: type, $uniqueKey: uniqueKey });
|
|
521
|
+
return row ? toJob(row) : null;
|
|
522
|
+
}
|
|
475
523
|
close() {
|
|
476
524
|
try {
|
|
477
525
|
if (this.db.filename !== ':memory:' && this.db.filename !== '') {
|
|
@@ -522,7 +570,8 @@ export class JobQueue {
|
|
|
522
570
|
$maxRetries: 3,
|
|
523
571
|
$runAt: now,
|
|
524
572
|
$batchId: null,
|
|
525
|
-
$uniqueKey: null
|
|
573
|
+
$uniqueKey: null,
|
|
574
|
+
$backoffConfig: null
|
|
526
575
|
});
|
|
527
576
|
}
|
|
528
577
|
// Enqueue "finally" callback job regardless of failures
|
|
@@ -535,7 +584,8 @@ export class JobQueue {
|
|
|
535
584
|
$maxRetries: 3,
|
|
536
585
|
$runAt: now,
|
|
537
586
|
$batchId: null,
|
|
538
|
-
$uniqueKey: null
|
|
587
|
+
$uniqueKey: null,
|
|
588
|
+
$backoffConfig: null
|
|
539
589
|
});
|
|
540
590
|
}
|
|
541
591
|
}
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAoG3C,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAY/C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAsBnD"}
|
package/dist/schema.js
CHANGED
|
@@ -17,7 +17,8 @@ CREATE TABLE IF NOT EXISTS jobs (
|
|
|
17
17
|
request_log TEXT,
|
|
18
18
|
response_log TEXT,
|
|
19
19
|
batch_id TEXT REFERENCES job_batches(id),
|
|
20
|
-
unique_key TEXT
|
|
20
|
+
unique_key TEXT,
|
|
21
|
+
backoff_config TEXT
|
|
21
22
|
)`;
|
|
22
23
|
// State-aware dedup: same (type, unique_key) cannot be both pending/processing at once.
|
|
23
24
|
// Once the job completes, the same key can be re-enqueued.
|
|
@@ -107,12 +108,13 @@ export function initializeSchema(db) {
|
|
|
107
108
|
db.run(FAILED_JOBS_TABLE);
|
|
108
109
|
db.run(SCHEDULES_TABLE);
|
|
109
110
|
db.run(SCHEDULES_NEXT_RUN_INDEX);
|
|
110
|
-
//
|
|
111
|
-
const cols = db
|
|
112
|
-
.prepare("PRAGMA table_info(jobs)")
|
|
113
|
-
.all();
|
|
111
|
+
// Migrations for columns added after initial schema creation
|
|
112
|
+
const cols = db.prepare('PRAGMA table_info(jobs)').all();
|
|
114
113
|
if (!cols.some(c => c.name === 'unique_key')) {
|
|
115
114
|
db.run('ALTER TABLE jobs ADD COLUMN unique_key TEXT');
|
|
116
115
|
}
|
|
116
|
+
if (!cols.some(c => c.name === 'backoff_config')) {
|
|
117
|
+
db.run('ALTER TABLE jobs ADD COLUMN backoff_config TEXT');
|
|
118
|
+
}
|
|
117
119
|
db.run(JOBS_UNIQUE_KEY_INDEX);
|
|
118
120
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -41,6 +41,11 @@ export type FailedJob = {
|
|
|
41
41
|
readonly requestLog: string | null;
|
|
42
42
|
readonly responseLog: string | null;
|
|
43
43
|
};
|
|
44
|
+
export type BackoffConfig = {
|
|
45
|
+
type: 'exponential' | 'fixed';
|
|
46
|
+
/** Base delay in ms. Exponential: delayMs * 2^retryCount. Fixed: always delayMs. Max 1h. */
|
|
47
|
+
delayMs: number;
|
|
48
|
+
};
|
|
44
49
|
export type AddJobOptions = {
|
|
45
50
|
priority?: number;
|
|
46
51
|
runAt?: Date;
|
|
@@ -52,6 +57,11 @@ export type AddJobOptions = {
|
|
|
52
57
|
* existing job id is returned. Once the job completes, the same key can be re-used.
|
|
53
58
|
*/
|
|
54
59
|
uniqueKey?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Backoff strategy for retries. Exponential: delayMs * 2^retryCount, capped at 1h.
|
|
62
|
+
* Fixed: always delayMs between retries. Default: retry immediately.
|
|
63
|
+
*/
|
|
64
|
+
backoff?: BackoffConfig;
|
|
55
65
|
};
|
|
56
66
|
export type JobContext = {
|
|
57
67
|
reportProgress: (percent: number) => void;
|
|
@@ -69,6 +79,8 @@ export type WorkerOptions<T = unknown> = {
|
|
|
69
79
|
onError?: (job: Job<T>, error: unknown) => void;
|
|
70
80
|
/** Hard wall-clock limit per job execution in ms. Job is marked failed on timeout. */
|
|
71
81
|
timeoutMs?: number;
|
|
82
|
+
/** Max concurrent jobs this worker runs simultaneously. Default: 1. */
|
|
83
|
+
concurrency?: number;
|
|
72
84
|
};
|
|
73
85
|
export type JobStats = {
|
|
74
86
|
pending: number;
|
|
@@ -113,6 +125,7 @@ export type JobRow = {
|
|
|
113
125
|
request_log: string | null;
|
|
114
126
|
response_log: string | null;
|
|
115
127
|
unique_key: string | null;
|
|
128
|
+
backoff_config: string | null;
|
|
116
129
|
};
|
|
117
130
|
export type FailedJobRow = {
|
|
118
131
|
id: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,cAAc,QAAQ;gBAEnB,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,YAAY,GACZ,MAAM,GACN,QAAQ,GACR,SAAS,GACT,WAAW,CAAC;AAEhB,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,IAAI;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/worker.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare class JobWorker<TMap extends JobMap = Record<string, unknown>, K
|
|
|
7
7
|
private abortController;
|
|
8
8
|
private timer;
|
|
9
9
|
private running;
|
|
10
|
-
private
|
|
10
|
+
private activeCount;
|
|
11
11
|
private stopResolve;
|
|
12
12
|
constructor(queue: JobQueue<TMap>, options: WorkerOptions<TMap[K]> & {
|
|
13
13
|
type: K;
|
|
@@ -17,5 +17,6 @@ export declare class JobWorker<TMap extends JobMap = Record<string, unknown>, K
|
|
|
17
17
|
stop(): Promise<void>;
|
|
18
18
|
private scheduleNext;
|
|
19
19
|
private poll;
|
|
20
|
+
private runJob;
|
|
20
21
|
}
|
|
21
22
|
//# sourceMappingURL=worker.d.ts.map
|
package/dist/worker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,KAAK,EAAmB,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGtE,qBAAa,SAAS,CACpB,IAAI,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,IAAI;IAEnD,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,KAAK,EAAmB,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGtE,qBAAa,SAAS,CACpB,IAAI,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,IAAI;IAEnD,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAA6B;gBAG9C,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EACrB,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE;IAY/C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,KAAK,IAAI,IAAI;IAOP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B,OAAO,CAAC,YAAY;YAMN,IAAI;YAoBJ,MAAM;CAiDrB"}
|
package/dist/worker.js
CHANGED
|
@@ -7,7 +7,7 @@ export class JobWorker {
|
|
|
7
7
|
abortController = null;
|
|
8
8
|
timer = null;
|
|
9
9
|
running = false;
|
|
10
|
-
|
|
10
|
+
activeCount = 0;
|
|
11
11
|
stopResolve = null;
|
|
12
12
|
constructor(queue, options) {
|
|
13
13
|
this.queue = queue;
|
|
@@ -35,7 +35,7 @@ export class JobWorker {
|
|
|
35
35
|
this.timer = null;
|
|
36
36
|
}
|
|
37
37
|
this.abortController?.abort();
|
|
38
|
-
if (this.
|
|
38
|
+
if (this.activeCount > 0) {
|
|
39
39
|
return new Promise(resolve => {
|
|
40
40
|
this.stopResolve = resolve;
|
|
41
41
|
});
|
|
@@ -50,16 +50,21 @@ export class JobWorker {
|
|
|
50
50
|
async poll() {
|
|
51
51
|
if (!this.running)
|
|
52
52
|
return;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
const concurrency = this.options.concurrency ?? 1;
|
|
54
|
+
// Drain available jobs up to available capacity in one poll tick
|
|
55
|
+
while (this.activeCount < concurrency) {
|
|
56
|
+
if (this.rateLimiter && !this.rateLimiter.canProceed())
|
|
57
|
+
break;
|
|
58
|
+
const job = this.queue.pollAndClaim(this.options.type);
|
|
59
|
+
if (!job)
|
|
60
|
+
break;
|
|
61
|
+
this.rateLimiter?.record();
|
|
62
|
+
this.activeCount++;
|
|
63
|
+
void this.runJob(job);
|
|
61
64
|
}
|
|
62
|
-
this.
|
|
65
|
+
this.scheduleNext();
|
|
66
|
+
}
|
|
67
|
+
async runJob(job) {
|
|
63
68
|
try {
|
|
64
69
|
const ctx = {
|
|
65
70
|
reportProgress: (percent) => {
|
|
@@ -67,7 +72,6 @@ export class JobWorker {
|
|
|
67
72
|
},
|
|
68
73
|
signal: this.abortController.signal
|
|
69
74
|
};
|
|
70
|
-
this.rateLimiter?.record();
|
|
71
75
|
const handlerPromise = this.options.handler(job, ctx);
|
|
72
76
|
if (this.options.timeoutMs) {
|
|
73
77
|
const timeoutMs = this.options.timeoutMs;
|
|
@@ -98,14 +102,11 @@ export class JobWorker {
|
|
|
98
102
|
this.options.onError?.(job, error);
|
|
99
103
|
}
|
|
100
104
|
finally {
|
|
101
|
-
this.
|
|
102
|
-
if (this.stopResolve) {
|
|
105
|
+
this.activeCount--;
|
|
106
|
+
if (!this.running && this.activeCount === 0 && this.stopResolve) {
|
|
103
107
|
this.stopResolve();
|
|
104
108
|
this.stopResolve = null;
|
|
105
109
|
}
|
|
106
|
-
else {
|
|
107
|
-
this.scheduleNext();
|
|
108
|
-
}
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
}
|