@secondlayer/subgraphs 3.24.0 → 3.24.2

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.
@@ -11,6 +11,11 @@ import { createHash } from "node:crypto";
11
11
 
12
12
  // src/schema/utils.ts
13
13
  import { pgSchemaName } from "@secondlayer/shared/db/queries/subgraphs";
14
+ function quotePgIdent(name) {
15
+ if (/^[a-z_][a-z0-9_]*$/i.test(name))
16
+ return name;
17
+ return `"${name.replace(/"/g, '""')}"`;
18
+ }
14
19
 
15
20
  // src/schema/generator.ts
16
21
  var TYPE_MAP = {
@@ -35,7 +40,7 @@ function tableNeedsTrgm(tableDef) {
35
40
  return Object.values(tableDef.columns).some((col) => col.search);
36
41
  }
37
42
  function emitTableDDL(schemaName, tableName, tableDef) {
38
- const qualifiedName = `${schemaName}.${tableName}`;
43
+ const qualifiedName = `${quotePgIdent(schemaName)}.${quotePgIdent(tableName)}`;
39
44
  const statements = [];
40
45
  const columnDefs = [
41
46
  "_id BIGSERIAL PRIMARY KEY",
@@ -46,12 +51,12 @@ function emitTableDDL(schemaName, tableName, tableDef) {
46
51
  for (const [colName, col] of Object.entries(tableDef.columns)) {
47
52
  const sqlType = TYPE_MAP[col.type];
48
53
  const nullable = col.nullable ? "" : " NOT NULL";
49
- let colDef = `${colName} ${sqlType}${nullable}`;
54
+ let colDef = `${quotePgIdent(colName)} ${sqlType}${nullable}`;
50
55
  if (col.default !== undefined) {
51
56
  colDef += ` DEFAULT ${escapeLiteralDefault(col.default)}`;
52
57
  }
53
58
  if (col.type === "uint") {
54
- colDef += ` CHECK (${colName} >= 0)`;
59
+ colDef += ` CHECK (${quotePgIdent(colName)} >= 0)`;
55
60
  }
56
61
  columnDefs.push(colDef);
57
62
  }
@@ -59,30 +64,30 @@ function emitTableDDL(schemaName, tableName, tableDef) {
59
64
  ${columnDefs.join(`,
60
65
  `)}
61
66
  )`);
62
- statements.push(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_block_height ON ${qualifiedName} (_block_height)`);
63
- statements.push(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_tx_id ON ${qualifiedName} (_tx_id)`);
67
+ statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_block_height`)} ON ${qualifiedName} (_block_height)`);
68
+ statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_tx_id`)} ON ${qualifiedName} (_tx_id)`);
64
69
  for (const [colName, col] of Object.entries(tableDef.columns)) {
65
70
  if (col.indexed) {
66
- statements.push(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName} ON ${qualifiedName} (${colName})`);
71
+ statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_${colName}`)} ON ${qualifiedName} (${quotePgIdent(colName)})`);
67
72
  }
68
73
  }
