cairnq 0.15.0 → 0.15.1
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/worker.d.ts +5 -0
- package/dist/worker.js +19 -3
- package/package.json +1 -1
- package/src/worker.ts +17 -3
package/dist/worker.d.ts
CHANGED
|
@@ -87,6 +87,8 @@ export declare class Worker {
|
|
|
87
87
|
private readonly backoffMaxMs;
|
|
88
88
|
private stopped;
|
|
89
89
|
private stopWake;
|
|
90
|
+
private freed$;
|
|
91
|
+
private freedWake;
|
|
90
92
|
private readonly stopped$;
|
|
91
93
|
private ownsStore;
|
|
92
94
|
constructor(store: TaskStore, queues: string[], opts?: WorkerOptions);
|
|
@@ -279,6 +281,9 @@ export declare class Worker {
|
|
|
279
281
|
* cuts it short when a task on this worker's queues becomes claimable;
|
|
280
282
|
* stop() interrupts it either way, and sleepOrStop bounds it at `ms` so the
|
|
281
283
|
* poll fallback — which also drives lease recovery — never stretches.
|
|
284
|
+
*
|
|
285
|
+
* `freed` is the third way out: a resource unit coming back frees a claim the
|
|
286
|
+
* store has no reason to announce (see `freed$`).
|
|
282
287
|
*/
|
|
283
288
|
private idle;
|
|
284
289
|
private sleepOrStop;
|
package/dist/worker.js
CHANGED
|
@@ -162,6 +162,13 @@ export class Worker {
|
|
|
162
162
|
backoffMaxMs;
|
|
163
163
|
stopped = false;
|
|
164
164
|
stopWake;
|
|
165
|
+
// Re-armed before each claim, resolved when a call gives a resource unit
|
|
166
|
+
// back. A claim can come back empty because a resource is at capacity rather
|
|
167
|
+
// than the queue, and that release is local — no store notification covers
|
|
168
|
+
// it, so the idle sleep waits on this too. Armed before the claim, so a
|
|
169
|
+
// release landing *during* it still shortens the sleep that follows.
|
|
170
|
+
freed$ = Promise.resolve();
|
|
171
|
+
freedWake = () => { };
|
|
165
172
|
// Resolved once by stop(); every sleep races against it. A stopped worker
|
|
166
173
|
// never restarts, so one promise serves the instance's lifetime.
|
|
167
174
|
stopped$ = new Promise((r) => (this.stopWake = r));
|
|
@@ -353,6 +360,7 @@ export class Worker {
|
|
|
353
360
|
await this.idle(pollMs);
|
|
354
361
|
continue;
|
|
355
362
|
}
|
|
363
|
+
this.freed$ = new Promise((r) => (this.freedWake = r));
|
|
356
364
|
let drawn;
|
|
357
365
|
try {
|
|
358
366
|
drawn = await this.store.claimSession(
|
|
@@ -369,7 +377,7 @@ export class Worker {
|
|
|
369
377
|
continue;
|
|
370
378
|
}
|
|
371
379
|
if (!drawn?.length) {
|
|
372
|
-
await this.idle(pollMs);
|
|
380
|
+
await this.idle(pollMs, this.freed$);
|
|
373
381
|
continue;
|
|
374
382
|
}
|
|
375
383
|
for (const { src, calls } of drawn) {
|
|
@@ -384,6 +392,8 @@ export class Worker {
|
|
|
384
392
|
const p = call.finally(() => {
|
|
385
393
|
this.planner.release(resource);
|
|
386
394
|
running.delete(p);
|
|
395
|
+
if (resource != null)
|
|
396
|
+
this.freedWake();
|
|
387
397
|
});
|
|
388
398
|
running.add(p);
|
|
389
399
|
}
|
|
@@ -746,9 +756,15 @@ export class Worker {
|
|
|
746
756
|
* cuts it short when a task on this worker's queues becomes claimable;
|
|
747
757
|
* stop() interrupts it either way, and sleepOrStop bounds it at `ms` so the
|
|
748
758
|
* poll fallback — which also drives lease recovery — never stretches.
|
|
759
|
+
*
|
|
760
|
+
* `freed` is the third way out: a resource unit coming back frees a claim the
|
|
761
|
+
* store has no reason to announce (see `freed$`).
|
|
749
762
|
*/
|
|
750
|
-
idle(ms) {
|
|
751
|
-
|
|
763
|
+
idle(ms, freed) {
|
|
764
|
+
const racers = [this.sleepOrStop(ms), this.store.claimWake(this.queues, ms)];
|
|
765
|
+
if (freed)
|
|
766
|
+
racers.push(freed);
|
|
767
|
+
return Promise.race(racers);
|
|
752
768
|
}
|
|
753
769
|
sleepOrStop(ms) {
|
|
754
770
|
if (this.stopped)
|
package/package.json
CHANGED
package/src/worker.ts
CHANGED
|
@@ -281,6 +281,13 @@ export class Worker {
|
|
|
281
281
|
private readonly backoffMaxMs: number;
|
|
282
282
|
private stopped = false;
|
|
283
283
|
private stopWake!: () => void;
|
|
284
|
+
// Re-armed before each claim, resolved when a call gives a resource unit
|
|
285
|
+
// back. A claim can come back empty because a resource is at capacity rather
|
|
286
|
+
// than the queue, and that release is local — no store notification covers
|
|
287
|
+
// it, so the idle sleep waits on this too. Armed before the claim, so a
|
|
288
|
+
// release landing *during* it still shortens the sleep that follows.
|
|
289
|
+
private freed$ = Promise.resolve();
|
|
290
|
+
private freedWake: () => void = () => {};
|
|
284
291
|
// Resolved once by stop(); every sleep races against it. A stopped worker
|
|
285
292
|
// never restarts, so one promise serves the instance's lifetime.
|
|
286
293
|
private readonly stopped$ = new Promise<void>((r) => (this.stopWake = r));
|
|
@@ -519,6 +526,7 @@ export class Worker {
|
|
|
519
526
|
await this.idle(pollMs);
|
|
520
527
|
continue;
|
|
521
528
|
}
|
|
529
|
+
this.freed$ = new Promise<void>((r) => (this.freedWake = r));
|
|
522
530
|
let drawn: Draw[] | undefined;
|
|
523
531
|
try {
|
|
524
532
|
drawn = await this.store.claimSession(
|
|
@@ -536,7 +544,7 @@ export class Worker {
|
|
|
536
544
|
continue;
|
|
537
545
|
}
|
|
538
546
|
if (!drawn?.length) {
|
|
539
|
-
await this.idle(pollMs);
|
|
547
|
+
await this.idle(pollMs, this.freed$);
|
|
540
548
|
continue;
|
|
541
549
|
}
|
|
542
550
|
for (const { src, calls } of drawn) {
|
|
@@ -552,6 +560,7 @@ export class Worker {
|
|
|
552
560
|
const p = call.finally(() => {
|
|
553
561
|
this.planner.release(resource);
|
|
554
562
|
running.delete(p);
|
|
563
|
+
if (resource != null) this.freedWake();
|
|
555
564
|
});
|
|
556
565
|
running.add(p);
|
|
557
566
|
}
|
|
@@ -929,9 +938,14 @@ export class Worker {
|
|
|
929
938
|
* cuts it short when a task on this worker's queues becomes claimable;
|
|
930
939
|
* stop() interrupts it either way, and sleepOrStop bounds it at `ms` so the
|
|
931
940
|
* poll fallback — which also drives lease recovery — never stretches.
|
|
941
|
+
*
|
|
942
|
+
* `freed` is the third way out: a resource unit coming back frees a claim the
|
|
943
|
+
* store has no reason to announce (see `freed$`).
|
|
932
944
|
*/
|
|
933
|
-
private idle(ms: number): Promise<void> {
|
|
934
|
-
|
|
945
|
+
private idle(ms: number, freed?: Promise<void>): Promise<void> {
|
|
946
|
+
const racers = [this.sleepOrStop(ms), this.store.claimWake(this.queues, ms)];
|
|
947
|
+
if (freed) racers.push(freed);
|
|
948
|
+
return Promise.race(racers);
|
|
935
949
|
}
|
|
936
950
|
|
|
937
951
|
private sleepOrStop(ms: number): Promise<void> {
|