@secondlayer/subgraphs 3.13.0 → 3.14.1

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.
@@ -1332,6 +1332,7 @@ function matchSources(sources, transactions, events, traitContracts = new Map) {
1332
1332
  // src/runtime/block-processor.ts
1333
1333
  import { getTargetDb } from "@secondlayer/shared/db";
1334
1334
  import { resolveTraitContractIds } from "@secondlayer/shared/db/queries/contracts";
1335
+ import { advanceOperationCursor } from "@secondlayer/shared/db/queries/subgraph-operations";
1335
1336
  import {
1336
1337
  isByoSubgraph,
1337
1338
  recordSubgraphProcessed,
@@ -1951,6 +1952,21 @@ async function resolveTraitContracts(subgraph, blockHeight, db) {
1951
1952
  }
1952
1953
  return resolved;
1953
1954
  }
1955
+
1956
+ class CursorRaceLostError extends Error {
1957
+ constructor(operationId, height) {
1958
+ super(`op ${operationId} lost cursor race at block ${height}`);
1959
+ this.name = "CursorRaceLostError";
1960
+ }
1961
+ }
1962
+ function opCursorMode(opts) {
1963
+ const ap = opts?.atomicProgress;
1964
+ return ap && "operationId" in ap ? ap : undefined;
1965
+ }
1966
+ function statusMode(opts) {
1967
+ const ap = opts?.atomicProgress;
1968
+ return ap && "status" in ap ? ap : undefined;
1969
+ }
1954
1970
  var BLOCK_RETRY_DELAYS_MS = [500, 2000, 5000];
1955
1971
  function journalEnabled(opts) {
1956
1972
  return !opts?.skipProgressUpdate;
@@ -2044,12 +2060,19 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2044
2060
  }
2045
2061
  };
2046
2062
  if (route.byo) {
2047
- if (opts?.atomicProgress) {
2063
+ if (statusMode(opts)) {
2048
2064
  const row = await targetDb.selectFrom("subgraphs").select("last_processed_block").where("name", "=", subgraphName).executeTakeFirst();
2049
2065
  if (row && Number(row.last_processed_block) >= blockHeight) {
2050
2066
  result.skipped = true;
2051
2067
  return result;
2052
2068
  }
2069
+ } else if (opCursorMode(opts)) {
2070
+ const om = opCursorMode(opts);
2071
+ const row = await targetDb.selectFrom("subgraph_operations").select("cursor_block").where("id", "=", om.operationId).executeTakeFirst();
2072
+ if (row?.cursor_block != null && Number(row.cursor_block) >= blockHeight) {
2073
+ result.skipped = true;
2074
+ return result;
2075
+ }
2053
2076
  }
2054
2077
  let runResult = { processed: 0, errors: 0 };
2055
2078
  let manifest;
@@ -2070,41 +2093,71 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2070
2093
  if (manifest && manifest.count > 0) {
2071
2094
  await emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block.height);
2072
2095
  }
2073
- if (opts?.atomicProgress && manifest && manifest.count > 0) {
2074
- await updateSubgraphStatus(tx, subgraphName, opts.atomicProgress.status, blockHeight);
2096
+ const byoSm = statusMode(opts);
2097
+ const byoOm = opCursorMode(opts);
2098
+ if (byoSm && manifest && manifest.count > 0) {
2099
+ await updateSubgraphStatus(tx, subgraphName, byoSm.status, blockHeight);
2100
+ } else if (byoOm && manifest && manifest.count > 0) {
2101
+ await advanceOperationCursor(tx, byoOm.operationId, blockHeight);
2075
2102
  }
2076
2103
  await applyProgress(tx, runResult);
2077
2104
  });
