@secondlayer/subgraphs 4.1.5 → 4.2.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 +87 -29
- package/dist/src/index.js +376 -128
- package/dist/src/index.js.map +9 -7
- package/dist/src/runtime/block-processor.d.ts +72 -23
- package/dist/src/runtime/block-processor.js +186 -53
- package/dist/src/runtime/block-processor.js.map +7 -5
- package/dist/src/runtime/catchup.d.ts +72 -23
- package/dist/src/runtime/catchup.js +201 -68
- package/dist/src/runtime/catchup.js.map +7 -5
- package/dist/src/runtime/emitter.js +24 -1
- package/dist/src/runtime/emitter.js.map +5 -4
- package/dist/src/runtime/processor.js +328 -166
- package/dist/src/runtime/processor.js.map +10 -7
- package/dist/src/runtime/reindex.d.ts +72 -23
- package/dist/src/runtime/reindex.js +238 -105
- package/dist/src/runtime/reindex.js.map +7 -5
- package/dist/src/runtime/reorg.d.ts +72 -23
- package/dist/src/runtime/reorg.js +215 -81
- package/dist/src/runtime/reorg.js.map +8 -6
- package/dist/src/runtime/runner.d.ts +72 -23
- package/dist/src/runtime/runner.js +156 -23
- package/dist/src/runtime/runner.js.map +8 -6
- package/dist/src/runtime/source-matcher.d.ts +72 -23
- package/dist/src/schema/index.d.ts +72 -23
- package/dist/src/schema/index.js +115 -1
- package/dist/src/schema/index.js.map +3 -3
- package/dist/src/service.js +348 -171
- package/dist/src/service.js.map +11 -8
- package/dist/src/testing/index.d.ts +195 -24
- package/dist/src/testing/index.js +448 -25
- package/dist/src/testing/index.js.map +9 -6
- package/dist/src/triggers/index.d.ts +83 -24
- package/dist/src/triggers/index.js +5 -2
- package/dist/src/triggers/index.js.map +3 -3
- package/dist/src/types.d.ts +73 -24
- package/dist/src/validate.d.ts +72 -23
- package/dist/src/validate.js +115 -1
- package/dist/src/validate.js.map +3 -3
- package/package.json +2 -2
|
@@ -1212,7 +1212,7 @@ function matchSources(sources, transactions, events, traitContracts = new Map, f
|
|
|
1212
1212
|
|
|
1213
1213
|
// src/runtime/runner.ts
|
|
1214
1214
|
import { getErrorMessage } from "@secondlayer/shared";
|
|
1215
|
-
import { logger as
|
|
1215
|
+
import { logger as logger4 } from "@secondlayer/shared/logger";
|
|
1216
1216
|
import {
|
|
1217
1217
|
clarityValueToJS,
|
|
1218
1218
|
deserializeCV as deserializeCV4,
|
|
@@ -1226,6 +1226,19 @@ import {
|
|
|
1226
1226
|
function camelizeDataKey(str) {
|
|
1227
1227
|
return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
1228
1228
|
}
|
|
1229
|
+
function camelizeKeys(obj) {
|
|
1230
|
+
if (obj === null || obj === undefined)
|
|
1231
|
+
return obj;
|
|
1232
|
+
if (typeof obj !== "object")
|
|
1233
|
+
return obj;
|
|
1234
|
+
if (Array.isArray(obj))
|
|
1235
|
+
return obj.map(camelizeKeys);
|
|
1236
|
+
const result = {};
|
|
1237
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
1238
|
+
result[camelizeDataKey(k)] = camelizeKeys(v);
|
|
1239
|
+
}
|
|
1240
|
+
return result;
|
|
1241
|
+
}
|
|
1229
1242
|
function cvToTree(cv) {
|
|
1230
1243
|
switch (cv.type) {
|
|
1231
1244
|
case "uint":
|
|
@@ -1550,6 +1563,58 @@ function inferPrintTopics(samples) {
|
|
|
1550
1563
|
return out.sort((a, b) => b.count - a.count);
|
|
1551
1564
|
}
|
|
1552
1565
|
|
|
1566
|
+
// src/runtime/materialize.ts
|
|
1567
|
+
function resolveColumn(col, event, tx, block) {
|
|
1568
|
+
if ("fromTx" in col) {
|
|
1569
|
+
return { ok: true, value: tx[col.fromTx] };
|
|
1570
|
+
}
|
|
1571
|
+
if ("fromBlock" in col) {
|
|
1572
|
+
return { ok: true, value: block[col.fromBlock] };
|
|
1573
|
+
}
|
|
1574
|
+
const data = event.data;
|
|
1575
|
+
const dataObj = data !== null && typeof data === "object" && !Array.isArray(data) ? data : undefined;
|
|
1576
|
+
if (dataObj && Object.prototype.hasOwnProperty.call(dataObj, col.from)) {
|
|
1577
|
+
return { ok: true, value: dataObj[col.from] };
|
|
1578
|
+
}
|
|
1579
|
+
if (col.from === "topic" && "topic" in event) {
|
|
1580
|
+
return { ok: true, value: event.topic };
|
|
1581
|
+
}
|
|
1582
|
+
if (Object.prototype.hasOwnProperty.call(event, col.from)) {
|
|
1583
|
+
return { ok: true, value: event[col.from] };
|
|
1584
|
+
}
|
|
1585
|
+
return { ok: false, missing: col.from };
|
|
1586
|
+
}
|
|
1587
|
+
function buildMaterializeRow(spec, event, ctx, tableColumns) {
|
|
1588
|
+
const row = {};
|
|
1589
|
+
for (const [colName, mapping] of Object.entries(spec.columns)) {
|
|
1590
|
+
const resolved = resolveColumn(mapping, event, ctx.tx, ctx.block);
|
|
1591
|
+
if (!resolved.ok) {
|
|
1592
|
+
const colDef = tableColumns[colName];
|
|
1593
|
+
if (colDef?.nullable) {
|
|
1594
|
+
row[colName] = null;
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
return {
|
|
1598
|
+
ok: false,
|
|
1599
|
+
reason: `required materialize field "${resolved.missing}" missing for column "${colName}"`
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
row[colName] = resolved.value ?? null;
|
|
1603
|
+
}
|
|
1604
|
+
return { ok: true, row };
|
|
1605
|
+
}
|
|
1606
|
+
function applyMaterializeInsert(spec, event, ctx, schema) {
|
|
1607
|
+
const table = schema[spec.table];
|
|
1608
|
+
if (!table) {
|
|
1609
|
+
return { ok: false, reason: `materialize table "${spec.table}" missing` };
|
|
1610
|
+
}
|
|
1611
|
+
const built = buildMaterializeRow(spec, event, ctx, table.columns);
|
|
1612
|
+
if (!built.ok)
|
|
1613
|
+
return built;
|
|
1614
|
+
ctx.insert(spec.table, built.row);
|
|
1615
|
+
return { ok: true };
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1553
1618
|
// src/runtime/print-validate.ts
|
|
1554
1619
|
var COLUMN_TYPES = new Set([
|
|
1555
1620
|
"text",
|
|
@@ -1629,21 +1694,62 @@ function validatePrintPayload(prints, topic, data) {
|
|
|
1629
1694
|
return matchesTopic(declared, data);
|
|
1630
1695
|
}
|
|
1631
1696
|
|
|
1632
|
-
// src/runtime/
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1697
|
+
// src/runtime/violations.ts
|
|
1698
|
+
import { getTargetDb } from "@secondlayer/shared/db";
|
|
1699
|
+
import { logger as logger3 } from "@secondlayer/shared/logger";
|
|
1700
|
+
import { sql as sql2 } from "kysely";
|
|
1701
|
+
var VIOLATIONS_CAP_PER_SUBGRAPH = 100;
|
|
1702
|
+
function jsonSafe2(value) {
|
|
1703
|
+
if (typeof value === "bigint")
|
|
1704
|
+
return value.toString();
|
|
1705
|
+
if (value === null || value === undefined)
|
|
1706
|
+
return value;
|
|
1707
|
+
if (Array.isArray(value))
|
|
1708
|
+
return value.map(jsonSafe2);
|
|
1709
|
+
if (typeof value === "object") {
|
|
1710
|
+
const out = {};
|
|
1711
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1712
|
+
out[k] = jsonSafe2(v);
|
|
1713
|
+
}
|
|
1714
|
+
return out;
|
|
1644
1715
|
}
|
|
1645
|
-
return
|
|
1716
|
+
return value;
|
|
1646
1717
|
}
|
|
1718
|
+
async function defaultRecordPrintViolation(input) {
|
|
1719
|
+
try {
|
|
1720
|
+
const db = getTargetDb();
|
|
1721
|
+
const sample = jsonSafe2(input.samplePayload);
|
|
1722
|
+
await db.insertInto("subgraph_violations").values({
|
|
1723
|
+
subgraph_name: input.subgraphName,
|
|
1724
|
+
source_name: input.sourceName,
|
|
1725
|
+
block_height: input.blockHeight,
|
|
1726
|
+
tx_id: input.txId,
|
|
1727
|
+
reason: input.reason,
|
|
1728
|
+
sample_payload: sample
|
|
1729
|
+
}).execute();
|
|
1730
|
+
await sql2`
|
|
1731
|
+
DELETE FROM subgraph_violations
|
|
1732
|
+
WHERE id IN (
|
|
1733
|
+
SELECT id FROM subgraph_violations
|
|
1734
|
+
WHERE subgraph_name = ${input.subgraphName}
|
|
1735
|
+
ORDER BY seen_at DESC
|
|
1736
|
+
OFFSET ${VIOLATIONS_CAP_PER_SUBGRAPH}
|
|
1737
|
+
)
|
|
1738
|
+
`.execute(db);
|
|
1739
|
+
} catch (err) {
|
|
1740
|
+
logger3.warn("Failed to record print violation", {
|
|
1741
|
+
subgraph: input.subgraphName,
|
|
1742
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
var recorder = defaultRecordPrintViolation;
|
|
1747
|
+
async function recordPrintViolation(input) {
|
|
1748
|
+
await recorder(input);
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
// src/runtime/runner.ts
|
|
1752
|
+
var DEFAULT_ERROR_THRESHOLD = 50;
|
|
1647
1753
|
function decodeFunctionArgs2(args) {
|
|
1648
1754
|
let parsed = args;
|
|
1649
1755
|
if (typeof parsed === "string") {
|
|
@@ -1891,16 +1997,18 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
1891
1997
|
units.sort((a, b) => (a.tx.tx_index ?? 0) - (b.tx.tx_index ?? 0) || (a.event?.event_index ?? -1) - (b.event?.event_index ?? -1));
|
|
1892
1998
|
for (const { tx, event, sourceName } of units) {
|
|
1893
1999
|
if (errors >= threshold) {
|
|
1894
|
-
|
|
2000
|
+
logger4.error("Subgraph error threshold reached, skipping remaining events", {
|
|
1895
2001
|
subgraph: subgraph.name,
|
|
1896
2002
|
errors,
|
|
1897
2003
|
threshold
|
|
1898
2004
|
});
|
|
1899
2005
|
return { processed, errors, ...skipped > 0 ? { skipped } : {} };
|
|
1900
2006
|
}
|
|
2007
|
+
const filter = filterLookup.get(sourceName);
|
|
2008
|
+
const materialize = filter && "materialize" in filter && filter.materialize !== undefined ? filter.materialize : undefined;
|
|
1901
2009
|
const handler = subgraph.handlers[sourceName] ?? subgraph.handlers["*"] ?? null;
|
|
1902
|
-
if (!handler) {
|
|
1903
|
-
|
|
2010
|
+
if (!handler && !materialize) {
|
|
2011
|
+
logger4.warn("No handler found for source", {
|
|
1904
2012
|
subgraph: subgraph.name,
|
|
1905
2013
|
sourceName,
|
|
1906
2014
|
txId: tx.tx_id
|
|
@@ -1915,7 +2023,6 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
1915
2023
|
contractId: tx.contract_id ?? null,
|
|
1916
2024
|
functionName: tx.function_name ?? null
|
|
1917
2025
|
});
|
|
1918
|
-
const filter = filterLookup.get(sourceName);
|
|
1919
2026
|
const checkpoint = ctx.opsCheckpoint();
|
|
1920
2027
|
try {
|
|
1921
2028
|
let payload;
|
|
@@ -1957,22 +2064,48 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
1957
2064
|
const verdict = validatePrintPayload(filter.prints, printPayload.topic ?? "", printPayload.data ?? {});
|
|
1958
2065
|
if (!verdict.ok) {
|
|
1959
2066
|
skipped++;
|
|
1960
|
-
|
|
2067
|
+
logger4.warn("Print payload does not match declared prints schema", {
|
|
1961
2068
|
subgraph: subgraph.name,
|
|
1962
2069
|
sourceName,
|
|
1963
2070
|
topic: printPayload.topic,
|
|
1964
2071
|
txId: tx.tx_id,
|
|
1965
2072
|
reason: verdict.reason
|
|
1966
2073
|
});
|
|
2074
|
+
recordPrintViolation({
|
|
2075
|
+
subgraphName: subgraph.name,
|
|
2076
|
+
sourceName,
|
|
2077
|
+
blockHeight: ctx.block.height,
|
|
2078
|
+
txId: tx.tx_id,
|
|
2079
|
+
reason: verdict.reason,
|
|
2080
|
+
samplePayload: {
|
|
2081
|
+
topic: printPayload.topic ?? "",
|
|
2082
|
+
data: printPayload.data ?? {}
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
1967
2085
|
continue;
|
|
1968
2086
|
}
|
|
1969
2087
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
2088
|
+
if (materialize) {
|
|
2089
|
+
const result = applyMaterializeInsert(materialize, payload, ctx, subgraph.schema);
|
|
2090
|
+
if (!result.ok) {
|
|
2091
|
+
skipped++;
|
|
2092
|
+
logger4.warn("Materialize skipped: required field missing", {
|
|
2093
|
+
subgraph: subgraph.name,
|
|
2094
|
+
sourceName,
|
|
2095
|
+
txId: tx.tx_id,
|
|
2096
|
+
reason: result.reason
|
|
2097
|
+
});
|
|
2098
|
+
continue;
|
|
2099
|
+
}
|
|
2100
|
+
processed++;
|
|
2101
|
+
} else if (handler) {
|
|
2102
|
+
await handler(payload, ctx);
|
|
2103
|
+
processed++;
|
|
2104
|
+
}
|
|
1972
2105
|
} catch (err) {
|
|
1973
2106
|
ctx.rollbackTo(checkpoint);
|
|
1974
2107
|
errors++;
|
|
1975
|
-
|
|
2108
|
+
logger4.error("Subgraph handler error", {
|
|
1976
2109
|
subgraph: subgraph.name,
|
|
1977
2110
|
sourceName,
|
|
1978
2111
|
txId: tx.tx_id,
|
|
@@ -1985,7 +2118,7 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
1985
2118
|
}
|
|
1986
2119
|
|
|
1987
2120
|
// src/runtime/block-processor.ts
|
|
1988
|
-
import { getTargetDb } from "@secondlayer/shared/db";
|
|
2121
|
+
import { getTargetDb as getTargetDb2 } from "@secondlayer/shared/db";
|
|
1989
2122
|
import { resolveTraitContractIds } from "@secondlayer/shared/db/queries/contracts";
|
|
1990
2123
|
import { recordGapBatch } from "@secondlayer/shared/db/queries/subgraph-gaps";
|
|
1991
2124
|
import { advanceOperationCursor } from "@secondlayer/shared/db/queries/subgraph-operations";
|
|
@@ -1996,15 +2129,15 @@ import {
|
|
|
1996
2129
|
rewindLiveProgress,
|
|
1997
2130
|
updateSubgraphStatus
|
|
1998
2131
|
} from "@secondlayer/shared/db/queries/subgraphs";
|
|
1999
|
-
import { logger as
|
|
2000
|
-
import { sql as
|
|
2132
|
+
import { logger as logger8 } from "@secondlayer/shared/logger";
|
|
2133
|
+
import { sql as sql4 } from "kysely";
|
|
2001
2134
|
|
|
2002
2135
|
// src/runtime/block-source.ts
|
|
2003
2136
|
import { getSourceDb as getSourceDb2 } from "@secondlayer/shared/db";
|
|
2004
2137
|
import {
|
|
2005
2138
|
createInternalIndexHttpClient
|
|
2006
2139
|
} from "@secondlayer/shared/index-http";
|
|
2007
|
-
import { logger as
|
|
2140
|
+
import { logger as logger5 } from "@secondlayer/shared/logger";
|
|
2008
2141
|
|
|
2009
2142
|
// src/runtime/batch-loader.ts
|
|
2010
2143
|
async function loadBlockRange(db, fromHeight, toHeight) {
|
|
@@ -2491,7 +2624,7 @@ class FallbackBlockSource {
|
|
|
2491
2624
|
try {
|
|
2492
2625
|
return await this.primary.getTip();
|
|
2493
2626
|
} catch (err) {
|
|
2494
|
-
|
|
2627
|
+
logger5.warn("block source primary getTip failed — using DB tap", {
|
|
2495
2628
|
error: err instanceof Error ? err.message : String(err)
|
|
2496
2629
|
});
|
|
2497
2630
|
return this.fallback.getTip();
|
|
@@ -2501,7 +2634,7 @@ class FallbackBlockSource {
|
|
|
2501
2634
|
try {
|
|
2502
2635
|
return await this.primary.loadBlockRange(fromHeight, toHeight);
|
|
2503
2636
|
} catch (err) {
|
|
2504
|
-
|
|
2637
|
+
logger5.warn("block source primary loadBlockRange failed — using DB tap", {
|
|
2505
2638
|
from: fromHeight,
|
|
2506
2639
|
to: toHeight,
|
|
2507
2640
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -2538,7 +2671,7 @@ function resolveBlockSource(subgraph) {
|
|
|
2538
2671
|
return new FallbackBlockSource(new PublicApiBlockSource(buildHttpClient(), referencedIndexEventTypes(subgraph), canSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined, needsTransactionData(subgraph)), postgresBlockSource);
|
|
2539
2672
|
}
|
|
2540
2673
|
if (process.env.SUBGRAPH_SOURCE === "streams-index" && subgraph) {
|
|
2541
|
-
|
|
2674
|
+
logger5.debug("Subgraph not streams-index eligible, using DB tap", {
|
|
2542
2675
|
subgraph: subgraph.name
|
|
2543
2676
|
});
|
|
2544
2677
|
}
|
|
@@ -2547,7 +2680,7 @@ function resolveBlockSource(subgraph) {
|
|
|
2547
2680
|
|
|
2548
2681
|
// src/runtime/outbox-emit.ts
|
|
2549
2682
|
import { createHash as createHash2 } from "node:crypto";
|
|
2550
|
-
import { logger as
|
|
2683
|
+
import { logger as logger6 } from "@secondlayer/shared/logger";
|
|
2551
2684
|
var loggedKillSwitch = false;
|
|
2552
2685
|
var OP_VERB = {
|
|
2553
2686
|
insert: "created",
|
|
@@ -2571,7 +2704,7 @@ function stableStringify(obj) {
|
|
|
2571
2704
|
async function emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, blockHeight) {
|
|
2572
2705
|
if (!isEmitOutboxEnabled()) {
|
|
2573
2706
|
if (!loggedKillSwitch) {
|
|
2574
|
-
|
|
2707
|
+
logger6.warn("SECONDLAYER_EMIT_OUTBOX=false — outbox emission bypassed");
|
|
2575
2708
|
loggedKillSwitch = true;
|
|
2576
2709
|
}
|
|
2577
2710
|
return 0;
|
|
@@ -2616,7 +2749,7 @@ function sandboxEnabled(subgraph) {
|
|
|
2616
2749
|
// src/runtime/sandbox/host.ts
|
|
2617
2750
|
import { tmpdir } from "node:os";
|
|
2618
2751
|
import { fileURLToPath } from "node:url";
|
|
2619
|
-
import { logger as
|
|
2752
|
+
import { logger as logger7 } from "@secondlayer/shared/logger";
|
|
2620
2753
|
|
|
2621
2754
|
// src/runtime/sandbox/bundle.ts
|
|
2622
2755
|
import esbuild from "esbuild";
|
|
@@ -2696,7 +2829,7 @@ function spawnSandboxProcess() {
|
|
|
2696
2829
|
break;
|
|
2697
2830
|
const text = decoder.decode(value, { stream: true });
|
|
2698
2831
|
if (text.trim()) {
|
|
2699
|
-
|
|
2832
|
+
logger7.warn("Sandbox subprocess stderr", { stderr: text.trim() });
|
|
2700
2833
|
}
|
|
2701
2834
|
}
|
|
2702
2835
|
} catch {}
|
|
@@ -2754,7 +2887,7 @@ async function ensureSandboxProcess(subgraphName, version, handlerCode) {
|
|
|
2754
2887
|
try {
|
|
2755
2888
|
await initSandboxProcess(existing.proc, subgraphName, version, handlerCode);
|
|
2756
2889
|
existing.version = version;
|
|
2757
|
-
|
|
2890
|
+
logger7.info("Sandbox subprocess handler reloaded", {
|
|
2758
2891
|
subgraph: subgraphName,
|
|
2759
2892
|
version
|
|
2760
2893
|
});
|
|
@@ -2762,7 +2895,7 @@ async function ensureSandboxProcess(subgraphName, version, handlerCode) {
|
|
|
2762
2895
|
} catch (err) {
|
|
2763
2896
|
existing.proc.kill();
|
|
2764
2897
|
pool.delete(subgraphName);
|
|
2765
|
-
|
|
2898
|
+
logger7.warn("Sandbox subprocess re-init failed; respawning", {
|
|
2766
2899
|
subgraph: subgraphName,
|
|
2767
2900
|
error: err instanceof Error ? err.message : String(err)
|
|
2768
2901
|
});
|
|
@@ -2845,7 +2978,7 @@ async function runBlockThroughProcess(entry, subgraphName, hostCtx, block, match
|
|
|
2845
2978
|
return result;
|
|
2846
2979
|
} catch (err) {
|
|
2847
2980
|
evictSandboxWorker(subgraphName);
|
|
2848
|
-
|
|
2981
|
+
logger7.warn("Sandbox subprocess run failed; subprocess evicted", {
|
|
2849
2982
|
subgraph: subgraphName,
|
|
2850
2983
|
blockHeight: block.height,
|
|
2851
2984
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -2916,7 +3049,7 @@ async function answerRead(hostCtx, msg) {
|
|
|
2916
3049
|
|
|
2917
3050
|
// src/runtime/subscription-state.ts
|
|
2918
3051
|
import { listSubscriptions } from "@secondlayer/shared/db/queries/subscriptions";
|
|
2919
|
-
import { sql as
|
|
3052
|
+
import { sql as sql3 } from "kysely";
|
|
2920
3053
|
|
|
2921
3054
|
// src/runtime/emitter-matcher.ts
|
|
2922
3055
|
function isPrimitive(v) {
|
|
@@ -3080,7 +3213,7 @@ class SubscriptionMatcher {
|
|
|
3080
3213
|
// src/runtime/subscription-state.ts
|
|
3081
3214
|
var matcher = new SubscriptionMatcher;
|
|
3082
3215
|
async function refreshMatcher(db) {
|
|
3083
|
-
const rows = await
|
|
3216
|
+
const rows = await sql3`
|
|
3084
3217
|
SELECT * FROM subscriptions WHERE status = 'active'
|
|
3085
3218
|
`.execute(db);
|
|
3086
3219
|
matcher.setAll(rows.rows);
|
|
@@ -3102,7 +3235,7 @@ async function resolveRoute(subgraphName, targetDb) {
|
|
|
3102
3235
|
version: row?.version ?? ""
|
|
3103
3236
|
};
|
|
3104
3237
|
routeCache.set(subgraphName, route);
|
|
3105
|
-
|
|
3238
|
+
logger8.info("subgraph handler dispatch path resolved", {
|
|
3106
3239
|
subgraph: subgraphName,
|
|
3107
3240
|
path: sandboxEnabled({ sandbox_workers: route.sandboxWorkers }) ? "sandbox" : "in-process"
|
|
3108
3241
|
});
|
|
@@ -3126,8 +3259,8 @@ async function resolveFactoryContracts(subgraph, blockHeight, schemaName, db, tx
|
|
|
3126
3259
|
for (const [discoveringSource, factory] of factories) {
|
|
3127
3260
|
const known = new Set;
|
|
3128
3261
|
try {
|
|
3129
|
-
const rows = await
|
|
3130
|
-
SELECT address FROM ${
|
|
3262
|
+
const rows = await sql4`
|
|
3263
|
+
SELECT address FROM ${sql4.raw(`"${schemaName}"."_factory_addresses"`)}
|
|
3131
3264
|
WHERE source_name = ${discoveringSource} AND block_height <= ${blockHeight}
|
|
3132
3265
|
`.execute(db);
|
|
3133
3266
|
for (const row of rows.rows)
|
|
@@ -3155,8 +3288,8 @@ async function persistFactoryDiscoveries(schemaName, db, blockHeight, discovered
|
|
|
3155
3288
|
if (discovered.length === 0)
|
|
3156
3289
|
return;
|
|
3157
3290
|
for (const { sourceName, address } of discovered) {
|
|
3158
|
-
await
|
|
3159
|
-
INSERT INTO ${
|
|
3291
|
+
await sql4`
|
|
3292
|
+
INSERT INTO ${sql4.raw(`"${schemaName}"."_factory_addresses"`)}
|
|
3160
3293
|
(source_name, address, block_height)
|
|
3161
3294
|
VALUES (${sourceName}, ${address}, ${blockHeight})
|
|
3162
3295
|
ON CONFLICT (source_name, address) DO NOTHING
|
|
@@ -3216,7 +3349,7 @@ async function processBlockWithRetry(subgraph, subgraphName, blockHeight, opts,
|
|
|
3216
3349
|
const delay = retryDelaysMs[attempt];
|
|
3217
3350
|
if (delay === undefined)
|
|
3218
3351
|
break;
|
|
3219
|
-
|
|
3352
|
+
logger8.warn("Block processing failed, retrying", {
|
|
3220
3353
|
subgraph: subgraphName,
|
|
3221
3354
|
blockHeight,
|
|
3222
3355
|
attempt: attempt + 1,
|
|
@@ -3229,7 +3362,7 @@ async function processBlockWithRetry(subgraph, subgraphName, blockHeight, opts,
|
|
|
3229
3362
|
throw lastError;
|
|
3230
3363
|
}
|
|
3231
3364
|
async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
3232
|
-
const targetDb =
|
|
3365
|
+
const targetDb = getTargetDb2();
|
|
3233
3366
|
const blockStart = performance.now();
|
|
3234
3367
|
const result = {
|
|
3235
3368
|
blockHeight,
|
|
@@ -3248,7 +3381,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
3248
3381
|
} else {
|
|
3249
3382
|
const data = (await resolveBlockSource(subgraph).loadBlockRange(blockHeight, blockHeight)).get(blockHeight);
|
|
3250
3383
|
if (!data) {
|
|
3251
|
-
|
|
3384
|
+
logger8.debug("Block not found or non-canonical for subgraph processing", {
|
|
3252
3385
|
subgraph: subgraphName,
|
|
3253
3386
|
blockHeight
|
|
3254
3387
|
});
|
|
@@ -3314,7 +3447,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
3314
3447
|
{ start: blockHeight, end: blockHeight, reason: "processing_error" }
|
|
3315
3448
|
]);
|
|
3316
3449
|
} else {
|
|
3317
|
-
|
|
3450
|
+
logger8.warn("Block errors not recorded as a gap — no subgraphId", {
|
|
3318
3451
|
subgraph: subgraphName,
|
|
3319
3452
|
blockHeight,
|
|
3320
3453
|
errors: rr.errors
|
|
@@ -3387,7 +3520,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
3387
3520
|
});
|
|
3388
3521
|
} catch (err) {
|
|
3389
3522
|
if (err instanceof CursorRaceLostError || err instanceof LiveCursorRaceLostError) {
|
|
3390
|
-
|
|
3523
|
+
logger8.warn("cursor race lost — block already covered", {
|
|
3391
3524
|
subgraph: subgraphName,
|
|
3392
3525
|
blockHeight,
|
|
3393
3526
|
error: err.message
|
|
@@ -3412,10 +3545,10 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
3412
3545
|
try {
|
|
3413
3546
|
const tables = Object.keys(subgraph.schema);
|
|
3414
3547
|
for (const table of tables) {
|
|
3415
|
-
const { rows } = await
|
|
3548
|
+
const { rows } = await sql4.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(route.dataDb);
|
|
3416
3549
|
const count = Number(rows[0]?.count ?? 0);
|
|
3417
3550
|
if (count >= 1e7) {
|
|
3418
|
-
|
|
3551
|
+
logger8.warn("Subgraph table exceeds 10M rows (estimate)", {
|
|
3419
3552
|
subgraph: subgraphName,
|
|
3420
3553
|
table,
|
|
3421
3554
|
count
|
|
@@ -3423,13 +3556,13 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
3423
3556
|
}
|
|
3424
3557
|
}
|
|
3425
3558
|
} catch (err) {
|
|
3426
|
-
|
|
3559
|
+
logger8.debug("Row count sample failed", {
|
|
3427
3560
|
subgraph: subgraphName,
|
|
3428
3561
|
error: err instanceof Error ? err.message : String(err)
|
|
3429
3562
|
});
|
|
3430
3563
|
}
|
|
3431
3564
|
if (journalEnabled(opts)) {
|
|
3432
|
-
await
|
|
3565
|
+
await sql4.raw(`DELETE FROM "${schemaName}"."_journal" WHERE "block_height" < ${blockHeight - JOURNAL_RETENTION_BLOCKS}`).execute(route.dataDb).catch(() => {});
|
|
3433
3566
|
}
|
|
3434
3567
|
}
|
|
3435
3568
|
return result;
|
|
@@ -3499,9 +3632,9 @@ class StatsAccumulator {
|
|
|
3499
3632
|
}
|
|
3500
3633
|
|
|
3501
3634
|
// src/runtime/catchup.ts
|
|
3502
|
-
import { getTargetDb as
|
|
3635
|
+
import { getTargetDb as getTargetDb3, sql as sql5 } from "@secondlayer/shared/db";
|
|
3503
3636
|
import { getSubgraph } from "@secondlayer/shared/db/queries/subgraphs";
|
|
3504
|
-
import { logger as
|
|
3637
|
+
import { logger as logger9 } from "@secondlayer/shared/logger";
|
|
3505
3638
|
|
|
3506
3639
|
// src/runtime/catchup-leader.ts
|
|
3507
3640
|
import {
|
|
@@ -3631,8 +3764,8 @@ async function withSubgraphBlockLock(name, fn) {
|
|
|
3631
3764
|
}
|
|
3632
3765
|
}
|
|
3633
3766
|
async function withSubgraphBlockAdvisoryLock(name, fn) {
|
|
3634
|
-
return
|
|
3635
|
-
await
|
|
3767
|
+
return getTargetDb3().transaction().execute(async (lockTx) => {
|
|
3768
|
+
await sql5`SELECT pg_advisory_xact_lock(hashtext(${`subgraph-block:${name}`}))`.execute(lockTx);
|
|
3636
3769
|
return fn();
|
|
3637
3770
|
});
|
|
3638
3771
|
}
|
|
@@ -3693,7 +3826,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3693
3826
|
catchingUp.add(subgraphName);
|
|
3694
3827
|
try {
|
|
3695
3828
|
const source = resolveBlockSource(subgraph);
|
|
3696
|
-
const targetDb =
|
|
3829
|
+
const targetDb = getTargetDb3();
|
|
3697
3830
|
const subgraphRow = await getSubgraph(targetDb, subgraphName);
|
|
3698
3831
|
if (!subgraphRow)
|
|
3699
3832
|
return 0;
|
|
@@ -3705,7 +3838,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3705
3838
|
if (usesDecodedIndexPlane(subgraph)) {
|
|
3706
3839
|
const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(subgraph));
|
|
3707
3840
|
if (!bound.ok) {
|
|
3708
|
-
|
|
3841
|
+
logger9.warn("Subgraph catch-up stalled: missing decoder checkpoint", {
|
|
3709
3842
|
event: "subgraph_catchup_decoder_stall",
|
|
3710
3843
|
subgraph: subgraphName,
|
|
3711
3844
|
missing: bound.missing
|
|
@@ -3713,7 +3846,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3713
3846
|
return 0;
|
|
3714
3847
|
}
|
|
3715
3848
|
if (bound.floor !== null && bound.floor < rawTip) {
|
|
3716
|
-
|
|
3849
|
+
logger9.debug("Subgraph catch-up tip bounded by decoder progress", {
|
|
3717
3850
|
event: "subgraph_catchup_decoder_floor",
|
|
3718
3851
|
subgraph: subgraphName,
|
|
3719
3852
|
rawTip,
|
|
@@ -3728,7 +3861,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3728
3861
|
const subgraphStart = Number(subgraphRow.start_block) || 1;
|
|
3729
3862
|
const startBlock = Math.max(lastProcessedBlock + 1, subgraphStart);
|
|
3730
3863
|
const totalBlocks = chainTip - lastProcessedBlock;
|
|
3731
|
-
|
|
3864
|
+
logger9.info("Subgraph catch-up starting", {
|
|
3732
3865
|
subgraph: subgraphName,
|
|
3733
3866
|
from: startBlock,
|
|
3734
3867
|
to: chainTip,
|
|
@@ -3744,7 +3877,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3744
3877
|
let nextBatchPromise = batchConfig.prefetch ? source.loadBlockRange(currentHeight, prefetchedBatchEnd) : undefined;
|
|
3745
3878
|
while (currentHeight <= chainTip) {
|
|
3746
3879
|
if (!isCatchUpLeader()) {
|
|
3747
|
-
|
|
3880
|
+
logger9.info("Lost catch-up leadership, stopping catch-up", {
|
|
3748
3881
|
subgraph: subgraphName,
|
|
3749
3882
|
processed
|
|
3750
3883
|
});
|
|
@@ -3752,7 +3885,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3752
3885
|
}
|
|
3753
3886
|
const currentRow = await getSubgraph(targetDb, subgraphName);
|
|
3754
3887
|
if (!currentRow || currentRow.status !== "active") {
|
|
3755
|
-
|
|
3888
|
+
logger9.info("Subgraph status changed, stopping catch-up", {
|
|
3756
3889
|
subgraph: subgraphName,
|
|
3757
3890
|
status: currentRow?.status ?? "deleted"
|
|
3758
3891
|
});
|
|
@@ -3781,7 +3914,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3781
3914
|
blockData = (await source.loadBlockRange(height, height)).get(height);
|
|
3782
3915
|
}
|
|
3783
3916
|
if (!blockData) {
|
|
3784
|
-
|
|
3917
|
+
logger9.warn("Block missing during catch-up, deferring to next tick", {
|
|
3785
3918
|
subgraph: subgraphName,
|
|
3786
3919
|
blockHeight: height
|
|
3787
3920
|
});
|
|
@@ -3802,12 +3935,12 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3802
3935
|
});
|
|
3803
3936
|
} catch (err) {
|
|
3804
3937
|
if (err instanceof ReorgEpochChangedError) {
|
|
3805
|
-
|
|
3938
|
+
logger9.info("Reorg detected mid catch-up, aborting walk without writing further progress", { subgraph: subgraphName, blockHeight: height });
|
|
3806
3939
|
stopCatchup = true;
|
|
3807
3940
|
break;
|
|
3808
3941
|
}
|
|
3809
3942
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3810
|
-
|
|
3943
|
+
logger9.error("Block processing failed persistently during catch-up", {
|
|
3811
3944
|
subgraph: subgraphName,
|
|
3812
3945
|
blockHeight: height,
|
|
3813
3946
|
error: errorMsg
|
|
@@ -3826,7 +3959,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3826
3959
|
}
|
|
3827
3960
|
}
|
|
3828
3961
|
if (processed % LOG_INTERVAL === 0) {
|
|
3829
|
-
|
|
3962
|
+
logger9.info("Subgraph catch-up progress", {
|
|
3830
3963
|
subgraph: subgraphName,
|
|
3831
3964
|
processed,
|
|
3832
3965
|
total: totalBlocks,
|
|
@@ -3842,7 +3975,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3842
3975
|
currentHeight = batchEnd + 1;
|
|
3843
3976
|
}
|
|
3844
3977
|
await stats.flush(targetDb);
|
|
3845
|
-
|
|
3978
|
+
logger9.info("Subgraph catch-up complete", {
|
|
3846
3979
|
subgraph: subgraphName,
|
|
3847
3980
|
processed
|
|
3848
3981
|
});
|
|
@@ -3854,7 +3987,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
|
|
|
3854
3987
|
|
|
3855
3988
|
// src/runtime/reindex.ts
|
|
3856
3989
|
import { getErrorMessage as getErrorMessage3 } from "@secondlayer/shared";
|
|
3857
|
-
import { getRawClient, getTargetDb as
|
|
3990
|
+
import { getRawClient, getTargetDb as getTargetDb4 } from "@secondlayer/shared/db";
|
|
3858
3991
|
import {
|
|
3859
3992
|
recordGapBatch as recordGapBatch2,
|
|
3860
3993
|
resolveGaps
|
|
@@ -3867,11 +4000,11 @@ import {
|
|
|
3867
4000
|
recordSubgraphProcessed as recordSubgraphProcessed2,
|
|
3868
4001
|
updateSubgraphStatus as updateSubgraphStatus2
|
|
3869
4002
|
} from "@secondlayer/shared/db/queries/subgraphs";
|
|
3870
|
-
import { logger as
|
|
4003
|
+
import { logger as logger11 } from "@secondlayer/shared/logger";
|
|
3871
4004
|
|
|
3872
4005
|
// src/runtime/reindex-notify.ts
|
|
3873
4006
|
import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
|
|
3874
|
-
import { logger as
|
|
4007
|
+
import { logger as logger10 } from "@secondlayer/shared/logger";
|
|
3875
4008
|
async function notifyReindexComplete(db, subgraphName, stats) {
|
|
3876
4009
|
try {
|
|
3877
4010
|
const subgraph = await db.selectFrom("subgraphs").select(["account_id"]).where("name", "=", subgraphName).executeTakeFirst();
|
|
@@ -3882,7 +4015,7 @@ async function notifyReindexComplete(db, subgraphName, stats) {
|
|
|
3882
4015
|
return;
|
|
3883
4016
|
const resendKey = process.env.RESEND_API_KEY;
|
|
3884
4017
|
if (!resendKey) {
|
|
3885
|
-
|
|
4018
|
+
logger10.warn("RESEND_API_KEY unset — skipping reindex-complete email", {
|
|
3886
4019
|
subgraph: subgraphName
|
|
3887
4020
|
});
|
|
3888
4021
|
return;
|
|
@@ -3904,14 +4037,14 @@ async function notifyReindexComplete(db, subgraphName, stats) {
|
|
|
3904
4037
|
});
|
|
3905
4038
|
if (!res.ok) {
|
|
3906
4039
|
const text = await res.text().catch(() => "");
|
|
3907
|
-
|
|
4040
|
+
logger10.warn("reindex-complete email failed", {
|
|
3908
4041
|
subgraph: subgraphName,
|
|
3909
4042
|
status: res.status,
|
|
3910
4043
|
body: text.slice(0, 200)
|
|
3911
4044
|
});
|
|
3912
4045
|
}
|
|
3913
4046
|
} catch (err) {
|
|
3914
|
-
|
|
4047
|
+
logger10.warn("reindex-complete email threw", {
|
|
3915
4048
|
subgraph: subgraphName,
|
|
3916
4049
|
error: getErrorMessage2(err)
|
|
3917
4050
|
});
|
|
@@ -3980,7 +4113,7 @@ function coalesceFailedBlocks(blocks) {
|
|
|
3980
4113
|
}
|
|
3981
4114
|
async function processBlockRange(def, opts) {
|
|
3982
4115
|
const source = resolveBlockSource(def);
|
|
3983
|
-
const targetDb =
|
|
4116
|
+
const targetDb = getTargetDb4();
|
|
3984
4117
|
const subgraphName = def.name;
|
|
3985
4118
|
const { fromBlock, toBlock, status } = opts;
|
|
3986
4119
|
const totalBlocks = toBlock - fromBlock + 1;
|
|
@@ -4023,7 +4156,7 @@ async function processBlockRange(def, opts) {
|
|
|
4023
4156
|
while (currentHeight <= toBlock) {
|
|
4024
4157
|
if (opts.signal?.aborted) {
|
|
4025
4158
|
aborted = true;
|
|
4026
|
-
|
|
4159
|
+
logger11.info("Block processing aborted", {
|
|
4027
4160
|
subgraph: subgraphName,
|
|
4028
4161
|
currentBlock: currentHeight,
|
|
4029
4162
|
reason: String(opts.signal.reason ?? "unknown")
|
|
@@ -4074,7 +4207,7 @@ async function processBlockRange(def, opts) {
|
|
|
4074
4207
|
result = mayWrite ? await withSubgraphBlockWriteLock(subgraphName, runBlock) : await runBlock();
|
|
4075
4208
|
} catch (err) {
|
|
4076
4209
|
const errorMsg = getErrorMessage3(err);
|
|
4077
|
-
|
|
4210
|
+
logger11.error("Block processing failed persistently", {
|
|
4078
4211
|
subgraph: subgraphName,
|
|
4079
4212
|
blockHeight: height,
|
|
4080
4213
|
error: errorMsg
|
|
@@ -4120,7 +4253,7 @@ async function processBlockRange(def, opts) {
|
|
|
4120
4253
|
lastProgressFlushAt = now;
|
|
4121
4254
|
}
|
|
4122
4255
|
if (blocksProcessed % LOG_INTERVAL2 === 0) {
|
|
4123
|
-
|
|
4256
|
+
logger11.info(`${status === "reindexing" ? "Reindex" : "Backfill"} progress`, {
|
|
4124
4257
|
subgraph: subgraphName,
|
|
4125
4258
|
processed: blocksProcessed,
|
|
4126
4259
|
total: totalBlocks,
|
|
@@ -4140,7 +4273,7 @@ async function processBlockRange(def, opts) {
|
|
|
4140
4273
|
if (batchFailedBlocks.length > 0 && opts.subgraphId) {
|
|
4141
4274
|
const gaps = coalesceFailedBlocks(batchFailedBlocks);
|
|
4142
4275
|
await recordGapBatch2(targetDb, opts.subgraphId, subgraphName, gaps).catch((err) => {
|
|
4143
|
-
|
|
4276
|
+
logger11.warn("Failed to record subgraph gaps", {
|
|
4144
4277
|
subgraph: subgraphName,
|
|
4145
4278
|
error: err instanceof Error ? err.message : String(err)
|
|
4146
4279
|
});
|
|
@@ -4157,7 +4290,7 @@ async function processBlockRange(def, opts) {
|
|
|
4157
4290
|
} else {
|
|
4158
4291
|
await updateSubgraphStatus2(targetDb, subgraphName, status, jumpTo - 1);
|
|
4159
4292
|
}
|
|
4160
|
-
|
|
4293
|
+
logger11.info("Sparse skip", {
|
|
4161
4294
|
subgraph: subgraphName,
|
|
4162
4295
|
from: batchEnd + 1,
|
|
4163
4296
|
to: jumpTo - 1,
|
|
@@ -4191,7 +4324,7 @@ async function resolveBlockRange(source, def, opts) {
|
|
|
4191
4324
|
}
|
|
4192
4325
|
const bound = await boundSourceTip(rawTip, decoderNamesForSubgraph(def));
|
|
4193
4326
|
if (!bound.ok) {
|
|
4194
|
-
|
|
4327
|
+
logger11.warn("Reindex stalled: missing decoder checkpoint", {
|
|
4195
4328
|
event: "subgraph_reindex_decoder_stall",
|
|
4196
4329
|
subgraph: def.name,
|
|
4197
4330
|
missing: bound.missing
|
|
@@ -4199,7 +4332,7 @@ async function resolveBlockRange(source, def, opts) {
|
|
|
4199
4332
|
throw new Error(`Reindex stalled: missing decoder checkpoint (${bound.missing.join(", ")})`);
|
|
4200
4333
|
}
|
|
4201
4334
|
if (bound.floor !== null && bound.floor < rawTip) {
|
|
4202
|
-
|
|
4335
|
+
logger11.debug("Reindex tip bounded by decoder progress", {
|
|
4203
4336
|
event: "subgraph_reindex_decoder_floor",
|
|
4204
4337
|
subgraph: def.name,
|
|
4205
4338
|
rawTip,
|
|
@@ -4214,16 +4347,16 @@ async function clearReindexMetadata(db, subgraphName) {
|
|
|
4214
4347
|
}
|
|
4215
4348
|
async function reindexSubgraph(def, opts) {
|
|
4216
4349
|
const source = resolveBlockSource(def);
|
|
4217
|
-
const targetDb =
|
|
4350
|
+
const targetDb = getTargetDb4();
|
|
4218
4351
|
const client = getRawClient("target");
|
|
4219
4352
|
const subgraphName = def.name;
|
|
4220
4353
|
const schemaName = opts?.schemaName ?? pgSchemaName(subgraphName);
|
|
4221
4354
|
await updateSubgraphStatus2(targetDb, subgraphName, "reindexing");
|
|
4222
|
-
|
|
4355
|
+
logger11.info("Reindex starting", { subgraph: subgraphName });
|
|
4223
4356
|
try {
|
|
4224
4357
|
const { fromBlock, toBlock } = await resolveBlockRange(source, def, opts);
|
|
4225
4358
|
if (fromBlock > toBlock) {
|
|
4226
|
-
|
|
4359
|
+
logger11.info("No blocks to reindex", {
|
|
4227
4360
|
subgraph: subgraphName,
|
|
4228
4361
|
fromBlock,
|
|
4229
4362
|
toBlock
|
|
@@ -4237,7 +4370,7 @@ async function reindexSubgraph(def, opts) {
|
|
|
4237
4370
|
await client.unsafe(stmt);
|
|
4238
4371
|
}
|
|
4239
4372
|
await updateSubgraphStatus2(targetDb, subgraphName, "reindexing", Math.max(0, fromBlock - 1));
|
|
4240
|
-
|
|
4373
|
+
logger11.info("Schema recreated for reindex", {
|
|
4241
4374
|
subgraph: subgraphName,
|
|
4242
4375
|
cursorResetTo: Math.max(0, fromBlock - 1)
|
|
4243
4376
|
});
|
|
@@ -4251,7 +4384,7 @@ async function reindexSubgraph(def, opts) {
|
|
|
4251
4384
|
last_error_at: null,
|
|
4252
4385
|
updated_at: new Date
|
|
4253
4386
|
}).where("name", "=", subgraphName).execute();
|
|
4254
|
-
|
|
4387
|
+
logger11.info("Reindexing blocks", {
|
|
4255
4388
|
subgraph: subgraphName,
|
|
4256
4389
|
fromBlock,
|
|
4257
4390
|
toBlock,
|
|
@@ -4273,9 +4406,9 @@ async function reindexSubgraph(def, opts) {
|
|
|
4273
4406
|
if (reason === "user-cancelled") {
|
|
4274
4407
|
await updateSubgraphStatus2(targetDb, subgraphName, "active");
|
|
4275
4408
|
await clearReindexMetadata(targetDb, subgraphName);
|
|
4276
|
-
|
|
4409
|
+
logger11.info("Reindex cancelled by user", { subgraph: subgraphName });
|
|
4277
4410
|
} else {
|
|
4278
|
-
|
|
4411
|
+
logger11.info("Reindex interrupted by shutdown, will resume", {
|
|
4279
4412
|
subgraph: subgraphName
|
|
4280
4413
|
});
|
|
4281
4414
|
}
|
|
@@ -4283,7 +4416,7 @@ async function reindexSubgraph(def, opts) {
|
|
|
4283
4416
|
}
|
|
4284
4417
|
await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
|
|
4285
4418
|
await clearReindexMetadata(targetDb, subgraphName);
|
|
4286
|
-
|
|
4419
|
+
logger11.info("Reindex complete", {
|
|
4287
4420
|
subgraph: subgraphName,
|
|
4288
4421
|
blocks: result.blocksProcessed,
|
|
4289
4422
|
events: result.totalEventsProcessed,
|
|
@@ -4296,7 +4429,7 @@ async function reindexSubgraph(def, opts) {
|
|
|
4296
4429
|
});
|
|
4297
4430
|
return { processed: result.blocksProcessed };
|
|
4298
4431
|
} catch (err) {
|
|
4299
|
-
|
|
4432
|
+
logger11.error("Reindex failed", {
|
|
4300
4433
|
subgraph: subgraphName,
|
|
4301
4434
|
error: getErrorMessage3(err)
|
|
4302
4435
|
});
|
|
@@ -4305,7 +4438,7 @@ async function reindexSubgraph(def, opts) {
|
|
|
4305
4438
|
}
|
|
4306
4439
|
}
|
|
4307
4440
|
async function resumeReindex(def, opts) {
|
|
4308
|
-
const targetDb =
|
|
4441
|
+
const targetDb = getTargetDb4();
|
|
4309
4442
|
const subgraphName = def.name;
|
|
4310
4443
|
const row = await targetDb.selectFrom("subgraphs").select([
|
|
4311
4444
|
"id",
|
|
@@ -4318,7 +4451,7 @@ async function resumeReindex(def, opts) {
|
|
|
4318
4451
|
const fromBlock = resolveReindexResumeBlock(row);
|
|
4319
4452
|
const toBlock = Number(row.reindex_to_block);
|
|
4320
4453
|
if (fromBlock == null) {
|
|
4321
|
-
|
|
4454
|
+
logger11.info("No reindex metadata, starting fresh reindex", {
|
|
4322
4455
|
subgraph: subgraphName
|
|
4323
4456
|
});
|
|
4324
4457
|
return reindexSubgraph(def, {
|
|
@@ -4327,12 +4460,12 @@ async function resumeReindex(def, opts) {
|
|
|
4327
4460
|
});
|
|
4328
4461
|
}
|
|
4329
4462
|
if (fromBlock > toBlock) {
|
|
4330
|
-
|
|
4463
|
+
logger11.info("Resume: no remaining blocks", { subgraph: subgraphName });
|
|
4331
4464
|
await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
|
|
4332
4465
|
await clearReindexMetadata(targetDb, subgraphName);
|
|
4333
4466
|
return { processed: 0 };
|
|
4334
4467
|
}
|
|
4335
|
-
|
|
4468
|
+
logger11.info("Resuming reindex", {
|
|
4336
4469
|
subgraph: subgraphName,
|
|
4337
4470
|
fromBlock,
|
|
4338
4471
|
toBlock,
|
|
@@ -4354,9 +4487,9 @@ async function resumeReindex(def, opts) {
|
|
|
4354
4487
|
if (reason === "user-cancelled") {
|
|
4355
4488
|
await updateSubgraphStatus2(targetDb, subgraphName, "active");
|
|
4356
4489
|
await clearReindexMetadata(targetDb, subgraphName);
|
|
4357
|
-
|
|
4490
|
+
logger11.info("Resume cancelled by user", { subgraph: subgraphName });
|
|
4358
4491
|
} else {
|
|
4359
|
-
|
|
4492
|
+
logger11.info("Resume interrupted by shutdown, will resume again", {
|
|
4360
4493
|
subgraph: subgraphName
|
|
4361
4494
|
});
|
|
4362
4495
|
}
|
|
@@ -4364,13 +4497,13 @@ async function resumeReindex(def, opts) {
|
|
|
4364
4497
|
}
|
|
4365
4498
|
await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
|
|
4366
4499
|
await clearReindexMetadata(targetDb, subgraphName);
|
|
4367
|
-
|
|
4500
|
+
logger11.info("Resumed reindex complete", {
|
|
4368
4501
|
subgraph: subgraphName,
|
|
4369
4502
|
blocks: result.blocksProcessed
|
|
4370
4503
|
});
|
|
4371
4504
|
return { processed: result.blocksProcessed };
|
|
4372
4505
|
} catch (err) {
|
|
4373
|
-
|
|
4506
|
+
logger11.error("Resumed reindex failed", {
|
|
4374
4507
|
subgraph: subgraphName,
|
|
4375
4508
|
error: getErrorMessage3(err)
|
|
4376
4509
|
});
|
|
@@ -4379,9 +4512,9 @@ async function resumeReindex(def, opts) {
|
|
|
4379
4512
|
}
|
|
4380
4513
|
}
|
|
4381
4514
|
async function backfillSubgraph(def, opts) {
|
|
4382
|
-
const targetDb =
|
|
4515
|
+
const targetDb = getTargetDb4();
|
|
4383
4516
|
const subgraphName = def.name;
|
|
4384
|
-
|
|
4517
|
+
logger11.info("Backfill starting", {
|
|
4385
4518
|
subgraph: subgraphName,
|
|
4386
4519
|
from: opts.fromBlock,
|
|
4387
4520
|
to: opts.toBlock
|
|
@@ -4399,17 +4532,17 @@ async function backfillSubgraph(def, opts) {
|
|
|
4399
4532
|
signal: opts.signal
|
|
4400
4533
|
});
|
|
4401
4534
|
if (result.aborted) {
|
|
4402
|
-
|
|
4535
|
+
logger11.info("Backfill aborted", { subgraph: subgraphName });
|
|
4403
4536
|
return { processed: result.blocksProcessed };
|
|
4404
4537
|
}
|
|
4405
4538
|
const resolved = await resolveGaps(targetDb, subgraphName, opts.fromBlock, opts.toBlock).catch(() => 0);
|
|
4406
4539
|
if (resolved > 0) {
|
|
4407
|
-
|
|
4540
|
+
logger11.info("Resolved subgraph gaps via backfill", {
|
|
4408
4541
|
subgraph: subgraphName,
|
|
4409
4542
|
resolved
|
|
4410
4543
|
});
|
|
4411
4544
|
}
|
|
4412
|
-
|
|
4545
|
+
logger11.info("Backfill complete", {
|
|
4413
4546
|
subgraph: subgraphName,
|
|
4414
4547
|
blocks: result.blocksProcessed,
|
|
4415
4548
|
events: result.totalEventsProcessed,
|
|
@@ -4417,7 +4550,7 @@ async function backfillSubgraph(def, opts) {
|
|
|
4417
4550
|
});
|
|
4418
4551
|
return { processed: result.blocksProcessed };
|
|
4419
4552
|
} catch (err) {
|
|
4420
|
-
|
|
4553
|
+
logger11.error("Backfill failed", {
|
|
4421
4554
|
subgraph: subgraphName,
|
|
4422
4555
|
error: getErrorMessage3(err)
|
|
4423
4556
|
});
|
|
@@ -4434,5 +4567,5 @@ export {
|
|
|
4434
4567
|
backfillSubgraph
|
|
4435
4568
|
};
|
|
4436
4569
|
|
|
4437
|
-
//# debugId=
|
|
4570
|
+
//# debugId=F75F0447014C339A64756E2164756E21
|
|
4438
4571
|
//# sourceMappingURL=reindex.js.map
|