@secondlayer/subgraphs 4.1.1 → 4.1.3

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/src/index.js CHANGED
@@ -2290,6 +2290,8 @@ function indexEventTypesForFilterTypes(filterTypes) {
2290
2290
  return [...types];
2291
2291
  }
2292
2292
  function referencedIndexEventTypes(subgraph) {
2293
+ if (!subgraph.sources)
2294
+ return [];
2293
2295
  return indexEventTypesForFilterTypes(sourceFilters(subgraph).map((f) => f.type));
2294
2296
  }
2295
2297
  function isStreamsIndexEligible(subgraph) {
@@ -3407,6 +3409,66 @@ function startCatchUpLeader(opts = {}) {
3407
3409
  });
3408
3410
  }
3409
3411
 
3412
+ // src/runtime/decoder-bound.ts
3413
+ import { decodeStreamsCursor, isEmptyRangeCursor } from "@secondlayer/shared";
3414
+ import { getSourceDb as getSourceDb3 } from "@secondlayer/shared/db";
3415
+ function decoderNameForEventType(indexEventType) {
3416
+ return `decode.${indexEventType}.v1`;
3417
+ }
3418
+ function decoderNamesForIndexEventTypes(eventTypes) {
3419
+ return eventTypes.map(decoderNameForEventType);
3420
+ }
3421
+ function decoderNamesForSubgraph(subgraph) {
3422
+ return decoderNamesForIndexEventTypes(referencedIndexEventTypes(subgraph));
3423
+ }
3424
+ function usesDecodedIndexPlane(subgraph) {
3425
+ return process.env.SUBGRAPH_SOURCE === "streams-index" && isStreamsIndexEligible(subgraph);
3426
+ }
3427
+ function committedHeight(cursor) {
3428
+ if (!cursor)
3429
+ return null;
3430
+ try {
3431
+ const decoded = decodeStreamsCursor(cursor);
3432
+ if (isEmptyRangeCursor(decoded))
3433
+ return decoded.block_height;
3434
+ return Math.max(0, decoded.block_height - 1);
3435
+ } catch {
3436
+ return null;
3437
+ }
3438
+ }
3439
+ async function decoderBoundTip(decoderNames, opts) {
3440
+ if (decoderNames.length === 0)
3441
+ return { kind: "unbounded" };
3442
+ const sourceDb = opts?.sourceDb ?? getSourceDb3();
3443
+ const rows = await sourceDb.selectFrom("decoder_checkpoints").select(["decoder_name", "last_cursor"]).where("decoder_name", "in", decoderNames).execute();
3444
+ const byName = new Map(rows.map((r) => [r.decoder_name, r.last_cursor]));
3445
+ const missing = [];
3446
+ const heights = [];
3447
+ for (const name of decoderNames) {
3448
+ const height = committedHeight(byName.get(name));
3449
+ if (height === null)
3450
+ missing.push(name);
3451
+ else
3452
+ heights.push(height);
3453
+ }
3454
+ if (missing.length > 0)
3455
+ return { kind: "stall", missing };
3456
+ return { kind: "height", height: Math.min(...heights) };
3457
+ }
3458
+ async function boundSourceTip(rawTip, decoderNames, opts) {
3459
+ const bound = await decoderBoundTip(decoderNames, opts);
3460
+ if (bound.kind === "stall")
3461
+ return { ok: false, missing: bound.missing };
3462
+ if (bound.kind === "unbounded") {
3463
+ return { ok: true, tip: rawTip, floor: null };
3464
+ }
3465
+ return {
3466
+ ok: true,
3467
+ tip: Math.min(rawTip, bound.height),
3468
+ floor: bound.height
3469
+ };
3470
+ }
3471
+
3410
3472
  // src/runtime/catchup.ts
3411
3473
  var LOG_INTERVAL = 1000;
3412
3474
  var STANDARD_CATCHUP_BATCH_CONFIG = {
@@ -3517,7 +3579,31 @@ async function catchUpSubgraph(subgraph, subgraphName) {
3517
3579
  if (!subgraphRow)
3518
3580
  return 0;
3519
3581
  const lastProcessedBlock = Number(subgraphRow.last_processed_block);
3520
- const chainTip = await source.getTip();
3582
+ const rawTip = await source.getTip();
3583
+ if (rawTip <= 0)
3584
+ return 0;
3585
+ let chainTip = rawTip;
3586
+ if (usesDecodedIndexPlane(subgraph)) {
3587
+ const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(subgraph));
3588
+ if (!bound.ok) {
3589
+ logger8.warn("Subgraph catch-up stalled: missing decoder checkpoint", {
3590
+ event: "subgraph_catchup_decoder_stall",
3591
+ subgraph: subgraphName,
3592
+ missing: bound.missing
3593
+ });
3594
+ return 0;
3595
+ }
3596
+ if (bound.floor !== null && bound.floor < rawTip) {
3597
+ logger8.debug("Subgraph catch-up tip bounded by decoder progress", {
3598
+ event: "subgraph_catchup_decoder_floor",
3599
+ subgraph: subgraphName,
3600
+ rawTip,
3601
+ floor: bound.floor,
3602
+ tip: bound.tip
3603
+ });
3604
+ }
3605
+ chainTip = bound.tip;
3606
+ }
3521
3607
  if (chainTip <= 0 || lastProcessedBlock >= chainTip)
3522
3608
  return 0;
3523
3609
  const subgraphStart = Number(subgraphRow.start_block) || 1;
@@ -3980,7 +4066,29 @@ async function processBlockRange(def, opts) {
3980
4066
  async function resolveBlockRange(source, def, opts) {
3981
4067
  const definitionStart = def.startBlock ?? 1;
3982
4068
  const fromBlock = opts?.startBlockFloor != null ? Math.max(definitionStart, opts.startBlockFloor) : definitionStart;
3983
- return { fromBlock, toBlock: await source.getTip() };
4069
+ const rawTip = await source.getTip();
4070
+ if (!usesDecodedIndexPlane(def)) {
4071
+ return { fromBlock, toBlock: rawTip };
4072
+ }
4073
+ const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(def));
4074
+ if (!bound.ok) {
4075
+ logger10.warn("Reindex stalled: missing decoder checkpoint", {
4076
+ event: "subgraph_reindex_decoder_stall",
4077
+ subgraph: def.name,
4078
+ missing: bound.missing
4079
+ });
4080
+ throw new Error(`Reindex stalled: missing decoder checkpoint (${bound.missing.join(", ")})`);
4081
+ }
4082
+ if (bound.floor !== null && bound.floor < rawTip) {
4083
+ logger10.debug("Reindex tip bounded by decoder progress", {
4084
+ event: "subgraph_reindex_decoder_floor",
4085
+ subgraph: def.name,
4086
+ rawTip,
4087
+ floor: bound.floor,
4088
+ tip: bound.tip
4089
+ });
4090
+ }
4091
+ return { fromBlock, toBlock: bound.tip };
3984
4092
  }
3985
4093
  async function clearReindexMetadata(db, subgraphName) {
3986
4094
  await db.updateTable("subgraphs").set({ reindex_from_block: null, reindex_to_block: null }).where("name", "=", subgraphName).execute();
@@ -5438,5 +5546,5 @@ export {
5438
5546
  ChainReadError
5439
5547
  };
5440
5548
 
5441
- //# debugId=E71414D5C2925EDA64756E2164756E21
5549
+ //# debugId=5A8D4A3C8F2C6DFE64756E2164756E21
5442
5550
  //# sourceMappingURL=index.js.map