69
74
  for (const [colName, col] of Object.entries(tableDef.columns)) {
70
75
  if (col.search) {
71
- statements.push(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName}_trgm ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`);
76
+ statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_${colName}_trgm`)} ON ${qualifiedName} USING gin (${quotePgIdent(colName)} gin_trgm_ops)`);
72
77
  }
73
78
  }
74
79
  if (tableDef.indexes) {
75
80
  for (let i = 0;i < tableDef.indexes.length; i++) {
76
81
  const cols = tableDef.indexes[i];
77
- const idxName = `idx_${schemaName}_${tableName}_composite_${i}`;
78
- statements.push(`CREATE INDEX IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.join(", ")})`);
82
+ const idxName = quotePgIdent(`idx_${schemaName}_${tableName}_composite_${i}`);
83
+ statements.push(`CREATE INDEX IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.map(quotePgIdent).join(", ")})`);
79
84
  }
80
85
  }
81
86
  if (tableDef.uniqueKeys) {
82
87
  for (let i = 0;i < tableDef.uniqueKeys.length; i++) {
83
88
  const cols = tableDef.uniqueKeys[i];
84
- const constraintName = `uq_${schemaName}_${tableName}_${cols.join("_")}`;
85
- statements.push(`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.join(", ")})`);
89
+ const constraintName = quotePgIdent(`uq_${schemaName}_${tableName}_${cols.join("_")}`);
90
+ statements.push(`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.map(quotePgIdent).join(", ")})`);
86
91
  }
87
92
  }
88
93
  return statements;
@@ -114,8 +119,8 @@ function emitFactoryDDL(schemaName) {
114
119
  }
115
120
  function emitForeignKeyDDL(schemaName, tableName, tableDef) {
116
121
  return (tableDef.relations ?? []).map((rel) => {
117
- const constraintName = `fk_${schemaName}_${tableName}_${rel.name}`;
118
- return `ALTER TABLE ${schemaName}.${tableName} ADD CONSTRAINT ${constraintName} ` + `FOREIGN KEY (${rel.fields.join(", ")}) ` + `REFERENCES ${schemaName}.${rel.references} (${rel.referencedColumns.join(", ")})`;
122
+ const constraintName = quotePgIdent(`fk_${schemaName}_${tableName}_${rel.name}`);
123
+ return `ALTER TABLE ${quotePgIdent(schemaName)}.${quotePgIdent(tableName)} ADD CONSTRAINT ${constraintName} ` + `FOREIGN KEY (${rel.fields.map(quotePgIdent).join(", ")}) ` + `REFERENCES ${quotePgIdent(schemaName)}.${quotePgIdent(rel.references)} (${rel.referencedColumns.map(quotePgIdent).join(", ")})`;
119
124
  });
120
125
  }
121
126
  function generateSubgraphSQL(def, schemaNameOverride) {
@@ -1634,7 +1639,7 @@ import {
1634
1639
  rewindLiveProgress,
1635
1640
  updateSubgraphStatus
1636
1641
  } from "@secondlayer/shared/db/queries/subgraphs";
1637
- import { logger as logger6 } from "@secondlayer/shared/logger";
1642
+ import { logger as logger7 } from "@secondlayer/shared/logger";
1638
1643
  import { sql as sql3 } from "kysely";
1639
1644
 
1640
1645
  // src/runtime/block-source.ts
@@ -2075,6 +2080,315 @@ async function emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block
2075
2080
  return rows.length;
2076
2081
  }
2077
2082
 
2083
+ // src/runtime/sandbox/flag.ts
2084
+ function sandboxWorkersGloballyEnabled() {
2085
+ return process.env.SUBGRAPH_SANDBOX_WORKERS === "1";
2086
+ }
2087
+ function sandboxEnabled(subgraph) {
2088
+ return sandboxWorkersGloballyEnabled() && subgraph.sandbox_workers === true;
2089
+ }
2090
+
2091
+ // src/runtime/sandbox/host.ts
2092
+ import { tmpdir } from "node:os";
2093
+ import { fileURLToPath } from "node:url";
2094
+ import { logger as logger6 } from "@secondlayer/shared/logger";
2095
+
2096
+ // src/runtime/sandbox/bundle.ts
2097
+ import esbuild from "esbuild";
2098
+ var ALLOWED_BARE_SPECIFIERS = new Set;
2099
+ var SUBGRAPHS_PACKAGE_SPECIFIER = "@secondlayer/subgraphs";
2100
+ var SUBGRAPHS_STUB_SOURCE = `export function defineSubgraph(def) { return def; }
2101
+ `;
2102
+ function resolverLockdownPlugin() {
2103
+ return {
2104
+ name: "f071-sandbox-resolver-lockdown",
2105
+ setup(build) {
2106
+ build.onResolve({ filter: /^@secondlayer\/subgraphs$/ }, (args) => ({
2107
+ path: args.path,
2108
+ namespace: "f071-sandbox-subgraphs-stub"
2109
+ }));
2110
+ build.onLoad({ filter: /.*/, namespace: "f071-sandbox-subgraphs-stub" }, () => ({ contents: SUBGRAPHS_STUB_SOURCE, loader: "js" }));
2111
+ build.onResolve({ filter: /^(node:|bun:)/ }, (args) => ({
2112
+ path: args.path,
2113
+ namespace: "f071-sandbox-blocked"
2114
+ }));
2115
+ build.onResolve({ filter: /^[^./]/ }, (args) => {
2116
+ if (args.path === SUBGRAPHS_PACKAGE_SPECIFIER)
2117
+ return;
2118
+ if (ALLOWED_BARE_SPECIFIERS.has(args.path))
2119
+ return;
2120
+ return { path: args.path, namespace: "f071-sandbox-blocked" };
2121
+ });
2122
+ build.onLoad({ filter: /.*/, namespace: "f071-sandbox-blocked" }, (args) => ({
2123
+ contents: `throw new Error(${JSON.stringify(`subgraph sandbox: import of "${args.path}" is blocked in sandboxed handler code — handlers must use the injected \`ctx\` for all I/O`)});`,
2124
+ loader: "js"
2125
+ }));
2126
+ }
2127
+ };
2128
+ }
2129
+ async function bundleHandlerCode(handlerCode) {
2130
+ const result = await esbuild.build({
2131
+ stdin: {
2132
+ contents: handlerCode,
2133
+ loader: "ts",
2134
+ resolveDir: process.cwd()
2135
+ },
2136
+ bundle: true,
2137
+ platform: "neutral",
2138
+ format: "esm",
2139
+ write: false,
2140
+ logLevel: "silent",
2141
+ plugins: [resolverLockdownPlugin()]
2142
+ });
2143
+ const out = result.outputFiles?.[0];
2144
+ if (!out)
2145
+ throw new Error("esbuild produced no output for handler_code bundle");
2146
+ return new TextDecoder().decode(out.contents);
2147
+ }
2148
+
2149
+ // src/runtime/sandbox/host.ts
2150
+ var BLOCK_TIMEOUT_MS = Number.parseInt(process.env.SUBGRAPH_SANDBOX_BLOCK_TIMEOUT_MS ?? "60000");
2151
+ var SUBPROCESS_ENTRY_PATH = fileURLToPath(new URL("./subprocess-entry.ts", import.meta.url));
2152
+ function spawnSandboxProcess() {
2153
+ let onMessage = null;
2154
+ const proc = Bun.spawn({
2155
+ cmd: [process.execPath, "--no-env-file", SUBPROCESS_ENTRY_PATH],
2156
+ env: { PATH: process.env.PATH ?? "" },
2157
+ cwd: tmpdir(),
2158
+ stdio: ["ignore", "ignore", "pipe"],
2159
+ serialization: "advanced",
2160
+ ipc(message) {
2161
+ onMessage?.(message);
2162
+ }
2163
+ });
2164
+ (async () => {
2165
+ const reader = proc.stderr.getReader();
2166
+ const decoder = new TextDecoder;
2167
+ try {
2168
+ while (true) {
2169
+ const { done, value } = await reader.read();
2170
+ if (done)
2171
+ break;
2172
+ const text = decoder.decode(value, { stream: true });
2173
+ if (text.trim()) {
2174
+ logger6.warn("Sandbox subprocess stderr", { stderr: text.trim() });
2175
+ }
2176
+ }
2177
+ } catch {}
2178
+ })();
2179
+ return {
2180
+ send: (msg) => proc.send(msg),
2181
+ kill: () => proc.kill(),
2182
+ exited: proc.exited,
2183
+ setOnMessage: (handler) => {
2184
+ onMessage = handler;
2185
+ }
2186
+ };
2187
+ }
2188
+ var pool = new Map;
2189
+
2190
+ class SandboxWorkerCrash extends Error {
2191
+ constructor(subgraphName, cause) {
2192
+ super(`sandbox subprocess for "${subgraphName}" failed: ${cause}`);
2193
+ this.name = "SandboxWorkerCrash";
2194
+ }
2195
+ }
2196
+ async function initSandboxProcess(proc, subgraphName, version, handlerCode) {
2197
+ const bundledCode = await bundleHandlerCode(handlerCode);
2198
+ let settled = false;
2199
+ const ready = new Promise((resolve, reject) => {
2200
+ proc.setOnMessage((msg) => {
2201
+ if (msg.type === "ready" && msg.version === version) {
2202
+ settled = true;
2203
+ proc.setOnMessage(null);
2204
+ resolve();
2205
+ } else if (msg.type === "error") {
2206
+ settled = true;
2207
+ proc.setOnMessage(null);
2208
+ reject(new SandboxWorkerCrash(subgraphName, msg.message));
2209
+ }
2210
+ });
2211
+ const init = { type: "init", bundledCode, version };
2212
+ proc.send(init);
2213
+ });
2214
+ const crashed = proc.exited.then((code) => {
2215
+ if (settled)
2216
+ return;
2217
+ throw new SandboxWorkerCrash(subgraphName, `subprocess exited (code ${code}) during init`);
2218
+ });
2219
+ await Promise.race([ready, crashed]);
2220
+ }
2221
+ async function ensureSandboxProcess(subgraphName, version, handlerCode) {
2222
+ if (handlerCode == null) {
2223
+ throw new SandboxWorkerCrash(subgraphName, "subgraph has no handler_code; cannot bundle for the sandbox path");
2224
+ }
2225
+ const existing = pool.get(subgraphName);
2226
+ if (existing && existing.version === version)
2227
+ return existing;
2228
+ if (existing) {
2229
+ try {
2230
+ await initSandboxProcess(existing.proc, subgraphName, version, handlerCode);
2231
+ existing.version = version;
2232
+ logger6.info("Sandbox subprocess handler reloaded", {
2233
+ subgraph: subgraphName,
2234
+ version
2235
+ });
2236
+ return existing;
2237
+ } catch (err) {
2238
+ existing.proc.kill();
2239
+ pool.delete(subgraphName);
2240
+ logger6.warn("Sandbox subprocess re-init failed; respawning", {
2241
+ subgraph: subgraphName,
2242
+ error: err instanceof Error ? err.message : String(err)
2243
+ });
2244
+ }
2245
+ }
2246
+ const proc = spawnSandboxProcess();
2247
+ try {
2248
+ await initSandboxProcess(proc, subgraphName, version, handlerCode);
2249
+ } catch (err) {
2250
+ proc.kill();
2251
+ throw err;
2252
+ }
2253
+ const entry = { proc, version, chain: Promise.resolve() };
2254
+ pool.set(subgraphName, entry);
2255
+ return entry;
2256
+ }
2257
+ function evictSandboxWorker(subgraphName) {
2258
+ const entry = pool.get(subgraphName);
2259
+ if (!entry)
2260
+ return;
2261
+ entry.proc.kill();
2262
+ pool.delete(subgraphName);
2263
+ }
2264
+ async function runHandlersSandboxed(params) {
2265
+ const { subgraphName, version, handlerCode, hostCtx, block, matched } = params;
2266
+ const entry = await ensureSandboxProcess(subgraphName, version, handlerCode);
2267
+ const run = entry.chain.then(() => runBlockThroughProcess(entry, subgraphName, hostCtx, block, matched));
2268
+ entry.chain = run.catch(() => {
2269
+ return;
2270
+ });
2271
+ return run;
2272
+ }
2273
+ async function runBlockThroughProcess(entry, subgraphName, hostCtx, block, matched) {
2274
+ const { proc } = entry;
2275
+ let timeoutHandle;
2276
+ let settled = false;
2277
+ try {
2278
+ const done = new Promise((resolve, reject) => {
2279
+ proc.setOnMessage((msg) => {
2280
+ if (msg.type === "readRequest") {
2281
+ answerRead(hostCtx, msg).then((reply) => {
2282
+ proc.send({ type: "readResponse", id: msg.id, reply });
2283
+ }).catch((err) => {
2284
+ settled = true;
2285
+ reject(new SandboxWorkerCrash(subgraphName, `host read failed: ${err instanceof Error ? err.message : String(err)}`));
2286
+ });
2287
+ return;
2288
+ }
2289
+ if (msg.type === "blockDone") {
2290
+ settled = true;
2291
+ resolve({
2292
+ ops: msg.ops,
2293
+ result: { processed: msg.processed, errors: msg.errors }
2294
+ });
2295
+ return;
2296
+ }
2297
+ if (msg.type === "error") {
2298
+ settled = true;
2299
+ reject(new SandboxWorkerCrash(subgraphName, msg.message));
2300
+ }
2301
+ });
2302
+ proc.send({ type: "runBlock", block, matched });
2303
+ });
2304
+ const crashed = proc.exited.then((code) => {
2305
+ if (settled)
2306
+ return;
2307
+ throw new SandboxWorkerCrash(subgraphName, `subprocess exited unexpectedly (code ${code}) mid-block`);
2308
+ });
2309
+ const deadline = new Promise((_, reject) => {
2310
+ timeoutHandle = setTimeout(() => {
2311
+ settled = true;
2312
+ reject(new SandboxWorkerCrash(subgraphName, `block ${block.height} exceeded ${BLOCK_TIMEOUT_MS}ms deadline`));
2313
+ }, BLOCK_TIMEOUT_MS);
2314
+ });
2315
+ const { ops, result } = await Promise.race([done, crashed, deadline]);
2316
+ for (const op of ops) {
2317
+ hostCtx.setTx(op.tx);
2318
+ replayOp(hostCtx, op);
2319
+ }
2320
+ return result;
2321
+ } catch (err) {
2322
+ evictSandboxWorker(subgraphName);
2323
+ logger6.warn("Sandbox subprocess run failed; subprocess evicted", {
2324
+ subgraph: subgraphName,
2325
+ blockHeight: block.height,
2326
+ error: err instanceof Error ? err.message : String(err)
2327
+ });
2328
+ throw err;
2329
+ } finally {
2330
+ if (timeoutHandle !== undefined)
2331
+ clearTimeout(timeoutHandle);
2332
+ proc.setOnMessage(null);
2333
+ }
2334
+ }
2335
+ function replayOp(hostCtx, op) {
2336
+ switch (op.method) {
2337
+ case "insert":
2338
+ hostCtx.insert(op.table, op.args[0]);
2339
+ return;
2340
+ case "upsert":
2341
+ hostCtx.upsert(op.table, op.args[0], op.args[1]);
2342
+ return;
2343
+ case "increment":
2344
+ hostCtx.increment(op.table, op.args[0], op.args[1]);
2345
+ return;
2346
+ case "update":
2347
+ hostCtx.update(op.table, op.args[0], op.args[1]);
2348
+ return;
2349
+ case "delete":
2350
+ hostCtx.delete(op.table, op.args[0]);
2351
+ return;
2352
+ }
2353
+ }
2354
+ async function answerRead(hostCtx, msg) {
2355
+ const { method, table, where, column } = msg;
2356
+ switch (method) {
2357
+ case "findOne":
2358
+ return { kind: "row", row: await hostCtx.findOne(table, where) };
2359
+ case "findMany":
2360
+ return { kind: "rows", rows: await hostCtx.findMany(table, where) };
2361
+ case "count":
2362
+ return { kind: "count", count: await hostCtx.count(table, where) };
2363
+ case "countDistinct": {
2364
+ if (!column)
2365
+ throw new Error("countDistinct read missing column");
2366
+ return {
2367
+ kind: "count",
2368
+ count: await hostCtx.countDistinct(table, column, where)
2369
+ };
2370
+ }
2371
+ case "sum": {
2372
+ if (!column)
2373
+ throw new Error("sum read missing column");
2374
+ const v = await hostCtx.sum(table, column, where);
2375
+ return { kind: "amount", amount: v.toString() };
2376
+ }
2377
+ case "min": {
2378
+ if (!column)
2379
+ throw new Error("min read missing column");
2380
+ const v = await hostCtx.min(table, column, where);
2381
+ return { kind: "amount", amount: v == null ? null : v.toString() };
2382
+ }
2383
+ case "max": {
2384
+ if (!column)
2385
+ throw new Error("max read missing column");
2386
+ const v = await hostCtx.max(table, column, where);
2387
+ return { kind: "amount", amount: v == null ? null : v.toString() };
2388
+ }
2389
+ }
2390
+ }
2391
+
2078
2392
  // src/runtime/subscription-state.ts
2079
2393
  import { listSubscriptions } from "@secondlayer/shared/db/queries/subscriptions";
2080
2394
  import { sql as sql2 } from "kysely";
@@ -2259,13 +2573,17 @@ async function resolveRoute(subgraphName, targetDb) {
2259
2573
  const route = {
2260
2574
  schemaName: row?.schema_name ?? pgSchemaName(subgraphName),
2261
2575
  dataDb: row && byo ? resolveSubgraphDb(row) : targetDb,
2262
- byo
2576
+ byo,
2577
+ sandboxWorkers: row?.sandbox_workers === true,
2578
+ handlerCode: row?.handler_code ?? null,
2579
+ version: row?.version ?? ""
2263
2580
  };
2264
2581
  routeCache.set(subgraphName, route);
2265
2582
  return route;
2266
2583
  }
2267
2584
  function invalidateSubgraphRoute(subgraphName) {
2268
2585
  routeCache.delete(subgraphName);
2586
+ evictSandboxWorker(subgraphName);
2269
2587
  }
2270
2588
  async function resolveFactoryContracts(subgraph, blockHeight, schemaName, db, txs, evts) {
2271
2589
  const factories = new Map;
@@ -2371,7 +2689,7 @@ async function processBlockWithRetry(subgraph, subgraphName, blockHeight, opts,
2371
2689
  const delay = retryDelaysMs[attempt];
2372
2690
  if (delay === undefined)
2373
2691
  break;
2374
- logger6.warn("Block processing failed, retrying", {
2692
+ logger7.warn("Block processing failed, retrying", {
2375
2693
  subgraph: subgraphName,
2376
2694
  blockHeight,
2377
2695
  attempt: attempt + 1,
@@ -2403,7 +2721,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2403
2721
  } else {
2404
2722
  const data = (await resolveBlockSource(subgraph).loadBlockRange(blockHeight, blockHeight)).get(blockHeight);
2405
2723
  if (!data) {
2406
- logger6.debug("Block not found or non-canonical for subgraph processing", {
2724
+ logger7.debug("Block not found or non-canonical for subgraph processing", {
2407
2725
  subgraph: subgraphName,
2408
2726
  blockHeight
2409
2727
  });
@@ -2539,7 +2857,16 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2539
2857
  }
2540
2858
  const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx, false, journalEnabled(opts));
2541
2859
  const handlerStart = performance.now();
2542
- const runResult = await runHandlers(subgraph, matched, ctx);
2860
+ const runResult = sandboxEnabled({
2861
+ sandbox_workers: route.sandboxWorkers
2862
+ }) ? await runHandlersSandboxed({
2863
+ subgraphName,
2864
+ version: route.version,
2865
+ handlerCode: route.handlerCode,
2866
+ hostCtx: ctx,
2867
+ block: blockMeta,
2868
+ matched
2869
+ }) : await runHandlers(subgraph, matched, ctx);
2543
2870
  handlerMs = performance.now() - handlerStart;
2544
2871
  result.processed = runResult.processed;
2545
2872
  result.errors = runResult.errors;
@@ -2565,7 +2892,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2565
2892
  });
2566
2893
  } catch (err) {
2567
2894
  if (err instanceof CursorRaceLostError || err instanceof LiveCursorRaceLostError) {
2568
- logger6.warn("cursor race lost — block already covered", {
2895
+ logger7.warn("cursor race lost — block already covered", {
2569
2896
  subgraph: subgraphName,
2570
2897
  blockHeight,
2571
2898
  error: err.message
@@ -2591,7 +2918,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2591
2918
  const { rows } = await sql3.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(route.dataDb);
2592
2919
  const count = Number(rows[0]?.count ?? 0);
2593
2920
  if (count >= 1e7) {
2594
- logger6.warn("Subgraph table exceeds 10M rows (estimate)", {
2921
+ logger7.warn("Subgraph table exceeds 10M rows (estimate)", {
2595
2922
  subgraph: subgraphName,
2596
2923
  table,
2597
2924
  count
@@ -2599,7 +2926,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
2599
2926
  }
2600
2927
  }
2601
2928
  } catch (err) {
2602
- logger6.debug("Row count sample failed", {
2929
+ logger7.debug("Row count sample failed", {
2603
2930
  subgraph: subgraphName,
2604
2931
  error: err instanceof Error ? err.message : String(err)
2605
2932
  });
@@ -2677,7 +3004,7 @@ class StatsAccumulator {
2677
3004
  // src/runtime/catchup.ts
2678
3005
  import { getTargetDb as getTargetDb2 } from "@secondlayer/shared/db";
2679
3006
  import { getSubgraph } from "@secondlayer/shared/db/queries/subgraphs";
2680
- import { logger as logger7 } from "@secondlayer/shared/logger";
3007
+ import { logger as logger8 } from "@secondlayer/shared/logger";
2681
3008
 
2682
3009
  // src/runtime/catchup-leader.ts
2683
3010
  import {
@@ -2811,7 +3138,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2811
3138
  const subgraphStart = Number(subgraphRow.start_block) || 1;
2812
3139
  const startBlock = Math.max(lastProcessedBlock + 1, subgraphStart);
2813
3140
  const totalBlocks = chainTip - lastProcessedBlock;
2814
- logger7.info("Subgraph catch-up starting", {
3141
+ logger8.info("Subgraph catch-up starting", {
2815
3142
  subgraph: subgraphName,
2816
3143
  from: startBlock,
2817
3144
  to: chainTip,
@@ -2827,7 +3154,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2827
3154
  let nextBatchPromise = batchConfig.prefetch ? source.loadBlockRange(currentHeight, prefetchedBatchEnd) : undefined;
2828
3155
  while (currentHeight <= chainTip) {
2829
3156
  if (!isCatchUpLeader()) {
2830
- logger7.info("Lost catch-up leadership, stopping catch-up", {
3157
+ logger8.info("Lost catch-up leadership, stopping catch-up", {
2831
3158
  subgraph: subgraphName,
2832
3159
  processed
2833
3160
  });
@@ -2835,7 +3162,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2835
3162
  }
2836
3163
  const currentRow = await getSubgraph(targetDb, subgraphName);
2837
3164
  if (!currentRow || currentRow.status !== "active") {
2838
- logger7.info("Subgraph status changed, stopping catch-up", {
3165
+ logger8.info("Subgraph status changed, stopping catch-up", {
2839
3166
  subgraph: subgraphName,
2840
3167
  status: currentRow?.status ?? "deleted"
2841
3168
  });
@@ -2864,7 +3191,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2864
3191
  blockData = (await source.loadBlockRange(height, height)).get(height);
2865
3192
  }
2866
3193
  if (!blockData) {
2867
- logger7.warn("Block missing during catch-up, deferring to next tick", {
3194
+ logger8.warn("Block missing during catch-up, deferring to next tick", {
2868
3195
  subgraph: subgraphName,
2869
3196
  blockHeight: height
2870
3197
  });
@@ -2884,12 +3211,12 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2884
3211
  });
2885
3212
  } catch (err) {
2886
3213
  if (err instanceof ReorgEpochChangedError) {
2887
- logger7.info("Reorg detected mid catch-up, aborting walk without writing further progress", { subgraph: subgraphName, blockHeight: height });
3214
+ logger8.info("Reorg detected mid catch-up, aborting walk without writing further progress", { subgraph: subgraphName, blockHeight: height });
2888
3215
  stopCatchup = true;
2889
3216
  break;
2890
3217
  }
2891
3218
  const errorMsg = err instanceof Error ? err.message : String(err);
2892
- logger7.error("Block processing failed persistently during catch-up", {
3219
+ logger8.error("Block processing failed persistently during catch-up", {
2893
3220
  subgraph: subgraphName,
2894
3221
  blockHeight: height,
2895
3222
  error: errorMsg
@@ -2908,7 +3235,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2908
3235
  }
2909
3236
  }
2910
3237
  if (processed % LOG_INTERVAL === 0) {
2911
- logger7.info("Subgraph catch-up progress", {
3238
+ logger8.info("Subgraph catch-up progress", {
2912
3239
  subgraph: subgraphName,
2913
3240
  processed,
2914
3241
  total: totalBlocks,
@@ -2924,7 +3251,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
2924
3251
  currentHeight = batchEnd + 1;
2925
3252
  }
2926
3253
  await stats.flush(targetDb);
2927
- logger7.info("Subgraph catch-up complete", {
3254
+ logger8.info("Subgraph catch-up complete", {
2928
3255
  subgraph: subgraphName,
2929
3256
  processed
2930
3257
  });
@@ -2941,14 +3268,14 @@ import {
2941
3268
  listSubgraphs,
2942
3269
  resolveSubgraphRawClient
2943
3270
  } from "@secondlayer/shared/db/queries/subgraphs";
2944
- import { logger as logger8 } from "@secondlayer/shared/logger";
3271
+ import { logger as logger9 } from "@secondlayer/shared/logger";
2945
3272
  import { sql as sql4 } from "kysely";
2946
3273
  async function handleSubgraphReorg(blockHeight, loadSubgraphDef) {
2947
3274
  const targetDb = getTargetDb3();
2948
3275
  const activeSubgraphs = (await listSubgraphs(targetDb)).filter((v) => v.status === "active");
2949
3276
  if (activeSubgraphs.length === 0)
2950
3277
  return;
2951
- logger8.info("Propagating reorg to subgraphs", {
3278
+ logger9.info("Propagating reorg to subgraphs", {
2952
3279
  blockHeight,
2953
3280
  subgraphCount: activeSubgraphs.length
2954
3281
  });
@@ -2965,7 +3292,7 @@ async function handleSubgraphReorg(blockHeight, loadSubgraphDef) {
2965
3292
  });
2966
3293
  });
2967
3294
  } catch (err) {
2968
- logger8.error("Subgraph reorg handling failed", {
3295
+ logger9.error("Subgraph reorg handling failed", {
2969
3296
  subgraph: sg.name,
2970
3297
  blockHeight,
2971
3298
  error: getErrorMessage2(err)
@@ -3003,7 +3330,7 @@ async function reorgOneSubgraph(sg, schema, blockHeight, loadSubgraphDef) {
3003
3330
  await tx.unsafe(`DELETE FROM "${schemaName}"."_journal" WHERE block_height >= $1`, [blockHeight]);
3004
3331
  });
3005
3332
  } else {
3006
- logger8.warn("Subgraph has no revert journal — falling back to height delete (accumulator rows may lose history)", { subgraph: sg.name, blockHeight });
3333
+ logger9.warn("Subgraph has no revert journal — falling back to height delete (accumulator rows may lose history)", { subgraph: sg.name, blockHeight });
3007
3334
  for (const tableName of tableNames) {
3008
3335
  await client.unsafe(`DELETE FROM "${schemaName}"."${tableName}" WHERE "_block_height" >= $1`, [blockHeight]);
3009
3336
  }
@@ -3046,7 +3373,7 @@ async function reorgOneSubgraph(sg, schema, blockHeight, loadSubgraphDef) {
3046
3373
  }).as("row_pk"),
3047
3374
  eb2.val("pending").as("status")
3048
3375
  ]).where("subgraph_name", "=", sg.name).where("table_name", "=", tableName).where("status", "=", "active")).onConflict((oc) => oc.columns(["subscription_id", "dedup_key"]).doNothing()).execute().catch((err) => {
3049
- logger8.error("Failed to emit revert event for subscriptions", {
3376
+ logger9.error("Failed to emit revert event for subscriptions", {
3050
3377
  event: "reorg_revert_emit_dropped",
3051
3378
  subgraph: sg.name,
3052
3379
  table: tableName,
@@ -3055,14 +3382,14 @@ async function reorgOneSubgraph(sg, schema, blockHeight, loadSubgraphDef) {
3055
3382
  });
3056
3383
  });
3057
3384
  }
3058
- logger8.info("Subgraph reorg cleanup done", {
3385
+ logger9.info("Subgraph reorg cleanup done", {
3059
3386
  subgraph: sg.name,
3060
3387
  blockHeight,
3061
3388
  tablesAffected: Object.keys(revertedByTable).length
3062
3389
  });
3063
3390
  const def = await loadSubgraphDef(sg);
3064
3391
  await processBlock(def, sg.name, blockHeight, { reorgRewind: true });
3065
- logger8.info("Subgraph reorg reprocessed", {
3392
+ logger9.info("Subgraph reorg reprocessed", {
3066
3393
  subgraph: sg.name,
3067
3394
  blockHeight
3068
3395
  });
@@ -3071,5 +3398,5 @@ export {
3071
3398
  handleSubgraphReorg
3072
3399
  };
3073
3400
 
3074
- //# debugId=314C75DB8B9D518F64756E2164756E21
3401
+ //# debugId=8717C174F5E08EB264756E2164756E21
3075
3402
  //# sourceMappingURL=reorg.js.map