@workglow/job-queue 0.0.109 → 0.0.113
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/browser.js +78 -24
- package/dist/browser.js.map +5 -5
- package/dist/bun.js +78 -24
- package/dist/bun.js.map +5 -5
- package/dist/job/JobQueueServer.d.ts +5 -0
- package/dist/job/JobQueueServer.d.ts.map +1 -1
- package/dist/job/JobQueueWorker.d.ts +34 -1
- package/dist/job/JobQueueWorker.d.ts.map +1 -1
- package/dist/limiter/ConcurrencyLimiter.d.ts +1 -2
- package/dist/limiter/ConcurrencyLimiter.d.ts.map +1 -1
- package/dist/node.js +78 -24
- package/dist/node.js.map +5 -5
- package/package.json +7 -5
package/dist/bun.js
CHANGED
|
@@ -513,6 +513,8 @@ class JobQueueWorker {
|
|
|
513
513
|
pollIntervalMs;
|
|
514
514
|
events = new EventEmitter2;
|
|
515
515
|
running = false;
|
|
516
|
+
wakeResolve = null;
|
|
517
|
+
wakeTimer = null;
|
|
516
518
|
activeJobAbortControllers = new Map;
|
|
517
519
|
processingTimes = new Map;
|
|
518
520
|
constructor(jobClass, options) {
|
|
@@ -532,11 +534,22 @@ class JobQueueWorker {
|
|
|
532
534
|
this.processJobs();
|
|
533
535
|
return this;
|
|
534
536
|
}
|
|
537
|
+
notify() {
|
|
538
|
+
if (this.wakeResolve) {
|
|
539
|
+
if (this.wakeTimer) {
|
|
540
|
+
clearTimeout(this.wakeTimer);
|
|
541
|
+
this.wakeTimer = null;
|
|
542
|
+
}
|
|
543
|
+
this.wakeResolve();
|
|
544
|
+
this.wakeResolve = null;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
535
547
|
async stop() {
|
|
536
548
|
if (!this.running) {
|
|
537
549
|
return this;
|
|
538
550
|
}
|
|
539
551
|
this.running = false;
|
|
552
|
+
this.notify();
|
|
540
553
|
const size = await this.storage.size(JobStatus3.PROCESSING);
|
|
541
554
|
const sleepTime = Math.max(100, size * 2);
|
|
542
555
|
await sleep(sleepTime);
|
|
@@ -586,26 +599,52 @@ class JobQueueWorker {
|
|
|
586
599
|
return this.storageToClass(job);
|
|
587
600
|
}
|
|
588
601
|
async processJobs() {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
602
|
+
while (this.running) {
|
|
603
|
+
try {
|
|
604
|
+
await this.checkForAbortingJobs();
|
|
605
|
+
const canProceed = await this.limiter.canProceed();
|
|
606
|
+
if (canProceed) {
|
|
607
|
+
const job = await this.next();
|
|
608
|
+
if (job) {
|
|
609
|
+
this.processSingleJob(job);
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (canProceed) {
|
|
614
|
+
const delay = await this.getIdleDelay();
|
|
615
|
+
await this.waitForWakeOrTimeout(delay);
|
|
599
616
|
} else {
|
|
600
|
-
await
|
|
617
|
+
await this.waitForWakeOrTimeout(this.pollIntervalMs);
|
|
601
618
|
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
if (this.running) {
|
|
605
|
-
setTimeout(() => this.processJobs(), this.pollIntervalMs);
|
|
619
|
+
} catch {
|
|
620
|
+
await sleep(this.pollIntervalMs);
|
|
606
621
|
}
|
|
607
622
|
}
|
|
608
623
|
}
|
|
624
|
+
async getIdleDelay() {
|
|
625
|
+
try {
|
|
626
|
+
const pending = await this.storage.peek(JobStatus3.PENDING, 1);
|
|
627
|
+
if (pending.length > 0 && pending[0].run_after) {
|
|
628
|
+
const delay = new Date(pending[0].run_after).getTime() - Date.now();
|
|
629
|
+
if (delay > 0) {
|
|
630
|
+
return Math.min(delay, this.pollIntervalMs);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
} catch {}
|
|
634
|
+
return this.pollIntervalMs;
|
|
635
|
+
}
|
|
636
|
+
waitForWakeOrTimeout(timeoutMs) {
|
|
637
|
+
return new Promise((resolve) => {
|
|
638
|
+
this.wakeTimer = setTimeout(() => {
|
|
639
|
+
this.wakeTimer = null;
|
|
640
|
+
this.wakeResolve = null;
|
|
641
|
+
resolve();
|
|
642
|
+
}, timeoutMs);
|
|
643
|
+
this.wakeResolve = () => {
|
|
644
|
+
resolve();
|
|
645
|
+
};
|
|
646
|
+
});
|
|
647
|
+
}
|
|
609
648
|
async checkForAbortingJobs() {
|
|
610
649
|
const abortingJobs = await this.storage.peek(JobStatus3.ABORTING);
|
|
611
650
|
for (const jobData of abortingJobs) {
|
|
@@ -809,6 +848,7 @@ class JobQueueServer {
|
|
|
809
848
|
clients = new Set;
|
|
810
849
|
running = false;
|
|
811
850
|
cleanupTimer = null;
|
|
851
|
+
storageUnsubscribe = null;
|
|
812
852
|
stats = {
|
|
813
853
|
totalJobs: 0,
|
|
814
854
|
completedJobs: 0,
|
|
@@ -838,6 +878,13 @@ class JobQueueServer {
|
|
|
838
878
|
this.running = true;
|
|
839
879
|
this.events.emit("server_start", this.queueName);
|
|
840
880
|
await this.fixupJobs();
|
|
881
|
+
try {
|
|
882
|
+
this.storageUnsubscribe = this.storage.subscribeToChanges((change) => {
|
|
883
|
+
if (change.type === "INSERT" || change.type === "UPDATE" && change.new?.status === JobStatus4.PENDING) {
|
|
884
|
+
this.notifyWorkers();
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
} catch {}
|
|
841
888
|
await Promise.all(this.workers.map((worker) => worker.start()));
|
|
842
889
|
this.startCleanupLoop();
|
|
843
890
|
return this;
|
|
@@ -847,6 +894,10 @@ class JobQueueServer {
|
|
|
847
894
|
return this;
|
|
848
895
|
}
|
|
849
896
|
this.running = false;
|
|
897
|
+
if (this.storageUnsubscribe) {
|
|
898
|
+
this.storageUnsubscribe();
|
|
899
|
+
this.storageUnsubscribe = null;
|
|
900
|
+
}
|
|
850
901
|
if (this.cleanupTimer) {
|
|
851
902
|
clearTimeout(this.cleanupTimer);
|
|
852
903
|
this.cleanupTimer = null;
|
|
@@ -891,6 +942,11 @@ class JobQueueServer {
|
|
|
891
942
|
removeClient(client) {
|
|
892
943
|
this.clients.delete(client);
|
|
893
944
|
}
|
|
945
|
+
notifyWorkers() {
|
|
946
|
+
for (const worker of this.workers) {
|
|
947
|
+
worker.notify();
|
|
948
|
+
}
|
|
949
|
+
}
|
|
894
950
|
on(event, listener) {
|
|
895
951
|
this.events.on(event, listener);
|
|
896
952
|
}
|
|
@@ -923,6 +979,7 @@ class JobQueueServer {
|
|
|
923
979
|
if (this.deleteAfterCompletionMs === 0) {
|
|
924
980
|
await this.storage.delete(jobId);
|
|
925
981
|
}
|
|
982
|
+
this.notifyWorkers();
|
|
926
983
|
});
|
|
927
984
|
worker.on("job_error", async (jobId, error, errorCode) => {
|
|
928
985
|
this.stats = { ...this.stats, failedJobs: this.stats.failedJobs + 1 };
|
|
@@ -931,6 +988,7 @@ class JobQueueServer {
|
|
|
931
988
|
if (this.deleteAfterFailureMs === 0) {
|
|
932
989
|
await this.storage.delete(jobId);
|
|
933
990
|
}
|
|
991
|
+
this.notifyWorkers();
|
|
934
992
|
});
|
|
935
993
|
worker.on("job_disabled", async (jobId) => {
|
|
936
994
|
this.stats = { ...this.stats, disabledJobs: this.stats.disabledJobs + 1 };
|
|
@@ -939,6 +997,7 @@ class JobQueueServer {
|
|
|
939
997
|
if (this.deleteAfterDisabledMs === 0) {
|
|
940
998
|
await this.storage.delete(jobId);
|
|
941
999
|
}
|
|
1000
|
+
this.notifyWorkers();
|
|
942
1001
|
});
|
|
943
1002
|
worker.on("job_retry", (jobId, runAfter) => {
|
|
944
1003
|
this.stats = { ...this.stats, retriedJobs: this.stats.retriedJobs + 1 };
|
|
@@ -1092,26 +1151,21 @@ var CONCURRENT_JOB_LIMITER = createServiceToken2("jobqueue.limiter.concurrent");
|
|
|
1092
1151
|
class ConcurrencyLimiter {
|
|
1093
1152
|
currentRunningJobs = 0;
|
|
1094
1153
|
maxConcurrentJobs;
|
|
1095
|
-
timeSliceInMilliseconds;
|
|
1096
1154
|
nextAllowedStartTime = new Date;
|
|
1097
|
-
constructor(maxConcurrentJobs
|
|
1155
|
+
constructor(maxConcurrentJobs) {
|
|
1098
1156
|
this.maxConcurrentJobs = maxConcurrentJobs;
|
|
1099
|
-
this.timeSliceInMilliseconds = timeSliceInMilliseconds;
|
|
1100
1157
|
}
|
|
1101
1158
|
async canProceed() {
|
|
1102
1159
|
return this.currentRunningJobs < this.maxConcurrentJobs && Date.now() >= this.nextAllowedStartTime.getTime();
|
|
1103
1160
|
}
|
|
1104
1161
|
async recordJobStart() {
|
|
1105
|
-
|
|
1106
|
-
this.currentRunningJobs++;
|
|
1107
|
-
this.nextAllowedStartTime = new Date(Date.now() + this.timeSliceInMilliseconds);
|
|
1108
|
-
}
|
|
1162
|
+
this.currentRunningJobs++;
|
|
1109
1163
|
}
|
|
1110
1164
|
async recordJobCompletion() {
|
|
1111
1165
|
this.currentRunningJobs = Math.max(0, this.currentRunningJobs - 1);
|
|
1112
1166
|
}
|
|
1113
1167
|
async getNextAvailableTime() {
|
|
1114
|
-
return this.currentRunningJobs
|
|
1168
|
+
return this.currentRunningJobs > this.maxConcurrentJobs ? new Date : new Date(Date.now() - 1);
|
|
1115
1169
|
}
|
|
1116
1170
|
async setNextAvailableTime(date) {
|
|
1117
1171
|
if (date > this.nextAllowedStartTime) {
|
|
@@ -1349,4 +1403,4 @@ export {
|
|
|
1349
1403
|
AbortSignalJobError
|
|
1350
1404
|
};
|
|
1351
1405
|
|
|
1352
|
-
//# debugId=
|
|
1406
|
+
//# debugId=FF64F110FAFE185564756E2164756E21
|