@secondlayer/subgraphs 3.9.0 → 3.11.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.
- package/README.md +12 -2
- package/dist/src/index.d.ts +22 -1
- package/dist/src/index.js +100 -15
- package/dist/src/index.js.map +5 -5
- package/dist/src/runtime/block-processor.js +43 -3
- package/dist/src/runtime/block-processor.js.map +3 -3
- package/dist/src/runtime/catchup.js +43 -3
- package/dist/src/runtime/catchup.js.map +3 -3
- package/dist/src/runtime/processor.js +88 -3
- package/dist/src/runtime/processor.js.map +5 -5
- package/dist/src/runtime/reindex.js +67 -3
- package/dist/src/runtime/reindex.js.map +4 -4
- package/dist/src/runtime/reorg.js +43 -3
- package/dist/src/runtime/reorg.js.map +3 -3
- package/dist/src/runtime/replay.js +43 -3
- package/dist/src/runtime/replay.js.map +3 -3
- package/dist/src/schema/index.js +32 -12
- package/dist/src/schema/index.js.map +3 -3
- package/dist/src/service.js +88 -3
- package/dist/src/service.js.map +5 -5
- package/package.json +2 -2
package/dist/src/service.js
CHANGED
|
@@ -1119,6 +1119,28 @@ function reconstructEvent(e) {
|
|
|
1119
1119
|
}
|
|
1120
1120
|
|
|
1121
1121
|
// src/runtime/block-source.ts
|
|
1122
|
+
function canSparseScan(subgraph) {
|
|
1123
|
+
if (Array.isArray(subgraph.sources))
|
|
1124
|
+
return false;
|
|
1125
|
+
const filters = sourceFilters(subgraph);
|
|
1126
|
+
if (filters.length === 0)
|
|
1127
|
+
return false;
|
|
1128
|
+
return filters.every((f) => Boolean(EVENT_FILTER_TO_INDEX_TYPE[f.type]));
|
|
1129
|
+
}
|
|
1130
|
+
function sparseProbeTargets(subgraph) {
|
|
1131
|
+
const targets = new Map;
|
|
1132
|
+
for (const f of sourceFilters(subgraph)) {
|
|
1133
|
+
const eventType = EVENT_FILTER_TO_INDEX_TYPE[f.type];
|
|
1134
|
+
if (!eventType)
|
|
1135
|
+
continue;
|
|
1136
|
+
const scoped = f;
|
|
1137
|
+
const contractId = scoped.contractId ?? scoped.assetIdentifier?.split("::")[0];
|
|
1138
|
+
const key = `${eventType}|${contractId ?? ""}`;
|
|
1139
|
+
targets.set(key, { eventType, ...contractId ? { contractId } : {} });
|
|
1140
|
+
}
|
|
1141
|
+
return [...targets.values()];
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1122
1144
|
class PostgresBlockSource {
|
|
1123
1145
|
async getTip() {
|
|
1124
1146
|
const progress = await getSourceDb().selectFrom("index_progress").selectAll().where("network", "=", process.env.NETWORK ?? "mainnet").executeTakeFirst();
|
|
@@ -1181,9 +1203,18 @@ function isStreamsIndexEligible(subgraph) {
|
|
|
1181
1203
|
class PublicApiBlockSource {
|
|
1182
1204
|
http;
|
|
1183
1205
|
eventTypes;
|
|
1184
|
-
|
|
1206
|
+
probeTargets;
|
|
1207
|
+
constructor(http, eventTypes, probeTargets) {
|
|
1185
1208
|
this.http = http;
|
|
1186
1209
|
this.eventTypes = eventTypes;
|
|
1210
|
+
this.probeTargets = probeTargets;
|
|
1211
|
+
}
|
|
1212
|
+
async nextDataHeight(afterHeight, untilHeight) {
|
|
1213
|
+
if (!this.probeTargets?.length)
|
|
1214
|
+
return afterHeight + 1;
|
|
1215
|
+
const hits = await Promise.all(this.probeTargets.map((t) => this.http.firstEventHeight(t.eventType, afterHeight + 1, untilHeight, t.contractId)));
|
|
1216
|
+
const found = hits.filter((h) => h !== null);
|
|
1217
|
+
return found.length ? Math.min(...found) : null;
|
|
1187
1218
|
}
|
|
1188
1219
|
getTip() {
|
|
1189
1220
|
return this.http.getIndexTip();
|
|
@@ -1247,6 +1278,15 @@ class FallbackBlockSource {
|
|
|
1247
1278
|
return this.fallback.loadBlockRange(fromHeight, toHeight);
|
|
1248
1279
|
}
|
|
1249
1280
|
}
|
|
1281
|
+
async nextDataHeight(afterHeight, untilHeight) {
|
|
1282
|
+
if (!this.primary.nextDataHeight)
|
|
1283
|
+
return afterHeight + 1;
|
|
1284
|
+
try {
|
|
1285
|
+
return await this.primary.nextDataHeight(afterHeight, untilHeight);
|
|
1286
|
+
} catch {
|
|
1287
|
+
return afterHeight + 1;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1250
1290
|
}
|
|
1251
1291
|
var postgresBlockSource = new PostgresBlockSource;
|
|
1252
1292
|
function buildHttpClient() {
|
|
@@ -1259,7 +1299,7 @@ function buildHttpClient() {
|
|
|
1259
1299
|
}
|
|
1260
1300
|
function resolveBlockSource(subgraph) {
|
|
1261
1301
|
if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph && isStreamsIndexEligible(subgraph)) {
|
|
1262
|
-
return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph)), postgresBlockSource);
|
|
1302
|
+
return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph), canSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined), postgresBlockSource);
|
|
1263
1303
|
}
|
|
1264
1304
|
if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph) {
|
|
1265
1305
|
logger3.debug("Subgraph not streams-index eligible, using DB tap", {
|
|
@@ -1929,6 +1969,7 @@ async function processBlockRange(def, opts) {
|
|
|
1929
1969
|
let batchSize = batchConfig.defaultBatchSize;
|
|
1930
1970
|
let currentHeight = fromBlock;
|
|
1931
1971
|
let aborted = false;
|
|
1972
|
+
const sparse = Boolean(source.nextDataHeight && canSparseScan(def));
|
|
1932
1973
|
const flushHealth = async () => {
|
|
1933
1974
|
if (pendingEventsProcessed === 0 && pendingErrors === 0)
|
|
1934
1975
|
return;
|
|
@@ -1959,6 +2000,7 @@ async function processBlockRange(def, opts) {
|
|
|
1959
2000
|
nextBatchPromise = source.loadBlockRange(nextStart, nextBatchEnd);
|
|
1960
2001
|
}
|
|
1961
2002
|
const batchFailedBlocks = [];
|
|
2003
|
+
let batchMatched = 0;
|
|
1962
2004
|
for (let height = currentHeight;height <= batchEnd; height++) {
|
|
1963
2005
|
const blockData = batch.get(height);
|
|
1964
2006
|
if (!blockData) {
|
|
@@ -1988,6 +2030,7 @@ async function processBlockRange(def, opts) {
|
|
|
1988
2030
|
continue;
|
|
1989
2031
|
}
|
|
1990
2032
|
blocksProcessed++;
|
|
2033
|
+
batchMatched += result.matched;
|
|
1991
2034
|
totalEventsProcessed += result.processed;
|
|
1992
2035
|
totalErrors += result.errors;
|
|
1993
2036
|
pendingEventsProcessed += result.processed;
|
|
@@ -2033,6 +2076,27 @@ async function processBlockRange(def, opts) {
|
|
|
2033
2076
|
});
|
|
2034
2077
|
});
|
|
2035
2078
|
}
|
|
2079
|
+
if (sparse && batchMatched === 0 && batchEnd < toBlock && source.nextDataHeight) {
|
|
2080
|
+
const next = await source.nextDataHeight(batchEnd, toBlock);
|
|
2081
|
+
const jumpTo = next === null ? toBlock + 1 : Math.max(next, batchEnd + 1);
|
|
2082
|
+
if (jumpTo > batchEnd + 1) {
|
|
2083
|
+
const skipped = Math.min(jumpTo, toBlock + 1) - (batchEnd + 1);
|
|
2084
|
+
blocksProcessed += skipped;
|
|
2085
|
+
await updateSubgraphStatus2(targetDb, subgraphName, status, jumpTo - 1);
|
|
2086
|
+
logger6.info("Sparse skip", {
|
|
2087
|
+
subgraph: subgraphName,
|
|
2088
|
+
from: batchEnd + 1,
|
|
2089
|
+
to: jumpTo - 1,
|
|
2090
|
+
skipped
|
|
2091
|
+
});
|
|
2092
|
+
currentHeight = jumpTo;
|
|
2093
|
+
if (currentHeight <= toBlock) {
|
|
2094
|
+
nextBatchEnd = Math.min(currentHeight + batchSize - 1, toBlock);
|
|
2095
|
+
nextBatchPromise = source.loadBlockRange(currentHeight, nextBatchEnd);
|
|
2096
|
+
}
|
|
2097
|
+
continue;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2036
2100
|
const avg = avgEventsPerBlock(batch);
|
|
2037
2101
|
if (avg > 50)
|
|
2038
2102
|
batchSize = Math.max(Math.round(batchSize * 0.5), batchConfig.minBatchSize);
|
|
@@ -2795,6 +2859,27 @@ async function startSubgraphOperationRunner(opts) {
|
|
|
2795
2859
|
let running = true;
|
|
2796
2860
|
let draining = false;
|
|
2797
2861
|
logger10.info("Starting subgraph operation runner", { concurrency, lockedBy });
|
|
2862
|
+
try {
|
|
2863
|
+
const stranded = await db.selectFrom("subgraphs").select(["id", "name", "account_id"]).where("status", "=", "reindexing").where("reindex_from_block", "is not", null).where("reindex_to_block", "is not", null).where(({ not, exists, selectFrom }) => not(exists(selectFrom("subgraph_operations").select("id").whereRef("subgraph_id", "=", "subgraphs.id").where("status", "in", ["queued", "running"])))).execute();
|
|
2864
|
+
for (const row of stranded) {
|
|
2865
|
+
try {
|
|
2866
|
+
await createSubgraphOperation(db, {
|
|
2867
|
+
subgraphId: row.id,
|
|
2868
|
+
subgraphName: row.name,
|
|
2869
|
+
accountId: row.account_id,
|
|
2870
|
+
kind: "reindex"
|
|
2871
|
+
});
|
|
2872
|
+
logger10.info("Re-enqueued stranded reindex", { subgraph: row.name });
|
|
2873
|
+
} catch (err) {
|
|
2874
|
+
if (!isActiveSubgraphOperationConflict(err))
|
|
2875
|
+
throw err;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
} catch (err) {
|
|
2879
|
+
logger10.warn("Stranded-reindex sweep failed", {
|
|
2880
|
+
error: getErrorMessage5(err)
|
|
2881
|
+
});
|
|
2882
|
+
}
|
|
2798
2883
|
const startOperation = (operation) => {
|
|
2799
2884
|
const controller = new AbortController;
|
|
2800
2885
|
active.set(operation.id, controller);
|
|
@@ -2996,5 +3081,5 @@ var shutdown = async () => {
|
|
|
2996
3081
|
process.on("SIGINT", shutdown);
|
|
2997
3082
|
process.on("SIGTERM", shutdown);
|
|
2998
3083
|
|
|
2999
|
-
//# debugId=
|
|
3084
|
+
//# debugId=899FAA83415B11C964756E2164756E21
|
|
3000
3085
|
//# sourceMappingURL=service.js.map
|