@secondlayer/subgraphs 3.25.0 → 3.26.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.
@@ -345,6 +345,29 @@ interface SubgraphDefinition {
345
345
  /** Handler functions — keys must match source names (or "*" for catch-all) */
346
346
  handlers: Record<string, SubgraphHandler>;
347
347
  }
348
+ import { Block, Event, Transaction } from "@secondlayer/shared/db";
349
+ interface BlockData {
350
+ block: Block;
351
+ txs: Transaction[];
352
+ events: Event[];
353
+ }
354
+ /**
355
+ * Where the subgraph runtime reads canonical chain data. Today it taps the
356
+ * indexer Postgres directly (`PostgresBlockSource`); the re-point adds a
357
+ * `PublicApiBlockSource` that consumes the Streams clock + Index data over
358
+ * HTTP. `matchSources` / handlers / flush / outbox are unchanged — only the
359
+ * loader + tip swap behind this seam.
360
+ */
361
+ interface BlockSource {
362
+ /** Highest canonical block height available to process. */
363
+ getTip(): Promise<number>;
364
+ /** Canonical block data for [fromHeight, toHeight], keyed by height. */
365
+ loadBlockRange(fromHeight: number, toHeight: number): Promise<Map<number, BlockData>>;
366
+ /** Sparse-scan probe: lowest height in (afterHeight, untilHeight] holding
367
+ * an event this source's subgraph could match, or null when the rest of
368
+ * the range is empty. Optional — only event-scoped sources support it. */
369
+ nextDataHeight?(afterHeight: number, untilHeight: number): Promise<number | null>;
370
+ }
348
371
  type ReindexBatchConfig = {
349
372
  defaultBatchSize: number
350
373
  minBatchSize: number
@@ -364,16 +387,49 @@ declare function initialReindexProgressBlock(fromBlock: number): number;
364
387
  declare function resolveReindexResumeBlock(row: ReindexResumeRow): number | null;
365
388
  declare function resolveReindexBatchConfig(env?: ReindexBatchEnv): ReindexBatchConfig;
366
389
  interface ReindexOptions {
367
- fromBlock?: number;
368
- toBlock?: number;
390
+ /**
391
+ * Policy floor on the walk's first block — NOT a caller-supplied range.
392
+ * Free-tier accounts may not reindex below their registered `start_block`
393
+ * (see `resolveGenesisPolicy` on the API side); this raises the walk start
394
+ * and can never lower it. There is deliberately no `toBlock` counterpart:
395
+ * a reindex always runs to chain tip. See {@link resolveBlockRange}.
396
+ */
397
+ startBlockFloor?: number;
369
398
  schemaName?: string;
370
399
  /** Op row to receive processed_events on each progress flush. */
371
400
  operationId?: string;
372
401
  signal?: AbortSignal;
373
402
  }
374
403
  /**
404
+ * Resolve the reindex walk range. Always the whole subgraph:
405
+ * `[def.startBlock, chain tip]`. Chain tip reads from `index_progress` —
406
+ * lives in the source DB.
407
+ *
408
+ * Reindex drops the schema unconditionally, so the walk range is also the
409
+ * ONLY data that survives. A narrower walk therefore does not "reindex a
410
+ * range" — it silently destroys every row outside it while leaving the
411
+ * subgraph reporting `active` at chain tip (f079: a single-block
412
+ * `--from-block N --to-block N` emptied sbtc-flows, and the first recovery
413
+ * attempt rebuilt only 21% of its history). Ranged, additive work is
414
+ * `backfillSubgraph`'s job.
415
+ *
416
+ * `startBlockFloor` is a plan-policy floor, not a range: it can only raise
417
+ * the start block, never lower it, and never bounds the end.
418
+ */
419
+ declare function resolveBlockRange(source: BlockSource, def: SubgraphDefinition, opts?: ReindexOptions): Promise<{
420
+ fromBlock: number
421
+ toBlock: number
422
+ }>;
423
+ /**
375
424
  * Reindex a subgraph by dropping its tables, recreating them, and reprocessing
376
425
  * all historical blocks through the handler pipeline.
426
+ *
427
+ * Always whole-subgraph: `[start_block, chain tip]`. There is no ranged
428
+ * reindex — the drop cannot be scoped to a range without re-running delta
429
+ * handlers (`ctx.increment` / `ctx.update` / `ctx.patchOrInsert`) over rows
430
+ * that were never removed, which is the exact double-count hazard `backfill`
431
+ * already refuses. Use `backfillSubgraph` for ranged, additive work.
432
+ *
377
433
  * Supports cancellation via AbortSignal — on shutdown abort, status stays
378
434
  * "reindexing" for auto-resume; on user cancel, status resets to "active".
379
435
  */
@@ -405,4 +461,4 @@ declare function backfillSubgraph(def: SubgraphDefinition, opts: {
405
461
  }): Promise<{
406
462
  processed: number
407
463
  }>;
408
- export { resumeReindex, resolveReindexResumeBlock, resolveReindexBatchConfig, reindexSubgraph, initialReindexProgressBlock, backfillSubgraph, ReindexOptions };
464
+ export { resumeReindex, resolveReindexResumeBlock, resolveReindexBatchConfig, resolveBlockRange, reindexSubgraph, initialReindexProgressBlock, backfillSubgraph, ReindexOptions };
@@ -2598,6 +2598,10 @@ async function resolveRoute(subgraphName, targetDb) {
2598
2598
  version: row?.version ?? ""
2599
2599
  };
2600
2600
  routeCache.set(subgraphName, route);
2601
+ logger7.info("subgraph handler dispatch path resolved", {
2602
+ subgraph: subgraphName,
2603
+ path: sandboxEnabled({ sandbox_workers: route.sandboxWorkers }) ? "sandbox" : "in-process"
2604
+ });
2601
2605
  return route;
2602
2606
  }
2603
2607
  function invalidateSubgraphRoute(subgraphName) {
@@ -3349,9 +3353,9 @@ async function processBlockRange(def, opts) {
3349
3353
  return { blocksProcessed, totalEventsProcessed, totalErrors, aborted };
3350
3354
  }
3351
3355
  async function resolveBlockRange(source, def, opts) {
3352
- const fromBlock = opts?.fromBlock ?? def.startBlock ?? 1;
3353
- const toBlock = opts?.toBlock != null ? opts.toBlock : await source.getTip();
3354
- return { fromBlock, toBlock };
3356
+ const definitionStart = def.startBlock ?? 1;
3357
+ const fromBlock = opts?.startBlockFloor != null ? Math.max(definitionStart, opts.startBlockFloor) : definitionStart;
3358
+ return { fromBlock, toBlock: await source.getTip() };
3355
3359
  }
3356
3360
  async function clearReindexMetadata(db, subgraphName) {
3357
3361
  await db.updateTable("subgraphs").set({ reindex_from_block: null, reindex_to_block: null }).where("name", "=", subgraphName).execute();
@@ -3572,10 +3576,11 @@ export {
3572
3576
  resumeReindex,
3573
3577
  resolveReindexResumeBlock,
3574
3578
  resolveReindexBatchConfig,
3579
+ resolveBlockRange,
3575
3580
  reindexSubgraph,
3576
3581
  initialReindexProgressBlock,
3577
3582
  backfillSubgraph
3578
3583
  };
3579
3584
 
3580
- //# debugId=BB1549A85CE0B1BD64756E2164756E21
3585
+ //# debugId=BBDD389FC2EBC25364756E2164756E21
3581
3586
  //# sourceMappingURL=reindex.js.map