@thru/replay 0.2.5 → 0.2.6
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 +27 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +27 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -419,12 +419,26 @@ var ReplayStream = class {
|
|
|
419
419
|
this.logger.info(
|
|
420
420
|
`replay entering BACKFILLING state (startSlot=${startSlot}, safetyMargin=${safetyMargin})`
|
|
421
421
|
);
|
|
422
|
+
let emptyPageRetries = 0;
|
|
423
|
+
const MAX_EMPTY_PAGE_RETRIES = 10;
|
|
422
424
|
while (!backfillDone) {
|
|
423
|
-
const page = await
|
|
425
|
+
const page = await currentFetchBackfill({ startSlot, cursor });
|
|
424
426
|
if (!page.items.length && !page.cursor && !page.done) {
|
|
425
|
-
|
|
427
|
+
emptyPageRetries++;
|
|
428
|
+
if (emptyPageRetries > MAX_EMPTY_PAGE_RETRIES) {
|
|
429
|
+
this.logger.error(
|
|
430
|
+
`backfill returned ${MAX_EMPTY_PAGE_RETRIES} consecutive empty pages; treating as done`
|
|
431
|
+
);
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
const backoffMs = calculateBackoff(emptyPageRetries - 1, DEFAULT_RETRY_CONFIG);
|
|
435
|
+
this.logger.warn(
|
|
436
|
+
`empty backfill page without cursor; retrying in ${backoffMs}ms (${emptyPageRetries}/${MAX_EMPTY_PAGE_RETRIES})`
|
|
437
|
+
);
|
|
438
|
+
await delay(backoffMs);
|
|
426
439
|
continue;
|
|
427
440
|
}
|
|
441
|
+
emptyPageRetries = 0;
|
|
428
442
|
const sorted = [...page.items].sort(
|
|
429
443
|
(a, b) => compareBigint(extractSlot(a), extractSlot(b))
|
|
430
444
|
);
|
|
@@ -550,19 +564,20 @@ var ReplayStream = class {
|
|
|
550
564
|
async *miniBackfill(fromSlot, fetchBackfill, extractSlot, keyOf, seenItem, recordEmission) {
|
|
551
565
|
this.logger.info(`mini-backfill starting from slot ${fromSlot}`);
|
|
552
566
|
const MINI_BACKFILL_TIMEOUT = 3e4;
|
|
553
|
-
|
|
567
|
+
let lastProgressTime = Date.now();
|
|
554
568
|
let cursor;
|
|
555
569
|
let itemsYielded = 0;
|
|
556
570
|
try {
|
|
557
571
|
while (true) {
|
|
558
|
-
if (Date.now() -
|
|
559
|
-
this.logger.warn(`mini-backfill timed out after ${MINI_BACKFILL_TIMEOUT}ms`);
|
|
572
|
+
if (Date.now() - lastProgressTime > MINI_BACKFILL_TIMEOUT) {
|
|
573
|
+
this.logger.warn(`mini-backfill timed out after ${MINI_BACKFILL_TIMEOUT}ms with no progress`);
|
|
560
574
|
break;
|
|
561
575
|
}
|
|
562
576
|
const page = await fetchBackfill({ startSlot: fromSlot, cursor });
|
|
563
577
|
const sorted = [...page.items].sort(
|
|
564
578
|
(a, b) => compareBigint(extractSlot(a), extractSlot(b))
|
|
565
579
|
);
|
|
580
|
+
let pageYielded = 0;
|
|
566
581
|
for (const item of sorted) {
|
|
567
582
|
const slot = extractSlot(item);
|
|
568
583
|
const key = keyOf(item);
|
|
@@ -572,9 +587,11 @@ var ReplayStream = class {
|
|
|
572
587
|
}
|
|
573
588
|
recordEmission(slot, key);
|
|
574
589
|
itemsYielded++;
|
|
590
|
+
pageYielded++;
|
|
575
591
|
this.metrics.emittedReconnect += 1;
|
|
576
592
|
yield item;
|
|
577
593
|
}
|
|
594
|
+
if (pageYielded > 0) lastProgressTime = Date.now();
|
|
578
595
|
cursor = page.cursor;
|
|
579
596
|
if (page.done || cursor === void 0) break;
|
|
580
597
|
}
|
|
@@ -588,10 +605,12 @@ var ReplayStream = class {
|
|
|
588
605
|
};
|
|
589
606
|
async function safeClose(pump) {
|
|
590
607
|
try {
|
|
591
|
-
await Promise.race([
|
|
592
|
-
pump.close(),
|
|
593
|
-
new Promise((resolve) => setTimeout(resolve, 5e3))
|
|
608
|
+
const result = await Promise.race([
|
|
609
|
+
pump.close().then(() => "closed"),
|
|
610
|
+
new Promise((resolve) => setTimeout(() => resolve("timeout"), 5e3))
|
|
594
611
|
]);
|
|
612
|
+
if (result === "timeout") {
|
|
613
|
+
}
|
|
595
614
|
} catch {
|
|
596
615
|
}
|
|
597
616
|
}
|