@secondlayer/sdk 6.48.1 → 6.49.0

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.d.ts CHANGED
@@ -773,12 +773,21 @@ type ConsumerBatchContext<
773
773
  > = {
774
774
  /** Checkpoint to commit alongside your rows. */
775
775
  cursor: string | null;
776
- /** Highest canonical block the sweep has reached. `null` before the first
777
- * row of a fresh consume. */
776
+ /** Highest canonical block a row was DELIVERED from. `null` before the
777
+ * first row of a fresh consume. With a sparse filter this parks at the
778
+ * last matching event — it measures event recency, not progress. */
778
779
  height: number | null;
780
+ /** Highest canonical block the sweep has VERIFIED through: an empty page
781
+ * is the server confirming nothing matches between the cursor and the
782
+ * tip, so a caught-up tail scans to the tip even when `height` is far
783
+ * below it. Rolls back with reorg rewinds. */
784
+ scannedHeight: number | null;
779
785
  /** Chain tip as of this page's read. */
780
786
  tipHeight: number;
781
- /** `tipHeight - height`, floored at 0. `null` until `height` is known. */
787
+ /** `tipHeight - scannedHeight`, floored at 0 — the consumer's actual
788
+ * backlog. `null` until a position is known. A caught-up consumer on a
789
+ * quiet contract reads ~0 here while `tipHeight - height` grows — that
790
+ * difference is event age, not lag. */
782
791
  blocksBehind: number | null;
783
792
  /**
784
793
  * The full tip for this page — `StreamsTip` or `IndexTip` depending on the
@@ -3324,7 +3333,10 @@ interface ConsumerHealth {
3324
3333
  * "are we near the tip": during a genesis backfill the loop is millions of
3325
3334
  * blocks behind and perfectly healthy, so lag can't be the signal. A wedged
3326
3335
  * loop stops reporting pages and flips to 503 — that's what platforms
3327
- * should restart on. `blocks_behind` still ships in the body for dashboards.
3336
+ * should restart on. The body carries position for dashboards:
3337
+ * `blocks_behind` is the actual backlog (`tip - scanned_height`, ~0 for a
3338
+ * caught-up tail even on a quiet contract), while `block_height` is the
3339
+ * last DELIVERED row — its distance from the tip is event age, not lag.
3328
3340
  */
3329
3341
  declare function consumerHealth(options?: {
3330
3342
  staleAfterMs?: number;
package/dist/index.js CHANGED
@@ -606,13 +606,15 @@ function resumeHeight(cursor) {
606
606
  return null;
607
607
  }
608
608
  }
609
- function batchContext(cursor, height, tip, reorgs = []) {
609
+ function batchContext(cursor, height, tip, reorgs = [], scannedHeight = null) {
610
610
  const tipHeight = tip.block_height;
611
+ const position = scannedHeight ?? height;
611
612
  return {
612
613
  cursor,
613
614
  height,
615
+ scannedHeight: position,
614
616
  tipHeight,
615
- blocksBehind: height === null ? null : Math.max(0, tipHeight - height),
617
+ blocksBehind: position === null ? null : Math.max(0, tipHeight - position),
616
618
  tip,
617
619
  reorgs
618
620
  };
@@ -679,6 +681,7 @@ async function consumeStreamsEvents(opts) {
679
681
  let pages = 0;
680
682
  let emptyPolls = 0;
681
683
  let height = resumeHeight(cursor);
684
+ let scanned = height;
682
685
  while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
683
686
  const envelope = await fetchPageWithRetry(() => opts.fetchEvents({
684
687
  cursor,
@@ -710,6 +713,7 @@ async function consumeStreamsEvents(opts) {
710
713
  }
711
714
  cursor = rewind;
712
715
  height = forkPoint > 0 ? forkPoint - 1 : null;
716
+ scanned = height;
713
717
  emptyPolls = 0;
714
718
  continue;
715
719
  }
@@ -717,7 +721,14 @@ async function consumeStreamsEvents(opts) {
717
721
  const emitted = finalizedOnly ? envelope.events.filter((event) => event.finalized) : envelope.events;
718
722
  const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
719
723
  height = emitted.at(-1)?.block_height ?? height;
720
- const ctx = batchContext(checkpoint ?? cursor, height, envelope.tip, envelope.reorgs);
724
+ if (emitted.length > 0) {
725
+ scanned = height;
726
+ } else if (checkpoint !== null && checkpoint !== cursor) {
727
+ scanned = resumeHeight(checkpoint) ?? scanned;
728
+ } else if (envelope.events.length === 0) {
729
+ scanned = envelope.tip.block_height;
730
+ }
731
+ const ctx = batchContext(checkpoint ?? cursor, height, envelope.tip, envelope.reorgs, scanned);
721
732
  opts.onProgress?.(ctx);
722
733
  let nextCursor;
723
734
  if (opts.sink) {
@@ -846,6 +857,7 @@ async function consumeIndexFeed(opts) {
846
857
  let pages = 0;
847
858
  let emptyPolls = 0;
848
859
  let height = resumeHeight(cursor);
860
+ let scanned = height;
849
861
  while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
850
862
  const envelope = await fetchPageWithRetry(() => opts.fetchPage({
851
863
  cursor,
@@ -871,6 +883,7 @@ async function consumeIndexFeed(opts) {
871
883
  }
872
884
  cursor = rewind;
873
885
  height = forkPoint > 0 ? forkPoint - 1 : null;
886
+ scanned = height;
874
887
  emptyPolls = 0;
875
888
  continue;
876
889
  }
@@ -879,7 +892,14 @@ async function consumeIndexFeed(opts) {
879
892
  const emitted = finalizedOnly ? items.filter((item) => item.block_height <= envelope.tip.finalized_height) : items;
880
893
  const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
881
894
  height = emitted.at(-1)?.block_height ?? height;
882
- const ctx = batchContext(checkpoint ?? cursor, height, envelope.tip, envelope.reorgs);
895
+ if (emitted.length > 0) {
896
+ scanned = height;
897
+ } else if (checkpoint !== null && checkpoint !== cursor) {
898
+ scanned = resumeHeight(checkpoint) ?? scanned;
899
+ } else {
900
+ scanned = finalizedOnly ? envelope.tip.finalized_height : envelope.tip.block_height;
901
+ }
902
+ const ctx = batchContext(checkpoint ?? cursor, height, envelope.tip, envelope.reorgs, scanned);
883
903
  opts.onProgress?.(ctx);
884
904
  let nextCursor;
885
905
  if (opts.sink) {
@@ -2668,6 +2688,7 @@ function consumerHealth(options = {}) {
2668
2688
  ok,
2669
2689
  checkpoint: lastCtx?.cursor ?? null,
2670
2690
  block_height: lastCtx?.height ?? null,
2691
+ scanned_height: lastCtx?.scannedHeight ?? null,
2671
2692
  tip_height: lastCtx?.tipHeight ?? null,
2672
2693
  blocks_behind: lastCtx?.blocksBehind ?? null,
2673
2694
  idle_s: Math.floor(idleMs / 1000),
@@ -2908,5 +2929,5 @@ export {
2908
2929
  ApiError
2909
2930
  };
2910
2931
 
2911
- //# debugId=33DAF3413D4D67EA64756E2164756E21
2932
+ //# debugId=7E3377791B68431D64756E2164756E21
2912
2933
  //# sourceMappingURL=index.js.map