@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 +111 -3
- package/dist/src/index.js.map +7 -6
- package/dist/src/runtime/block-processor.js +3 -1
- package/dist/src/runtime/block-processor.js.map +3 -3
- package/dist/src/runtime/catchup.js +88 -2
- package/dist/src/runtime/catchup.js.map +7 -6
- package/dist/src/runtime/processor.js +111 -3
- package/dist/src/runtime/processor.js.map +7 -6
- package/dist/src/runtime/reindex.js +111 -3
- package/dist/src/runtime/reindex.js.map +7 -6
- package/dist/src/runtime/reorg.js +88 -2
- package/dist/src/runtime/reorg.js.map +6 -5
- package/dist/src/runtime/replay.js +68 -4
- package/dist/src/runtime/replay.js.map +6 -5
- package/dist/src/service.js +111 -3
- package/dist/src/service.js.map +7 -6
- package/package.json +1 -1
package/dist/src/service.js
CHANGED
|
@@ -2075,6 +2075,8 @@ function indexEventTypesForFilterTypes(filterTypes) {
|
|
|
2075
2075
|
return [...types];
|
|
2076
2076
|
}
|
|
2077
2077
|
function referencedIndexEventTypes(subgraph) {
|
|
2078
|
+
if (!subgraph.sources)
|
|
2079
|
+
return [];
|
|
2078
2080
|
return indexEventTypesForFilterTypes(sourceFilters(subgraph).map((f) => f.type));
|
|
2079
2081
|
}
|
|
2080
2082
|
function isStreamsIndexEligible(subgraph) {
|
|
@@ -3192,6 +3194,66 @@ function startCatchUpLeader(opts = {}) {
|
|
|
3192
3194
|
});
|
|
3193
3195
|
}
|
|
3194
3196
|
|
|
3197
|
+
// src/runtime/decoder-bound.ts
|
|
3198
|
+
import { decodeStreamsCursor, isEmptyRangeCursor } from "@secondlayer/shared";
|
|
3199
|
+
import { getSourceDb as getSourceDb3 } from "@secondlayer/shared/db";
|
|
3200
|
+
function decoderNameForEventType(indexEventType) {
|
|
3201
|
+
return `decode.${indexEventType}.v1`;
|
|
3202
|
+
}
|
|
3203
|
+
function decoderNamesForIndexEventTypes(eventTypes) {
|
|
3204
|
+
return eventTypes.map(decoderNameForEventType);
|
|
3205
|
+
}
|
|
3206
|
+
function decoderNamesForSubgraph(subgraph) {
|
|
3207
|
+
return decoderNamesForIndexEventTypes(referencedIndexEventTypes(subgraph));
|
|
3208
|
+
}
|
|
3209
|
+
function usesDecodedIndexPlane(subgraph) {
|
|
3210
|
+
return process.env.SUBGRAPH_SOURCE === "streams-index" && isStreamsIndexEligible(subgraph);
|
|
3211
|
+
}
|
|
3212
|
+
function committedHeight(cursor) {
|
|
3213
|
+
if (!cursor)
|
|
3214
|
+
return null;
|
|
3215
|
+
try {
|
|
3216
|
+
const decoded = decodeStreamsCursor(cursor);
|
|
3217
|
+
if (isEmptyRangeCursor(decoded))
|
|
3218
|
+
return decoded.block_height;
|
|
3219
|
+
return Math.max(0, decoded.block_height - 1);
|
|
3220
|
+
} catch {
|
|
3221
|
+
return null;
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
async function decoderBoundTip(decoderNames, opts) {
|
|
3225
|
+
if (decoderNames.length === 0)
|
|
3226
|
+
return { kind: "unbounded" };
|
|
3227
|
+
const sourceDb = opts?.sourceDb ?? getSourceDb3();
|
|
3228
|
+
const rows = await sourceDb.selectFrom("decoder_checkpoints").select(["decoder_name", "last_cursor"]).where("decoder_name", "in", decoderNames).execute();
|
|
3229
|
+
const byName = new Map(rows.map((r) => [r.decoder_name, r.last_cursor]));
|
|
3230
|
+
const missing = [];
|
|
3231
|
+
const heights = [];
|
|
3232
|
+
for (const name of decoderNames) {
|
|
3233
|
+
const height = committedHeight(byName.get(name));
|
|
3234
|
+
if (height === null)
|
|
3235
|
+
missing.push(name);
|
|
3236
|
+
else
|
|
3237
|
+
heights.push(height);
|
|
3238
|
+
}
|
|
3239
|
+
if (missing.length > 0)
|
|
3240
|
+
return { kind: "stall", missing };
|
|
3241
|
+
return { kind: "height", height: Math.min(...heights) };
|
|
3242
|
+
}
|
|
3243
|
+
async function boundSourceTip(rawTip, decoderNames, opts) {
|
|
3244
|
+
const bound = await decoderBoundTip(decoderNames, opts);
|
|
3245
|
+
if (bound.kind === "stall")
|
|
3246
|
+
return { ok: false, missing: bound.missing };
|
|
3247
|
+
if (bound.kind === "unbounded") {
|
|
3248
|
+
return { ok: true, tip: rawTip, floor: null };
|
|
3249
|
+
}
|
|
3250
|
+
return {
|
|
3251
|
+
ok: true,
|
|
3252
|
+
tip: Math.min(rawTip, bound.height),
|
|
3253
|
+
floor: bound.height
|
|
3254
|
+
};
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3195
3257
|
// src/runtime/catchup.ts
|
|
3196
3258
|
var LOG_INTERVAL = 1000;
|
|
3197
3259
|
var STANDARD_CATCHUP_BATCH_CONFIG = {
|
|
@@ -3302,7 +3364,31 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3302
3364
|
if (!subgraphRow)
|
|
3303
3365
|
return 0;
|
|
3304
3366
|
const lastProcessedBlock = Number(subgraphRow.last_processed_block);
|
|
3305
|
-
const
|
|
3367
|
+
const rawTip = await source.getTip();
|
|
3368
|
+
if (rawTip <= 0)
|
|
3369
|
+
return 0;
|
|
3370
|
+
let chainTip = rawTip;
|
|
3371
|
+
if (usesDecodedIndexPlane(subgraph)) {
|
|
3372
|
+
const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(subgraph));
|
|
3373
|
+
if (!bound.ok) {
|
|
3374
|
+
logger8.warn("Subgraph catch-up stalled: missing decoder checkpoint", {
|
|
3375
|
+
event: "subgraph_catchup_decoder_stall",
|
|
3376
|
+
subgraph: subgraphName,
|
|
3377
|
+
missing: bound.missing
|
|
3378
|
+
});
|
|
3379
|
+
return 0;
|
|
3380
|
+
}
|
|
3381
|
+
if (bound.floor !== null && bound.floor < rawTip) {
|
|
3382
|
+
logger8.debug("Subgraph catch-up tip bounded by decoder progress", {
|
|
3383
|
+
event: "subgraph_catchup_decoder_floor",
|
|
3384
|
+
subgraph: subgraphName,
|
|
3385
|
+
rawTip,
|
|
3386
|
+
floor: bound.floor,
|
|
3387
|
+
tip: bound.tip
|
|
3388
|
+
});
|
|
3389
|
+
}
|
|
3390
|
+
chainTip = bound.tip;
|
|
3391
|
+
}
|
|
3306
3392
|
if (chainTip <= 0 || lastProcessedBlock >= chainTip)
|
|
3307
3393
|
return 0;
|
|
3308
3394
|
const subgraphStart = Number(subgraphRow.start_block) || 1;
|
|
@@ -3765,7 +3851,29 @@ async function processBlockRange(def, opts) {
|
|
|
3765
3851
|
async function resolveBlockRange(source, def, opts) {
|
|
3766
3852
|
const definitionStart = def.startBlock ?? 1;
|
|
3767
3853
|
const fromBlock = opts?.startBlockFloor != null ? Math.max(definitionStart, opts.startBlockFloor) : definitionStart;
|
|
3768
|
-
|
|
3854
|
+
const rawTip = await source.getTip();
|
|
3855
|
+
if (!usesDecodedIndexPlane(def)) {
|
|
3856
|
+
return { fromBlock, toBlock: rawTip };
|
|
3857
|
+
}
|
|
3858
|
+
const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(def));
|
|
3859
|
+
if (!bound.ok) {
|
|
3860
|
+
logger10.warn("Reindex stalled: missing decoder checkpoint", {
|
|
3861
|
+
event: "subgraph_reindex_decoder_stall",
|
|
3862
|
+
subgraph: def.name,
|
|
3863
|
+
missing: bound.missing
|
|
3864
|
+
});
|
|
3865
|
+
throw new Error(`Reindex stalled: missing decoder checkpoint (${bound.missing.join(", ")})`);
|
|
3866
|
+
}
|
|
3867
|
+
if (bound.floor !== null && bound.floor < rawTip) {
|
|
3868
|
+
logger10.debug("Reindex tip bounded by decoder progress", {
|
|
3869
|
+
event: "subgraph_reindex_decoder_floor",
|
|
3870
|
+
subgraph: def.name,
|
|
3871
|
+
rawTip,
|
|
3872
|
+
floor: bound.floor,
|
|
3873
|
+
tip: bound.tip
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
return { fromBlock, toBlock: bound.tip };
|
|
3769
3877
|
}
|
|
3770
3878
|
async function clearReindexMetadata(db, subgraphName) {
|
|
3771
3879
|
await db.updateTable("subgraphs").set({ reindex_from_block: null, reindex_to_block: null }).where("name", "=", subgraphName).execute();
|
|
@@ -4581,5 +4689,5 @@ var shutdown = async () => {
|
|
|
4581
4689
|
process.on("SIGINT", shutdown);
|
|
4582
4690
|
process.on("SIGTERM", shutdown);
|
|
4583
4691
|
|
|
4584
|
-
//# debugId=
|
|
4692
|
+
//# debugId=91A178D7CD34941D64756E2164756E21
|
|
4585
4693
|
//# sourceMappingURL=service.js.map
|