@nicnocquee/dataqueue 1.39.0 → 1.40.0-beta.20260612032253
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 +76 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +76 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/processor.test.ts +129 -0
- package/src/processor.ts +107 -28
- package/src/types.ts +13 -6
package/dist/index.d.cts
CHANGED
|
@@ -528,14 +528,20 @@ type JobHandlers<PayloadMap> = {
|
|
|
528
528
|
interface ProcessorOptions {
|
|
529
529
|
workerId?: string;
|
|
530
530
|
/**
|
|
531
|
-
* The number of jobs to
|
|
532
|
-
* - If not provided,
|
|
533
|
-
* -
|
|
531
|
+
* The maximum number of jobs to claim from the queue per poll.
|
|
532
|
+
* - If not provided, up to 10 jobs are claimed per poll.
|
|
533
|
+
* - With `startInBackground`, claims are capped to the number of free
|
|
534
|
+
* concurrency slots, so this only matters when it is below `concurrency`.
|
|
535
|
+
* - In serverless functions, it's better to claim fewer jobs at a time since serverless functions are charged by the second and have a timeout.
|
|
534
536
|
*/
|
|
535
537
|
batchSize?: number;
|
|
536
538
|
/**
|
|
537
|
-
* The maximum number of jobs to process in parallel
|
|
538
|
-
* -
|
|
539
|
+
* The maximum number of jobs to process in parallel.
|
|
540
|
+
* - With `startInBackground`, this is the steady number of jobs kept in
|
|
541
|
+
* flight: each slot is refilled as soon as it frees, so a slow job never
|
|
542
|
+
* blocks the other slots.
|
|
543
|
+
* - With the one-shot `start`, this caps parallelism within the single batch.
|
|
544
|
+
* - If not provided, defaults to 3.
|
|
539
545
|
* - Set to 1 to process jobs sequentially.
|
|
540
546
|
* - Set to a lower value to avoid resource exhaustion.
|
|
541
547
|
*/
|
|
@@ -564,7 +570,8 @@ interface ProcessorOptions {
|
|
|
564
570
|
interface Processor {
|
|
565
571
|
/**
|
|
566
572
|
* Start the job processor in the background.
|
|
567
|
-
* -
|
|
573
|
+
* - Keeps up to `concurrency` jobs in flight, refilling each slot as soon as it frees instead of waiting for a whole batch to settle.
|
|
574
|
+
* - Polls every pollInterval milliseconds (5 seconds if not provided) for new work as it becomes available.
|
|
568
575
|
* - **You have to call the stop method to stop the processor.**
|
|
569
576
|
* - Handlers are provided per-processor when calling createProcessor.
|
|
570
577
|
* - In serverless functions, it's recommended to call start instead and await it to finish.
|
package/dist/index.d.ts
CHANGED
|
@@ -528,14 +528,20 @@ type JobHandlers<PayloadMap> = {
|
|
|
528
528
|
interface ProcessorOptions {
|
|
529
529
|
workerId?: string;
|
|
530
530
|
/**
|
|
531
|
-
* The number of jobs to
|
|
532
|
-
* - If not provided,
|
|
533
|
-
* -
|
|
531
|
+
* The maximum number of jobs to claim from the queue per poll.
|
|
532
|
+
* - If not provided, up to 10 jobs are claimed per poll.
|
|
533
|
+
* - With `startInBackground`, claims are capped to the number of free
|
|
534
|
+
* concurrency slots, so this only matters when it is below `concurrency`.
|
|
535
|
+
* - In serverless functions, it's better to claim fewer jobs at a time since serverless functions are charged by the second and have a timeout.
|
|
534
536
|
*/
|
|
535
537
|
batchSize?: number;
|
|
536
538
|
/**
|
|
537
|
-
* The maximum number of jobs to process in parallel
|
|
538
|
-
* -
|
|
539
|
+
* The maximum number of jobs to process in parallel.
|
|
540
|
+
* - With `startInBackground`, this is the steady number of jobs kept in
|
|
541
|
+
* flight: each slot is refilled as soon as it frees, so a slow job never
|
|
542
|
+
* blocks the other slots.
|
|
543
|
+
* - With the one-shot `start`, this caps parallelism within the single batch.
|
|
544
|
+
* - If not provided, defaults to 3.
|
|
539
545
|
* - Set to 1 to process jobs sequentially.
|
|
540
546
|
* - Set to a lower value to avoid resource exhaustion.
|
|
541
547
|
*/
|
|
@@ -564,7 +570,8 @@ interface ProcessorOptions {
|
|
|
564
570
|
interface Processor {
|
|
565
571
|
/**
|
|
566
572
|
* Start the job processor in the background.
|
|
567
|
-
* -
|
|
573
|
+
* - Keeps up to `concurrency` jobs in flight, refilling each slot as soon as it frees instead of waiting for a whole batch to settle.
|
|
574
|
+
* - Polls every pollInterval milliseconds (5 seconds if not provided) for new work as it becomes available.
|
|
568
575
|
* - **You have to call the stop method to stop the processor.**
|
|
569
576
|
* - Handlers are provided per-processor when calling createProcessor.
|
|
570
577
|
* - In serverless functions, it's recommended to call start instead and await it to finish.
|
package/dist/index.js
CHANGED
|
@@ -586,8 +586,11 @@ var createProcessor = (backend, handlers, options = {}, onBeforeBatch, emit) =>
|
|
|
586
586
|
);
|
|
587
587
|
}
|
|
588
588
|
let running = false;
|
|
589
|
-
let
|
|
590
|
-
let
|
|
589
|
+
let pollTimer = null;
|
|
590
|
+
let claimInProgress = false;
|
|
591
|
+
let pumpRequested = false;
|
|
592
|
+
let inFlight = 0;
|
|
593
|
+
const inFlightJobs = /* @__PURE__ */ new Set();
|
|
591
594
|
setLogContext(options.verbose ?? false);
|
|
592
595
|
const processJobs = async () => {
|
|
593
596
|
if (!running) return 0;
|
|
@@ -629,29 +632,80 @@ var createProcessor = (backend, handlers, options = {}, onBeforeBatch, emit) =>
|
|
|
629
632
|
return {
|
|
630
633
|
/**
|
|
631
634
|
* Start the job processor in the background.
|
|
632
|
-
* -
|
|
635
|
+
* - Keeps up to `concurrency` jobs in flight, refilling each slot as soon as
|
|
636
|
+
* it frees instead of waiting for a whole batch to settle.
|
|
637
|
+
* - Polls every `pollInterval` milliseconds (5 seconds if not provided) for
|
|
638
|
+
* new work and to enqueue due cron jobs.
|
|
633
639
|
* - You have to call the stop method to stop the processor.
|
|
634
640
|
*/
|
|
635
641
|
startInBackground: () => {
|
|
636
642
|
if (running) return;
|
|
637
643
|
log(`Starting job processor with workerId: ${workerId}`);
|
|
638
644
|
running = true;
|
|
639
|
-
const
|
|
645
|
+
const pump = async () => {
|
|
640
646
|
if (!running) return;
|
|
641
|
-
if (
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
647
|
+
if (claimInProgress) {
|
|
648
|
+
pumpRequested = true;
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (inFlight >= concurrency) return;
|
|
652
|
+
claimInProgress = true;
|
|
653
|
+
pumpRequested = false;
|
|
654
|
+
let claimLimit = 0;
|
|
655
|
+
let claimed = 0;
|
|
656
|
+
try {
|
|
657
|
+
claimLimit = Math.min(concurrency - inFlight, batchSize);
|
|
658
|
+
const jobs = await backend.getNextBatch(workerId, claimLimit, jobType, groupConcurrency);
|
|
659
|
+
claimed = jobs.length;
|
|
660
|
+
for (const job of jobs) {
|
|
661
|
+
emit?.("job:processing", { jobId: job.id, jobType: job.jobType });
|
|
662
|
+
inFlight++;
|
|
663
|
+
const jobPromise = processJobWithHandlers(
|
|
664
|
+
backend,
|
|
665
|
+
job,
|
|
666
|
+
handlers,
|
|
667
|
+
emit
|
|
668
|
+
).catch((err) => {
|
|
669
|
+
onError(err instanceof Error ? err : new Error(String(err)));
|
|
670
|
+
}).finally(() => {
|
|
671
|
+
inFlight--;
|
|
672
|
+
inFlightJobs.delete(jobPromise);
|
|
673
|
+
void pump();
|
|
674
|
+
});
|
|
675
|
+
inFlightJobs.add(jobPromise);
|
|
676
|
+
}
|
|
677
|
+
} catch (error) {
|
|
678
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
679
|
+
onError(err);
|
|
680
|
+
emit?.("error", err);
|
|
681
|
+
} finally {
|
|
682
|
+
claimInProgress = false;
|
|
683
|
+
}
|
|
684
|
+
const moreLikely = claimed === claimLimit || pumpRequested;
|
|
685
|
+
if (running && moreLikely && inFlight < concurrency) {
|
|
686
|
+
void pump();
|
|
645
687
|
}
|
|
646
688
|
};
|
|
647
|
-
const
|
|
689
|
+
const tick = async () => {
|
|
648
690
|
if (!running) return;
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
691
|
+
if (onBeforeBatch) {
|
|
692
|
+
try {
|
|
693
|
+
await onBeforeBatch();
|
|
694
|
+
} catch (hookError) {
|
|
695
|
+
log(`onBeforeBatch hook error: ${hookError}`);
|
|
696
|
+
const err = hookError instanceof Error ? hookError : new Error(String(hookError));
|
|
697
|
+
onError(err);
|
|
698
|
+
emit?.("error", err);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
await pump();
|
|
702
|
+
if (running) {
|
|
703
|
+
pollTimer = setTimeout(() => {
|
|
704
|
+
void tick();
|
|
705
|
+
}, pollInterval);
|
|
706
|
+
}
|
|
653
707
|
};
|
|
654
|
-
|
|
708
|
+
void tick();
|
|
655
709
|
},
|
|
656
710
|
/**
|
|
657
711
|
* Stop the job processor that runs in the background.
|
|
@@ -660,9 +714,9 @@ var createProcessor = (backend, handlers, options = {}, onBeforeBatch, emit) =>
|
|
|
660
714
|
stop: () => {
|
|
661
715
|
log(`Stopping job processor with workerId: ${workerId}`);
|
|
662
716
|
running = false;
|
|
663
|
-
if (
|
|
664
|
-
clearTimeout(
|
|
665
|
-
|
|
717
|
+
if (pollTimer) {
|
|
718
|
+
clearTimeout(pollTimer);
|
|
719
|
+
pollTimer = null;
|
|
666
720
|
}
|
|
667
721
|
},
|
|
668
722
|
/**
|
|
@@ -672,17 +726,15 @@ var createProcessor = (backend, handlers, options = {}, onBeforeBatch, emit) =>
|
|
|
672
726
|
stopAndDrain: async (drainTimeoutMs = 3e4) => {
|
|
673
727
|
log(`Stopping and draining job processor with workerId: ${workerId}`);
|
|
674
728
|
running = false;
|
|
675
|
-
if (
|
|
676
|
-
clearTimeout(
|
|
677
|
-
|
|
729
|
+
if (pollTimer) {
|
|
730
|
+
clearTimeout(pollTimer);
|
|
731
|
+
pollTimer = null;
|
|
678
732
|
}
|
|
679
|
-
if (
|
|
733
|
+
if (inFlightJobs.size > 0) {
|
|
680
734
|
await Promise.race([
|
|
681
|
-
|
|
682
|
-
}),
|
|
735
|
+
Promise.allSettled(Array.from(inFlightJobs)),
|
|
683
736
|
new Promise((resolve) => setTimeout(resolve, drainTimeoutMs))
|
|
684
737
|
]);
|
|
685
|
-
currentBatchPromise = null;
|
|
686
738
|
}
|
|
687
739
|
log(`Job processor ${workerId} drained`);
|
|
688
740
|
},
|