@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.
- package/dist/src/index.d.ts +47 -1
- package/dist/src/index.js +443 -37
- package/dist/src/index.js.map +7 -6
- package/dist/src/runtime/block-processor.d.ts +16 -11
- package/dist/src/runtime/block-processor.js +83 -30
- package/dist/src/runtime/block-processor.js.map +3 -3
- package/dist/src/runtime/catchup.js +83 -30
- package/dist/src/runtime/catchup.js.map +3 -3
- package/dist/src/runtime/processor.js +111 -37
- package/dist/src/runtime/processor.js.map +5 -5
- package/dist/src/runtime/reindex.js +109 -36
- package/dist/src/runtime/reindex.js.map +4 -4
- package/dist/src/runtime/reorg.js +83 -30
- package/dist/src/runtime/reorg.js.map +3 -3
- package/dist/src/schema/index.js +3 -2
- package/dist/src/schema/index.js.map +3 -3
- package/dist/src/service.js +111 -37
- package/dist/src/service.js.map +5 -5
- package/dist/src/validate.js +3 -2
- package/dist/src/validate.js.map +3 -3
- package/package.json +2 -2
|
@@ -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
|
|
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
|
-
|
|
2074
|
-
|
|
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
|
-
|
|
2080
|
-
|
|
2081
|
-
const
|
|
2082
|
-
if (
|
|
2083
|
-
|
|
2084
|
-
|
|
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
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
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
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
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
|
-
|
|
2107
|
-
}
|
|
2159
|
+
throw err;
|
|
2160
|
+
}
|
|
2108
2161
|
}
|
|
2109
2162
|
const totalMs = performance.now() - blockStart;
|
|
2110
2163
|
result.timing = {
|
|
@@ -2209,7 +2262,10 @@ import {
|
|
|
2209
2262
|
recordGapBatch,
|
|
2210
2263
|
resolveGaps
|
|
2211
2264
|
} from "@secondlayer/shared/db/queries/subgraph-gaps";
|
|
2212
|
-
import {
|
|
2265
|
+
import {
|
|
2266
|
+
advanceOperationCursor as advanceOperationCursor2,
|
|
2267
|
+
updateOperationProcessedEvents
|
|
2268
|
+
} from "@secondlayer/shared/db/queries/subgraph-operations";
|
|
2213
2269
|
import {
|
|
2214
2270
|
recordSubgraphProcessed as recordSubgraphProcessed2,
|
|
2215
2271
|
updateSubgraphStatus as updateSubgraphStatus2
|
|
@@ -2282,6 +2338,7 @@ async function processBlockRange(def, opts) {
|
|
|
2282
2338
|
const totalBlocks = toBlock - fromBlock + 1;
|
|
2283
2339
|
const stats = new StatsAccumulator(subgraphName, opts.isCatchup);
|
|
2284
2340
|
let blocksProcessed = 0;
|
|
2341
|
+
let blocksSkippedByCursor = 0;
|
|
2285
2342
|
let totalEventsProcessed = 0;
|
|
2286
2343
|
let totalErrors = 0;
|
|
2287
2344
|
let pendingEventsProcessed = 0;
|
|
@@ -2342,7 +2399,8 @@ async function processBlockRange(def, opts) {
|
|
|
2342
2399
|
}
|
|
2343
2400
|
const batchFailedBlocks = [];
|
|
2344
2401
|
let batchMatched = 0;
|
|
2345
|
-
const
|
|
2402
|
+
const opCursor = status === "active" && opts.operationId ? { operationId: opts.operationId } : undefined;
|
|
2403
|
+
const atomicProgress = status === "reindexing" ? { status } : opCursor;
|
|
2346
2404
|
for (let height = currentHeight;height <= batchEnd; height++) {
|
|
2347
2405
|
let blockData = batch.get(height);
|
|
2348
2406
|
if (!blockData) {
|
|
@@ -2382,6 +2440,8 @@ async function processBlockRange(def, opts) {
|
|
|
2382
2440
|
continue;
|
|
2383
2441
|
}
|
|
2384
2442
|
blocksProcessed++;
|
|
2443
|
+
if (result.skipped)
|
|
2444
|
+
blocksSkippedByCursor++;
|
|
2385
2445
|
batchMatched += result.matched;
|
|
2386
2446
|
totalEventsProcessed += result.processed;
|
|
2387
2447
|
totalErrors += result.errors;
|
|
@@ -2399,7 +2459,11 @@ async function processBlockRange(def, opts) {
|
|
|
2399
2459
|
const now = Date.now();
|
|
2400
2460
|
const shouldFlushProgress = blocksProcessed % 100 === 0 || now - lastProgressFlushAt >= PROGRESS_FLUSH_INTERVAL_MS;
|
|
2401
2461
|
if (shouldFlushProgress) {
|
|
2402
|
-
|
|
2462
|
+
if (opCursor) {
|
|
2463
|
+
await advanceOperationCursor2(targetDb, opCursor.operationId, height);
|
|
2464
|
+
} else {
|
|
2465
|
+
await updateSubgraphStatus2(targetDb, subgraphName, status, height);
|
|
2466
|
+
}
|
|
2403
2467
|
if (opts.operationId) {
|
|
2404
2468
|
await updateOperationProcessedEvents(targetDb, opts.operationId, totalEventsProcessed).catch(() => {});
|
|
2405
2469
|
}
|
|
@@ -2411,7 +2475,8 @@ async function processBlockRange(def, opts) {
|
|
|
2411
2475
|
processed: blocksProcessed,
|
|
2412
2476
|
total: totalBlocks,
|
|
2413
2477
|
currentBlock: height,
|
|
2414
|
-
pct: Math.round(blocksProcessed / totalBlocks * 100)
|
|
2478
|
+
pct: Math.round(blocksProcessed / totalBlocks * 100),
|
|
2479
|
+
...blocksSkippedByCursor > 0 ? { skippedByCursor: blocksSkippedByCursor } : {}
|
|
2415
2480
|
});
|
|
2416
2481
|
}
|
|
2417
2482
|
}
|
|
@@ -2437,7 +2502,11 @@ async function processBlockRange(def, opts) {
|
|
|
2437
2502
|
if (jumpTo > batchEnd + 1) {
|
|
2438
2503
|
const skipped = Math.min(jumpTo, toBlock + 1) - (batchEnd + 1);
|
|
2439
2504
|
blocksProcessed += skipped;
|
|
2440
|
-
|
|
2505
|
+
if (opCursor) {
|
|
2506
|
+
await advanceOperationCursor2(targetDb, opCursor.operationId, jumpTo - 1);
|
|
2507
|
+
} else {
|
|
2508
|
+
await updateSubgraphStatus2(targetDb, subgraphName, status, jumpTo - 1);
|
|
2509
|
+
}
|
|
2441
2510
|
logger6.info("Sparse skip", {
|
|
2442
2511
|
subgraph: subgraphName,
|
|
2443
2512
|
from: batchEnd + 1,
|
|
@@ -2495,7 +2564,11 @@ async function reindexSubgraph(def, opts) {
|
|
|
2495
2564
|
for (const stmt of statements) {
|
|
2496
2565
|
await client.unsafe(stmt);
|
|
2497
2566
|
}
|
|
2498
|
-
|
|
2567
|
+
await updateSubgraphStatus2(targetDb, subgraphName, "reindexing", Math.max(0, fromBlock - 1));
|
|
2568
|
+
logger6.info("Schema recreated for reindex", {
|
|
2569
|
+
subgraph: subgraphName,
|
|
2570
|
+
cursorResetTo: Math.max(0, fromBlock - 1)
|
|
2571
|
+
});
|
|
2499
2572
|
await targetDb.updateTable("subgraphs").set({
|
|
2500
2573
|
last_processed_block: initialReindexProgressBlock(fromBlock),
|
|
2501
2574
|
reindex_from_block: fromBlock,
|
|
@@ -2683,5 +2756,5 @@ export {
|
|
|
2683
2756
|
backfillSubgraph
|
|
2684
2757
|
};
|
|
2685
2758
|
|
|
2686
|
-
//# debugId=
|
|
2759
|
+
//# debugId=16E6F70B818734C264756E2164756E21
|
|
2687
2760
|
//# sourceMappingURL=reindex.js.map
|