@indigoai-us/hq-cloud 6.15.68 → 6.15.70
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/sync/push-receiver.d.ts +21 -3
- package/dist/sync/push-receiver.d.ts.map +1 -1
- package/dist/sync/push-receiver.js +195 -95
- package/dist/sync/push-receiver.js.map +1 -1
- package/dist/sync/push-receiver.test.js +105 -0
- package/dist/sync/push-receiver.test.js.map +1 -1
- package/dist/watcher.d.ts +5 -6
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +13 -10
- package/dist/watcher.js.map +1 -1
- package/dist/watcher.test.js +6 -5
- package/dist/watcher.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -124,6 +124,13 @@ export declare const DEFAULT_RECEIVER_DEDUPE_MAX_PATHS = 50000;
|
|
|
124
124
|
export declare const DEFAULT_RECEIVER_BATCH_MAX_PATHS = 256;
|
|
125
125
|
/** Bound raw receipt memory while draining a hot SQS queue into one pass. */
|
|
126
126
|
export declare const DEFAULT_RECEIVER_DRAIN_MAX_MESSAGES = 1000;
|
|
127
|
+
/**
|
|
128
|
+
* A second drain may keep receiving while a bulk targeted pull is running.
|
|
129
|
+
* This is deliberately small: it prevents one slow scheduler pass from
|
|
130
|
+
* silencing SQS intake without stockpiling enough leased receipts to outrun
|
|
131
|
+
* the ten-minute visibility lease.
|
|
132
|
+
*/
|
|
133
|
+
export declare const DEFAULT_RECEIVER_MAX_IN_FLIGHT_DRAINS = 2;
|
|
127
134
|
/** Consecutive one-second long-poll empties required to finish a drain. */
|
|
128
135
|
export declare const DEFAULT_RECEIVER_DRAIN_EMPTY_CONFIRMATIONS = 3;
|
|
129
136
|
/** Maximum extra time spent filling a drain that already received work. */
|
|
@@ -357,6 +364,8 @@ export interface SqsPushReceiverOptions {
|
|
|
357
364
|
batchMaxPaths?: number;
|
|
358
365
|
/** Maximum raw SQS receipts held while one batch is being formed. */
|
|
359
366
|
drainMaxMessages?: number;
|
|
367
|
+
/** Maximum received drains which may be processing at once. */
|
|
368
|
+
maxInFlightDrains?: number;
|
|
360
369
|
/** Reconnect backoff config. */
|
|
361
370
|
reconnect?: {
|
|
362
371
|
initialMs?: number;
|
|
@@ -410,6 +419,7 @@ export declare class SqsPushReceiver implements PushReceiver {
|
|
|
410
419
|
private readonly now;
|
|
411
420
|
private readonly batchMaxPaths;
|
|
412
421
|
private readonly drainMaxMessages;
|
|
422
|
+
private readonly maxInFlightDrains;
|
|
413
423
|
private _connected;
|
|
414
424
|
private disposed;
|
|
415
425
|
private disposing;
|
|
@@ -418,9 +428,9 @@ export declare class SqsPushReceiver implements PushReceiver {
|
|
|
418
428
|
private loopAbort;
|
|
419
429
|
/** The running poll loop promise; awaited (best-effort) during dispose. */
|
|
420
430
|
private loopPromise;
|
|
421
|
-
/**
|
|
422
|
-
private
|
|
423
|
-
private
|
|
431
|
+
/** Every admitted drain owns one controller until it reaches a terminal outcome. */
|
|
432
|
+
private readonly inFlightAborts;
|
|
433
|
+
private readonly inFlightDrains;
|
|
424
434
|
/** Per-path highest sequence number already PROCESSED by syncFn. */
|
|
425
435
|
private readonly seenSequencePerPath;
|
|
426
436
|
private _processedCount;
|
|
@@ -447,6 +457,14 @@ export declare class SqsPushReceiver implements PushReceiver {
|
|
|
447
457
|
* is fire-and-forgotten by `start()` and awaited best-effort by `dispose()`.
|
|
448
458
|
*/
|
|
449
459
|
private pollLoop;
|
|
460
|
+
/**
|
|
461
|
+
* Admit a received drain without coupling the next outer long-poll to its
|
|
462
|
+
* slow lane. The set itself is the bounded lease budget; completion frees a
|
|
463
|
+
* slot and wakes the poll loop through the raced promise below.
|
|
464
|
+
*/
|
|
465
|
+
private startDrain;
|
|
466
|
+
/** Wait only when the explicit receipt budget is full, never for one pass. */
|
|
467
|
+
private waitForDrainSlot;
|
|
450
468
|
/**
|
|
451
469
|
* Drain immediately-available messages, then collapse them by relative path
|
|
452
470
|
* before one sync pass. SQS caps an individual receive at ten messages, so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-receiver.d.ts","sourceRoot":"","sources":["../../src/sync/push-receiver.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"push-receiver.d.ts","sourceRoot":"","sources":["../../src/sync/push-receiver.ts"],"names":[],"mappings":"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"}
|
|
@@ -125,6 +125,13 @@ export const DEFAULT_RECEIVER_DEDUPE_MAX_PATHS = 50_000;
|
|
|
125
125
|
export const DEFAULT_RECEIVER_BATCH_MAX_PATHS = 256;
|
|
126
126
|
/** Bound raw receipt memory while draining a hot SQS queue into one pass. */
|
|
127
127
|
export const DEFAULT_RECEIVER_DRAIN_MAX_MESSAGES = 1_000;
|
|
128
|
+
/**
|
|
129
|
+
* A second drain may keep receiving while a bulk targeted pull is running.
|
|
130
|
+
* This is deliberately small: it prevents one slow scheduler pass from
|
|
131
|
+
* silencing SQS intake without stockpiling enough leased receipts to outrun
|
|
132
|
+
* the ten-minute visibility lease.
|
|
133
|
+
*/
|
|
134
|
+
export const DEFAULT_RECEIVER_MAX_IN_FLIGHT_DRAINS = 2;
|
|
128
135
|
/** Consecutive one-second long-poll empties required to finish a drain. */
|
|
129
136
|
export const DEFAULT_RECEIVER_DRAIN_EMPTY_CONFIRMATIONS = 3;
|
|
130
137
|
/** Maximum extra time spent filling a drain that already received work. */
|
|
@@ -312,6 +319,7 @@ export class SqsPushReceiver {
|
|
|
312
319
|
now;
|
|
313
320
|
batchMaxPaths;
|
|
314
321
|
drainMaxMessages;
|
|
322
|
+
maxInFlightDrains;
|
|
315
323
|
_connected = false;
|
|
316
324
|
disposed = false;
|
|
317
325
|
disposing = false;
|
|
@@ -320,9 +328,9 @@ export class SqsPushReceiver {
|
|
|
320
328
|
loopAbort = null;
|
|
321
329
|
/** The running poll loop promise; awaited (best-effort) during dispose. */
|
|
322
330
|
loopPromise = null;
|
|
323
|
-
/**
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
/** Every admitted drain owns one controller until it reaches a terminal outcome. */
|
|
332
|
+
inFlightAborts = new Set();
|
|
333
|
+
inFlightDrains = new Set();
|
|
326
334
|
/** Per-path highest sequence number already PROCESSED by syncFn. */
|
|
327
335
|
seenSequencePerPath;
|
|
328
336
|
_processedCount = 0;
|
|
@@ -371,6 +379,7 @@ export class SqsPushReceiver {
|
|
|
371
379
|
this.now = opts.now ?? (() => Date.now());
|
|
372
380
|
this.batchMaxPaths = Math.max(1, Math.floor(opts.batchMaxPaths ?? DEFAULT_RECEIVER_BATCH_MAX_PATHS));
|
|
373
381
|
this.drainMaxMessages = Math.max(1, Math.floor(opts.drainMaxMessages ?? DEFAULT_RECEIVER_DRAIN_MAX_MESSAGES));
|
|
382
|
+
this.maxInFlightDrains = Math.max(1, Math.floor(opts.maxInFlightDrains ?? DEFAULT_RECEIVER_MAX_IN_FLIGHT_DRAINS));
|
|
374
383
|
}
|
|
375
384
|
// ─── PushReceiver surface ────────────────────────────────────────────────
|
|
376
385
|
get connected() {
|
|
@@ -404,20 +413,22 @@ export class SqsPushReceiver {
|
|
|
404
413
|
catch {
|
|
405
414
|
/* AbortController.abort never throws on Node; defensive. */
|
|
406
415
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
416
|
+
for (const controller of this.inFlightAborts) {
|
|
417
|
+
try {
|
|
418
|
+
controller.abort();
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
/* defensive */
|
|
422
|
+
}
|
|
412
423
|
}
|
|
413
|
-
if (this.
|
|
424
|
+
if (this.inFlightDrains.size > 0) {
|
|
414
425
|
const drainDeadline = new Promise((resolve) => {
|
|
415
426
|
const t = setTimeout(resolve, this.disposeDrainMs);
|
|
416
427
|
// Unref so a hung syncFn can't keep the loop alive past process exit.
|
|
417
428
|
t.unref?.();
|
|
418
429
|
});
|
|
419
430
|
await Promise.race([
|
|
420
|
-
this.
|
|
431
|
+
Promise.allSettled([...this.inFlightDrains]).then(() => undefined),
|
|
421
432
|
drainDeadline,
|
|
422
433
|
]);
|
|
423
434
|
}
|
|
@@ -464,6 +475,9 @@ export class SqsPushReceiver {
|
|
|
464
475
|
async pollLoop(signal) {
|
|
465
476
|
let attempt = 0;
|
|
466
477
|
while (!signal.aborted) {
|
|
478
|
+
await this.waitForDrainSlot(signal);
|
|
479
|
+
if (signal.aborted)
|
|
480
|
+
return;
|
|
467
481
|
let received;
|
|
468
482
|
try {
|
|
469
483
|
received = await this.sqs.receiveMessage({
|
|
@@ -487,7 +501,51 @@ export class SqsPushReceiver {
|
|
|
487
501
|
}
|
|
488
502
|
if (signal.aborted)
|
|
489
503
|
return;
|
|
490
|
-
|
|
504
|
+
if (received.messages.length > 0) {
|
|
505
|
+
// One drain owns collection at a time so its coalescing/receipt caps
|
|
506
|
+
// retain their exact meaning. Once collection is complete, this await
|
|
507
|
+
// resolves and the next outer receive may overlap only the slow pass.
|
|
508
|
+
await this.startDrain(received.messages, signal);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Admit a received drain without coupling the next outer long-poll to its
|
|
514
|
+
* slow lane. The set itself is the bounded lease budget; completion frees a
|
|
515
|
+
* slot and wakes the poll loop through the raced promise below.
|
|
516
|
+
*/
|
|
517
|
+
startDrain(initial, signal) {
|
|
518
|
+
let resolveIntake = () => undefined;
|
|
519
|
+
const intakeComplete = new Promise((resolve) => {
|
|
520
|
+
resolveIntake = resolve;
|
|
521
|
+
});
|
|
522
|
+
const drain = this.handleReceivedMessages(initial, signal, resolveIntake).catch((err) => {
|
|
523
|
+
this.logger.error({
|
|
524
|
+
event: "receiver.drain.failed",
|
|
525
|
+
tenantId: this.tenantId,
|
|
526
|
+
err: { message: err?.message },
|
|
527
|
+
}, "push receiver drain failed");
|
|
528
|
+
});
|
|
529
|
+
this.inFlightDrains.add(drain);
|
|
530
|
+
void drain.then(() => {
|
|
531
|
+
this.inFlightDrains.delete(drain);
|
|
532
|
+
});
|
|
533
|
+
return intakeComplete;
|
|
534
|
+
}
|
|
535
|
+
/** Wait only when the explicit receipt budget is full, never for one pass. */
|
|
536
|
+
async waitForDrainSlot(signal) {
|
|
537
|
+
while (!signal.aborted && this.inFlightDrains.size >= this.maxInFlightDrains) {
|
|
538
|
+
let onAbort;
|
|
539
|
+
const abortWait = new Promise((resolve) => {
|
|
540
|
+
onAbort = resolve;
|
|
541
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
542
|
+
});
|
|
543
|
+
await Promise.race([
|
|
544
|
+
...this.inFlightDrains,
|
|
545
|
+
abortWait,
|
|
546
|
+
]);
|
|
547
|
+
if (onAbort)
|
|
548
|
+
signal.removeEventListener("abort", onAbort);
|
|
491
549
|
}
|
|
492
550
|
}
|
|
493
551
|
/**
|
|
@@ -499,13 +557,32 @@ export class SqsPushReceiver {
|
|
|
499
557
|
* bounds receipt memory. Coalescing happens while draining, so once the
|
|
500
558
|
* path cap is full no further receive can lease an unservable backlog.
|
|
501
559
|
*/
|
|
502
|
-
async handleReceivedMessages(initial, signal) {
|
|
503
|
-
if (this.disposing || this.disposed)
|
|
504
|
-
return;
|
|
560
|
+
async handleReceivedMessages(initial, signal, onIntakeComplete) {
|
|
505
561
|
const selected = new Map();
|
|
506
562
|
const receiptsByPath = new Map();
|
|
507
563
|
let receivedCount = 0;
|
|
564
|
+
let deletedCount = 0;
|
|
565
|
+
let releasedCount = 0;
|
|
566
|
+
let processedCount = 0;
|
|
508
567
|
let saturated = false;
|
|
568
|
+
let intakeCompleted = false;
|
|
569
|
+
const completeIntake = () => {
|
|
570
|
+
if (intakeCompleted)
|
|
571
|
+
return;
|
|
572
|
+
intakeCompleted = true;
|
|
573
|
+
onIntakeComplete();
|
|
574
|
+
};
|
|
575
|
+
const acknowledge = async (msg) => {
|
|
576
|
+
if (await this.safeDelete(msg)) {
|
|
577
|
+
deletedCount += 1;
|
|
578
|
+
}
|
|
579
|
+
else if (await this.releaseUnselected(msg)) {
|
|
580
|
+
// A failed delete is not allowed to strand a stale receipt until its
|
|
581
|
+
// normal lease expires. Releasing preserves delete-after-success while
|
|
582
|
+
// returning retry ownership to SQS immediately.
|
|
583
|
+
releasedCount += 1;
|
|
584
|
+
}
|
|
585
|
+
};
|
|
509
586
|
const selectMessages = async (messages) => {
|
|
510
587
|
for (const msg of messages) {
|
|
511
588
|
receivedCount += 1;
|
|
@@ -521,19 +598,19 @@ export class SqsPushReceiver {
|
|
|
521
598
|
messageId: msg.MessageId,
|
|
522
599
|
err: { message: err.message },
|
|
523
600
|
}, "push receiver dropped event: decode failed");
|
|
524
|
-
await
|
|
601
|
+
await acknowledge(msg);
|
|
525
602
|
continue;
|
|
526
603
|
}
|
|
527
604
|
// Self-echoes are decoded (so identity is trustworthy), then acknowledged
|
|
528
605
|
// immediately. They never consume a targeted-pull pass.
|
|
529
606
|
if (!this.shouldProcess(event)) {
|
|
530
|
-
await
|
|
607
|
+
await acknowledge(msg);
|
|
531
608
|
continue;
|
|
532
609
|
}
|
|
533
610
|
const seen = this.seenSequencePerPath.get(event.relativePath);
|
|
534
611
|
if (seen !== undefined && event.sequenceNumber <= seen) {
|
|
535
612
|
this._dedupedCount += 1;
|
|
536
|
-
await
|
|
613
|
+
await acknowledge(msg);
|
|
537
614
|
continue;
|
|
538
615
|
}
|
|
539
616
|
const selectedEvent = selected.get(event.relativePath);
|
|
@@ -542,7 +619,8 @@ export class SqsPushReceiver {
|
|
|
542
619
|
// This receipt cannot join the current pull. Do not hold it behind
|
|
543
620
|
// that pull: explicitly return it now so its next receive has a fresh
|
|
544
621
|
// receipt lease instead of silently waiting for the old lease to expire.
|
|
545
|
-
await this.releaseUnselected(msg)
|
|
622
|
+
if (await this.releaseUnselected(msg))
|
|
623
|
+
releasedCount += 1;
|
|
546
624
|
continue;
|
|
547
625
|
}
|
|
548
626
|
const receipts = receiptsByPath.get(event.relativePath) ?? [];
|
|
@@ -556,80 +634,104 @@ export class SqsPushReceiver {
|
|
|
556
634
|
}
|
|
557
635
|
}
|
|
558
636
|
};
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
next = await this.sqs.receiveMessage({
|
|
582
|
-
queueUrl: this.queueUrl,
|
|
583
|
-
maxMessages: Math.min(this.maxMessages, this.drainMaxMessages - receivedCount),
|
|
584
|
-
waitTimeSeconds,
|
|
585
|
-
visibilityTimeoutSeconds: this.visibilityTimeoutSeconds,
|
|
586
|
-
signal,
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
catch (err) {
|
|
590
|
-
if (!signal.aborted) {
|
|
591
|
-
// A failed confirmation says nothing about the receipts already
|
|
592
|
-
// collected. Log and back off exactly like a failed outer receive,
|
|
593
|
-
// then dispatch this bounded batch and resume polling.
|
|
594
|
-
await this.backoffAfterReceiveFailure(err, signal, 0);
|
|
637
|
+
try {
|
|
638
|
+
if (this.disposing || this.disposed)
|
|
639
|
+
return;
|
|
640
|
+
await selectMessages(initial);
|
|
641
|
+
if (selected.size === 0)
|
|
642
|
+
return;
|
|
643
|
+
// Drain immediately-available pages until the raw receipt bound. An empty
|
|
644
|
+
// short-poll is only a sampling result, not proof the queue is empty: it
|
|
645
|
+
// must be followed by consecutive short long-poll confirmations. Keep the
|
|
646
|
+
// fill phase bounded so a near-empty queue dispatches promptly.
|
|
647
|
+
const fillDeadline = this.now() + DEFAULT_RECEIVER_DRAIN_FILL_MAX_MS;
|
|
648
|
+
let emptyConfirmations = 0;
|
|
649
|
+
let waitTimeSeconds = 0;
|
|
650
|
+
while (!saturated &&
|
|
651
|
+
receivedCount < this.drainMaxMessages &&
|
|
652
|
+
!signal.aborted &&
|
|
653
|
+
this.now() < fillDeadline) {
|
|
654
|
+
// Do not begin a one-second confirmation that would exceed the five
|
|
655
|
+
// second fill budget. The caller already has work to dispatch.
|
|
656
|
+
if (waitTimeSeconds > 0 &&
|
|
657
|
+
this.now() + waitTimeSeconds * 1_000 > fillDeadline) {
|
|
658
|
+
break;
|
|
595
659
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
660
|
+
let next;
|
|
661
|
+
try {
|
|
662
|
+
next = await this.sqs.receiveMessage({
|
|
663
|
+
queueUrl: this.queueUrl,
|
|
664
|
+
maxMessages: Math.min(this.maxMessages, this.drainMaxMessages - receivedCount),
|
|
665
|
+
waitTimeSeconds,
|
|
666
|
+
visibilityTimeoutSeconds: this.visibilityTimeoutSeconds,
|
|
667
|
+
signal,
|
|
668
|
+
});
|
|
605
669
|
}
|
|
606
|
-
|
|
607
|
-
|
|
670
|
+
catch (err) {
|
|
671
|
+
if (!signal.aborted) {
|
|
672
|
+
// A failed confirmation says nothing about the receipts already
|
|
673
|
+
// collected. Log and back off exactly like a failed outer receive,
|
|
674
|
+
// then dispatch this bounded batch and resume polling.
|
|
675
|
+
await this.backoffAfterReceiveFailure(err, signal, 0);
|
|
676
|
+
}
|
|
608
677
|
break;
|
|
609
|
-
|
|
678
|
+
}
|
|
679
|
+
if (next.messages.length === 0) {
|
|
680
|
+
if (waitTimeSeconds === 0) {
|
|
681
|
+
// SQS short-poll sampling can miss a nonempty standard queue. Turn
|
|
682
|
+
// the next receive into a bounded long-poll confirmation instead of
|
|
683
|
+
// paying for an under-filled sync pass.
|
|
684
|
+
waitTimeSeconds = DEFAULT_RECEIVER_DRAIN_CONFIRMATION_WAIT_SECONDS;
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
emptyConfirmations += 1;
|
|
688
|
+
if (emptyConfirmations >= DEFAULT_RECEIVER_DRAIN_EMPTY_CONFIRMATIONS)
|
|
689
|
+
break;
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
emptyConfirmations = 0;
|
|
693
|
+
waitTimeSeconds = 0;
|
|
694
|
+
await selectMessages(next.messages);
|
|
610
695
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
696
|
+
completeIntake();
|
|
697
|
+
const events = [...selected.values()];
|
|
698
|
+
const batches = this.syncBatchFn.partition?.(events) ?? [events];
|
|
699
|
+
for (const batch of batches) {
|
|
700
|
+
if (batch.length === 0)
|
|
701
|
+
continue;
|
|
702
|
+
const handled = await this.dispatchBatch(batch);
|
|
703
|
+
if (!handled) {
|
|
704
|
+
// The batch reached the sync engine and failed; preserve the
|
|
705
|
+
// existing retry contract by retaining its lease for redelivery.
|
|
706
|
+
// Receipts excluded by the capacity cap were already released
|
|
707
|
+
// during collection above.
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
// Receipt acknowledgement follows the successful lane, not the original
|
|
711
|
+
// aggregate delivery. A slow-lane failure therefore leaves only its own
|
|
712
|
+
// events available for redelivery while dedupe absorbs the completed fast
|
|
713
|
+
// lane if a transport delete races or fails.
|
|
714
|
+
for (const event of batch) {
|
|
715
|
+
processedCount += 1;
|
|
716
|
+
for (const msg of receiptsByPath.get(event.relativePath) ?? []) {
|
|
717
|
+
await acknowledge(msg);
|
|
718
|
+
}
|
|
630
719
|
}
|
|
631
720
|
}
|
|
632
721
|
}
|
|
722
|
+
finally {
|
|
723
|
+
completeIntake();
|
|
724
|
+
this.logger.info({
|
|
725
|
+
event: "receiver.drain",
|
|
726
|
+
tenantId: this.tenantId,
|
|
727
|
+
received: receivedCount,
|
|
728
|
+
coalesced: selected.size,
|
|
729
|
+
processed: processedCount,
|
|
730
|
+
deleted: deletedCount,
|
|
731
|
+
released: releasedCount,
|
|
732
|
+
remaining: Math.max(0, receivedCount - deletedCount - releasedCount),
|
|
733
|
+
}, "push receiver drain completed");
|
|
734
|
+
}
|
|
633
735
|
}
|
|
634
736
|
/**
|
|
635
737
|
* Invoke one coalesced sync pass. The dedupe high-water marks advance only
|
|
@@ -639,9 +741,8 @@ export class SqsPushReceiver {
|
|
|
639
741
|
if (this.disposing || this.disposed)
|
|
640
742
|
return false;
|
|
641
743
|
const controller = new AbortController();
|
|
642
|
-
this.
|
|
744
|
+
this.inFlightAborts.add(controller);
|
|
643
745
|
const ctx = { events, signal: controller.signal };
|
|
644
|
-
const holder = { p: null };
|
|
645
746
|
const startMs = this.now();
|
|
646
747
|
let handled = false;
|
|
647
748
|
const p = (async () => {
|
|
@@ -697,26 +798,22 @@ export class SqsPushReceiver {
|
|
|
697
798
|
}, "push receiver sync engine threw");
|
|
698
799
|
}
|
|
699
800
|
finally {
|
|
700
|
-
|
|
701
|
-
this.inFlightAbort = null;
|
|
702
|
-
if (this.inFlightSync === holder.p)
|
|
703
|
-
this.inFlightSync = null;
|
|
801
|
+
this.inFlightAborts.delete(controller);
|
|
704
802
|
}
|
|
705
803
|
})();
|
|
706
|
-
holder.p = p;
|
|
707
|
-
this.inFlightSync = p;
|
|
708
804
|
await p;
|
|
709
805
|
return handled;
|
|
710
806
|
}
|
|
711
807
|
/** Delete a message, swallowing transport errors (redelivery is harmless). */
|
|
712
808
|
async safeDelete(msg) {
|
|
713
809
|
if (!msg.ReceiptHandle)
|
|
714
|
-
return;
|
|
810
|
+
return false;
|
|
715
811
|
try {
|
|
716
812
|
await this.sqs.deleteMessage({
|
|
717
813
|
queueUrl: this.queueUrl,
|
|
718
814
|
receiptHandle: msg.ReceiptHandle,
|
|
719
815
|
});
|
|
816
|
+
return true;
|
|
720
817
|
}
|
|
721
818
|
catch (err) {
|
|
722
819
|
this.logger.warn({
|
|
@@ -725,18 +822,20 @@ export class SqsPushReceiver {
|
|
|
725
822
|
messageId: msg.MessageId,
|
|
726
823
|
err: { message: err?.message },
|
|
727
824
|
}, "push receiver failed to delete message (will redeliver; dedupe absorbs)");
|
|
825
|
+
return false;
|
|
728
826
|
}
|
|
729
827
|
}
|
|
730
828
|
/** Explicitly release an over-cap receipt; failures are loud, never silent. */
|
|
731
829
|
async releaseUnselected(msg) {
|
|
732
830
|
if (!msg.ReceiptHandle)
|
|
733
|
-
return;
|
|
831
|
+
return false;
|
|
734
832
|
try {
|
|
735
833
|
await this.sqs.changeMessageVisibility({
|
|
736
834
|
queueUrl: this.queueUrl,
|
|
737
835
|
receiptHandle: msg.ReceiptHandle,
|
|
738
836
|
visibilityTimeoutSeconds: 0,
|
|
739
837
|
});
|
|
838
|
+
return true;
|
|
740
839
|
}
|
|
741
840
|
catch (err) {
|
|
742
841
|
this.logger.error({
|
|
@@ -745,6 +844,7 @@ export class SqsPushReceiver {
|
|
|
745
844
|
messageId: msg.MessageId,
|
|
746
845
|
err: { message: err?.message },
|
|
747
846
|
}, "push receiver failed to release an over-cap receipt");
|
|
847
|
+
return false;
|
|
748
848
|
}
|
|
749
849
|
}
|
|
750
850
|
/**
|