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