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