2078
2105
  } else {
2079
- await targetDb.transaction().execute(async (tx) => {
2080
- if (opts?.atomicProgress) {
2081
- const row = await tx.selectFrom("subgraphs").select("last_processed_block").where("name", "=", subgraphName).executeTakeFirst();
2082
- if (row && Number(row.last_processed_block) >= blockHeight) {
2083
- result.skipped = true;
2084
- return;
2106
+ try {
2107
+ await targetDb.transaction().execute(async (tx) => {
2108
+ const opMode = opCursorMode(opts);
2109
+ if (statusMode(opts)) {
2110
+ const row = await tx.selectFrom("subgraphs").select("last_processed_block").where("name", "=", subgraphName).executeTakeFirst();
2111
+ if (row && Number(row.last_processed_block) >= blockHeight) {
2112
+ result.skipped = true;
2113
+ return;
2114
+ }
2115
+ } else if (opMode) {
2116
+ const row = await tx.selectFrom("subgraph_operations").select("cursor_block").where("id", "=", opMode.operationId).executeTakeFirst();
2117
+ if (row?.cursor_block != null && Number(row.cursor_block) >= blockHeight) {
2118
+ result.skipped = true;
2119
+ return;
2120
+ }
2085
2121
  }
2086
- }
2087
- const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx, false, journalEnabled(opts));
2088
- const handlerStart = performance.now();
2089
- const runResult = await runHandlers(subgraph, matched, ctx);
2090
- handlerMs = performance.now() - handlerStart;
2091
- result.processed = runResult.processed;
2092
- result.errors = runResult.errors;
2093
- let flushedWrites = false;
2094
- if (ctx.pendingOps > 0) {
2095
- const flushStart = performance.now();
2096
- const manifest = await ctx.flush();
2097
- flushedWrites = manifest.count > 0;
2098
- if (manifest.count > 0) {
2099
- await emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block.height);
2122
+ const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx, false, journalEnabled(opts));
2123
+ const handlerStart = performance.now();
2124
+ const runResult = await runHandlers(subgraph, matched, ctx);
2125
+ handlerMs = performance.now() - handlerStart;
2126
+ result.processed = runResult.processed;
2127
+ result.errors = runResult.errors;
2128
+ let flushedWrites = false;
2129
+ if (ctx.pendingOps > 0) {
2130
+ const flushStart = performance.now();
2131
+ const manifest = await ctx.flush();
2132
+ flushedWrites = manifest.count > 0;
2133
+ if (manifest.count > 0) {
2134
+ await emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block.height);
2135
+ }
2136
+ flushMs = performance.now() - flushStart;
2100
2137
  }
2101
- flushMs = performance.now() - flushStart;
2102
- }
2103
- if (opts?.atomicProgress && flushedWrites) {
2104
- await updateSubgraphStatus(tx, subgraphName, opts.atomicProgress.status, blockHeight);
2138
+ const sm = statusMode(opts);
2139
+ if (sm && flushedWrites) {
2140
+ await updateSubgraphStatus(tx, subgraphName, sm.status, blockHeight);
2141
+ } else if (opMode && flushedWrites) {
2142
+ const advanced = await advanceOperationCursor(tx, opMode.operationId, blockHeight);
2143
+ if (!advanced) {
2144
+ throw new CursorRaceLostError(opMode.operationId, blockHeight);
2145
+ }
2146
+ }
2147
+ await applyProgress(tx, runResult);
2148
+ });
2149
+ } catch (err) {
2150
+ if (err instanceof CursorRaceLostError) {
2151
+ logger5.warn("cursor race lost — block already covered", {
2152
+ subgraph: subgraphName,
2153
+ blockHeight,
2154
+ error: err.message
2155
+ });
2156
+ result.skipped = true;
2157
+ return result;
2105
2158
  }
2106
- await applyProgress(tx, runResult);
2107
- });
2159
+ throw err;
2160
+ }
2108
2161
  }
2109
2162
  const totalMs = performance.now() - blockStart;
2110
2163
  result.timing = {
@@ -2253,5 +2306,5 @@ export {
2253
2306
  handleSubgraphReorg
2254
2307
  };
2255
2308
 
2256
- //# debugId=9E3057C106B5756964756E2164756E21
2309
+ //# debugId=01BB18F0A13F194064756E2164756E21
2257
2310
  //# sourceMappingURL=reorg.js.map