@secondlayer/subgraphs 0.7.2 → 0.8.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.
@@ -6,8 +6,8 @@
6
6
  "import type { Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Kysely, type Transaction, sql } from \"kysely\";\nimport type { SubgraphSchema } from \"../types.ts\";\n\ntype AnyDb = Kysely<Database> | Transaction<Database>;\n\ninterface WriteOp {\n\tkind: \"insert\" | \"update\" | \"delete\";\n\ttable: string;\n\tdata: Record<string, unknown>;\n\t/** For update: SET clause */\n\tset?: Record<string, unknown>;\n}\n\nexport interface BlockMeta {\n\theight: number;\n\thash: string;\n\ttimestamp: number;\n\tburnBlockHeight: number;\n}\n\nexport interface TxMeta {\n\ttxId: string;\n\tsender: string;\n\ttype: string;\n\tstatus: string;\n}\n\n/** Validate that a column name is safe for SQL identifiers */\nfunction validateColumnName(name: string): void {\n\tif (!/^[a-z_][a-z0-9_]*$/i.test(name)) {\n\t\tthrow new Error(`Invalid column name: ${name}`);\n\t}\n}\n\n/**\n * Runtime context passed to subgraph handlers.\n * Batches writes and flushes them atomically at the end of a block.\n * Reads execute immediately against the DB (pre-flush state).\n */\nexport class SubgraphContext {\n\treadonly block: BlockMeta;\n\tprivate _tx: TxMeta;\n\tprivate readonly db: AnyDb;\n\tprivate readonly pgSchemaName: string;\n\tprivate readonly subgraphSchema: SubgraphSchema;\n\tprivate readonly ops: WriteOp[] = [];\n\n\tconstructor(\n\t\tdb: AnyDb,\n\t\tpgSchemaName: string,\n\t\tsubgraphSchema: SubgraphSchema,\n\t\tblock: BlockMeta,\n\t\ttx: TxMeta,\n\t) {\n\t\tthis.db = db;\n\t\tthis.pgSchemaName = pgSchemaName;\n\t\tthis.subgraphSchema = subgraphSchema;\n\t\tthis.block = block;\n\t\tthis._tx = tx;\n\t}\n\n\tget tx(): TxMeta {\n\t\treturn this._tx;\n\t}\n\n\t/** Update the current transaction context (used by runner between events) */\n\tsetTx(tx: TxMeta): void {\n\t\tthis._tx = tx;\n\t}\n\n\t// --- Write operations (batched) ---\n\n\tinsert(table: string, row: Record<string, unknown>): void {\n\t\tthis.validateTable(table);\n\t\tthis.ops.push({ kind: \"insert\", table, data: row });\n\t}\n\n\tupdate(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t\tset: Record<string, unknown>,\n\t): void {\n\t\tthis.validateTable(table);\n\t\tthis.ops.push({ kind: \"update\", table, data: where, set });\n\t}\n\n\tupsert(\n\t\ttable: string,\n\t\tkey: Record<string, unknown>,\n\t\trow: Record<string, unknown>,\n\t): void {\n\t\tthis.validateTable(table);\n\t\tconst tableDef = this.subgraphSchema[table]!;\n\t\tconst keyColumns = Object.keys(key);\n\n\t\t// Check if there's a matching uniqueKeys constraint\n\t\tconst hasUniqueConstraint = tableDef.uniqueKeys?.some(\n\t\t\t(uk) =>\n\t\t\t\tuk.length === keyColumns.length &&\n\t\t\t\tuk.every((c) => keyColumns.includes(c)),\n\t\t);\n\n\t\tif (hasUniqueConstraint) {\n\t\t\t// Use ON CONFLICT for proper upsert\n\t\t\tthis.ops.push({\n\t\t\t\tkind: \"insert\",\n\t\t\t\ttable,\n\t\t\t\tdata: { ...key, ...row, _upsert_keys: keyColumns },\n\t\t\t});\n\t\t} else {\n\t\t\t// Fallback: log warning, use findOne + conditional insert/update\n\t\t\tlogger.warn(\n\t\t\t\t\"upsert called without matching uniqueKeys constraint, using fallback\",\n\t\t\t\t{\n\t\t\t\t\ttable,\n\t\t\t\t\tkeys: keyColumns,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.ops.push({\n\t\t\t\tkind: \"insert\",\n\t\t\t\ttable,\n\t\t\t\tdata: {\n\t\t\t\t\t...key,\n\t\t\t\t\t...row,\n\t\t\t\t\t_upsert_fallback_keys: keyColumns,\n\t\t\t\t\t_upsert_fallback_set: row,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tdelete(table: string, where: Record<string, unknown>): void {\n\t\tthis.validateTable(table);\n\t\tthis.ops.push({ kind: \"delete\", table, data: where });\n\t}\n\n\t// --- Read operations (immediate) ---\n\n\tasync findOne(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t): Promise<Record<string, unknown> | null> {\n\t\tthis.validateTable(table);\n\t\tconst qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n\t\tconst { clause } = buildWhereClause(where);\n\t\tconst query = `SELECT * FROM ${qualifiedTable} WHERE ${clause} LIMIT 1`;\n\t\tconst { rows } = await sql.raw(query).execute(this.db);\n\t\tconst row = (rows as Record<string, unknown>[])[0] ?? null;\n\t\treturn row ? this.coerceRow(table, row) : null;\n\t}\n\n\tasync findMany(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t): Promise<Record<string, unknown>[]> {\n\t\tthis.validateTable(table);\n\t\tconst qualifiedTable = `\"${this.pgSchemaName}\".\"${table}\"`;\n\t\tconst { clause } = buildWhereClause(where);\n\t\tconst query = `SELECT * FROM ${qualifiedTable} WHERE ${clause}`;\n\t\tconst { rows } = await sql.raw(query).execute(this.db);\n\t\treturn (rows as Record<string, unknown>[]).map((r) =>\n\t\t\tthis.coerceRow(table, r),\n\t\t);\n\t}\n\n\t/** Coerce string values from Postgres back to BigInt for uint/int columns */\n\tprivate coerceRow(\n\t\ttable: string,\n\t\trow: Record<string, unknown>,\n\t): Record<string, unknown> {\n\t\tconst tableDef = this.subgraphSchema[table];\n\t\tif (!tableDef) return row;\n\t\tconst result = { ...row };\n\t\tfor (const [col, def] of Object.entries(tableDef.columns)) {\n\t\t\tif (\n\t\t\t\t(def.type === \"uint\" || def.type === \"int\") &&\n\t\t\t\ttypeof result[col] === \"string\"\n\t\t\t) {\n\t\t\t\tresult[col] = BigInt(result[col] as string);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t// --- Flush ---\n\n\t/** Number of pending write operations */\n\tget pendingOps(): number {\n\t\treturn this.ops.length;\n\t}\n\n\t/**\n\t * Execute all batched writes in a single transaction.\n\t * Auto-populates _block_height, _tx_id, _created_at on inserts.\n\t */\n\tasync flush(): Promise<number> {\n\t\tif (this.ops.length === 0) return 0;\n\n\t\tconst opsToFlush = [...this.ops];\n\t\tthis.ops.length = 0;\n\n\t\tconst statements = this.buildStatements(opsToFlush);\n\n\t\t// If db is already a transaction, execute directly\n\t\tif (\"isTransaction\" in this.db) {\n\t\t\tfor (const stmt of statements) {\n\t\t\t\tawait sql.raw(stmt).execute(this.db);\n\t\t\t}\n\t\t} else {\n\t\t\tawait (this.db as Kysely<Database>).transaction().execute(async (tx) => {\n\t\t\t\tfor (const stmt of statements) {\n\t\t\t\t\tawait sql.raw(stmt).execute(tx);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn opsToFlush.length;\n\t}\n\n\t/** Prepare a single insert row, returning its data, columns, upsert key for batching. */\n\tprivate prepareInsert(op: WriteOp): {\n\t\tdata: Record<string, unknown>;\n\t\tcols: string[];\n\t\tvals: string[];\n\t\tupsertKeys: string[] | undefined;\n\t\tbatchKey: string;\n\t} {\n\t\tconst upsertKeys = op.data._upsert_keys as string[] | undefined;\n\t\tconst data = { ...op.data };\n\t\tdelete data._upsert_keys;\n\t\tdelete data._upsert_fallback_keys;\n\t\tdelete data._upsert_fallback_set;\n\n\t\tdata._block_height = this.block.height;\n\t\tdata._tx_id = this._tx.txId;\n\t\tdata._created_at = \"NOW()\";\n\n\t\tconst cols = Object.keys(data);\n\t\tcols.forEach(validateColumnName);\n\t\tconst vals = cols.map((c) =>\n\t\t\tdata[c] === \"NOW()\" ? \"NOW()\" : escapeLiteral(data[c]),\n\t\t);\n\n\t\t// Batch key: table + sorted columns + upsert key signature (spread to avoid mutating cols)\n\t\tconst batchKey = `${op.table}:${[...cols].sort().join(\",\")}:${upsertKeys ? [...upsertKeys].sort().join(\",\") : \"\"}`;\n\n\t\treturn { data, cols, vals, upsertKeys, batchKey };\n\t}\n\n\t/** Build SQL statements from write ops, batching compatible INSERTs. */\n\tprivate buildStatements(ops: WriteOp[]): string[] {\n\t\tconst statements: string[] = [];\n\n\t\t// Group consecutive inserts by batch key\n\t\ttype InsertBatch = {\n\t\t\ttable: string;\n\t\t\tcols: string[];\n\t\t\trows: string[][];\n\t\t\tupsertKeys: string[] | undefined;\n\t\t};\n\n\t\tlet currentBatch: InsertBatch | null = null;\n\t\tlet currentBatchKey = \"\";\n\n\t\tconst flushInsertBatch = () => {\n\t\t\tif (!currentBatch) return;\n\t\t\tconst qualifiedTable = `\"${this.pgSchemaName}\".\"${currentBatch.table}\"`;\n\t\t\tconst colList = currentBatch.cols.map((c) => `\"${c}\"`).join(\", \");\n\n\t\t\t// Deduplicate by upsert key — last row wins (Postgres rejects duplicate keys in one INSERT)\n\t\t\tlet rows = currentBatch.rows;\n\t\t\tif (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {\n\t\t\t\tconst keyIndices = currentBatch.upsertKeys.map((k) =>\n\t\t\t\t\tcurrentBatch!.cols.indexOf(k),\n\t\t\t\t);\n\t\t\t\tconst seen = new Map<string, number>();\n\t\t\t\tfor (let i = 0; i < rows.length; i++) {\n\t\t\t\t\tconst key = keyIndices.map((ki) => rows[i][ki]).join(\"\\0\");\n\t\t\t\t\tseen.set(key, i);\n\t\t\t\t}\n\t\t\t\tif (seen.size < rows.length) {\n\t\t\t\t\trows = Array.from(seen.values()).map((i) => rows[i]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst valuesList = rows.map((r) => `(${r.join(\", \")})`).join(\", \");\n\t\t\tlet stmt = `INSERT INTO ${qualifiedTable} (${colList}) VALUES ${valuesList}`;\n\n\t\t\tif (currentBatch.upsertKeys && currentBatch.upsertKeys.length > 0) {\n\t\t\t\tconst updateCols = currentBatch.cols.filter(\n\t\t\t\t\t(c) => !currentBatch!.upsertKeys!.includes(c) && !c.startsWith(\"_\"),\n\t\t\t\t);\n\t\t\t\tif (updateCols.length > 0) {\n\t\t\t\t\tconst setClauses = updateCols.map((c) => `\"${c}\" = EXCLUDED.\"${c}\"`);\n\t\t\t\t\tstmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO UPDATE SET ${setClauses.join(\", \")}`;\n\t\t\t\t} else {\n\t\t\t\t\tstmt += ` ON CONFLICT (${currentBatch.upsertKeys.map((k) => `\"${k}\"`).join(\", \")}) DO NOTHING`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstatements.push(stmt);\n\t\t\tcurrentBatch = null;\n\t\t\tcurrentBatchKey = \"\";\n\t\t};\n\n\t\tfor (const op of ops) {\n\t\t\tconst qualifiedTable = `\"${this.pgSchemaName}\".\"${op.table}\"`;\n\n\t\t\tif (op.kind === \"insert\") {\n\t\t\t\tconst { cols, vals, upsertKeys, batchKey } = this.prepareInsert(op);\n\n\t\t\t\tif (batchKey === currentBatchKey && currentBatch) {\n\t\t\t\t\t// Same table + columns + upsert key — append to batch\n\t\t\t\t\tcurrentBatch.rows.push(vals);\n\t\t\t\t} else {\n\t\t\t\t\t// Different batch — flush previous and start new\n\t\t\t\t\tflushInsertBatch();\n\t\t\t\t\tcurrentBatch = { table: op.table, cols, rows: [vals], upsertKeys };\n\t\t\t\t\tcurrentBatchKey = batchKey;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Non-insert — flush any pending insert batch first\n\t\t\t\tflushInsertBatch();\n\n\t\t\t\tif (op.kind === \"update\") {\n\t\t\t\t\tconst setEntries = Object.entries(op.set!);\n\t\t\t\t\tsetEntries.forEach(([k]) => validateColumnName(k));\n\t\t\t\t\tconst setClauses = setEntries.map(\n\t\t\t\t\t\t([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`,\n\t\t\t\t\t);\n\t\t\t\t\tconst { clause } = buildWhereClause(op.data);\n\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t`UPDATE ${qualifiedTable} SET ${setClauses.join(\", \")} WHERE ${clause}`,\n\t\t\t\t\t);\n\t\t\t\t} else if (op.kind === \"delete\") {\n\t\t\t\t\tconst { clause } = buildWhereClause(op.data);\n\t\t\t\t\tstatements.push(`DELETE FROM ${qualifiedTable} WHERE ${clause}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flush any remaining insert batch\n\t\tflushInsertBatch();\n\n\t\treturn statements;\n\t}\n\n\tprivate validateTable(table: string): void {\n\t\tif (!this.subgraphSchema[table]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table \"${table}\" not found in subgraph schema. Available: [${Object.keys(this.subgraphSchema).join(\", \")}]`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// --- Helpers ---\n\nfunction escapeLiteral(value: unknown): string {\n\tif (value === null || value === undefined) return \"NULL\";\n\tif (typeof value === \"number\" || typeof value === \"bigint\")\n\t\treturn String(value);\n\tif (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n\tif (typeof value === \"object\")\n\t\treturn `'${JSON.stringify(value).replace(/'/g, \"''\")}'::jsonb`;\n\t// String — escape single quotes\n\treturn `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\nfunction buildWhereClause(where: Record<string, unknown>): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tconst entries = Object.entries(where);\n\tif (entries.length === 0) return { clause: \"TRUE\", values: [] };\n\n\tentries.forEach(([k]) => validateColumnName(k));\n\tconst parts = entries.map(([k, v]) => `\"${k}\" = ${escapeLiteral(v)}`);\n\treturn { clause: parts.join(\" AND \"), values: [] };\n}\n",
7
7
  "import { cvToJSON, deserializeCV } from \"@secondlayer/stacks/clarity\";\n\n/**\n * Decode a hex-encoded Clarity value to a JS object.\n * Returns original value on failure.\n */\nexport function decodeClarityValue(hex: string): unknown {\n\ttry {\n\t\tconst cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n\t\tconst cv = deserializeCV(cleanHex);\n\t\treturn cvToJSON(cv);\n\t} catch {\n\t\treturn hex;\n\t}\n}\n\n/**\n * Recursively decode all hex-encoded Clarity values in an object.\n * Any string starting with \"0x\" and longer than 10 chars is attempted.\n */\nexport function decodeEventData(data: unknown): unknown {\n\tif (typeof data === \"string\" && data.startsWith(\"0x\") && data.length > 10) {\n\t\treturn decodeClarityValue(data);\n\t}\n\n\tif (Array.isArray(data)) {\n\t\treturn data.map(decodeEventData);\n\t}\n\n\tif (typeof data === \"object\" && data !== null) {\n\t\tconst decoded: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tdecoded[key] = decodeEventData(value);\n\t\t}\n\t\treturn decoded;\n\t}\n\n\treturn data;\n}\n\n/**\n * Decode function args array (hex-encoded Clarity values).\n */\nexport function decodeFunctionArgs(args: string[]): unknown[] {\n\treturn args.map(decodeClarityValue);\n}\n",
8
8
  "import { getErrorMessage } from \"@secondlayer/shared\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { decodeEventData } from \"./clarity.ts\";\nimport type { SubgraphContext } from \"./context.ts\";\nimport type { MatchedTx } from \"./source-matcher.ts\";\n\n/** Max consecutive handler errors before marking subgraph as error */\nconst DEFAULT_ERROR_THRESHOLD = 50;\n\nexport interface RunResult {\n\tprocessed: number;\n\terrors: number;\n}\n\n/**\n * Resolve the handler for a matched tx.\n * Looks up by sourceKey first, then falls back to \"*\" catch-all.\n */\nfunction resolveHandler(handlers: SubgraphDefinition[\"handlers\"], key: string) {\n\treturn handlers[key] ?? handlers[\"*\"] ?? null;\n}\n\n/**\n * Run a subgraph's keyed handlers against all matched transactions/events.\n *\n * Each MatchedTx carries a sourceKey from the matcher. The runner looks up\n * the corresponding handler in subgraph.handlers, falling back to \"*\".\n *\n * Does NOT flush — caller is responsible for flushing ctx after run.\n */\nexport async function runHandlers(\n\tsubgraph: SubgraphDefinition,\n\tmatched: MatchedTx[],\n\tctx: SubgraphContext,\n\topts?: { errorThreshold?: number },\n): Promise<RunResult> {\n\tlet processed = 0;\n\tlet errors = 0;\n\tconst threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;\n\n\tfor (const { tx, events, sourceKey } of matched) {\n\t\tconst handler = resolveHandler(subgraph.handlers, sourceKey);\n\t\tif (!handler) {\n\t\t\tlogger.warn(\"No handler found for source key\", {\n\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\tsourceKey,\n\t\t\t\ttxId: tx.tx_id,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tctx.setTx({\n\t\t\ttxId: tx.tx_id,\n\t\t\tsender: tx.sender,\n\t\t\ttype: tx.type,\n\t\t\tstatus: tx.status,\n\t\t});\n\n\t\t// If no events but tx matched, call handler with tx-level data\n\t\tif (events.length === 0) {\n\t\t\ttry {\n\t\t\t\tconst txPayload: Record<string, unknown> = {\n\t\t\t\t\ttx: {\n\t\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\t\tsender: tx.sender,\n\t\t\t\t\t\ttype: tx.type,\n\t\t\t\t\t\tstatus: tx.status,\n\t\t\t\t\t\tcontractId: tx.contract_id,\n\t\t\t\t\t\tfunctionName: tx.function_name,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tawait handler(txPayload, ctx);\n\t\t\t\tprocessed++;\n\t\t\t} catch (err) {\n\t\t\t\terrors++;\n\t\t\t\tlogger.error(\"Subgraph handler error\", {\n\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\tsourceKey,\n\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const event of events) {\n\t\t\tif (errors >= threshold) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Subgraph error threshold reached, skipping remaining events\",\n\t\t\t\t\t{\n\t\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\t\terrors,\n\t\t\t\t\t\tthreshold,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn { processed, errors };\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst decoded = decodeEventData(event.data) as Record<string, unknown>;\n\t\t\t\tconst eventPayload: Record<string, unknown> = {\n\t\t\t\t\t...decoded,\n\t\t\t\t\t_eventId: event.id,\n\t\t\t\t\t_eventType: event.type,\n\t\t\t\t\t_eventIndex: event.event_index,\n\t\t\t\t\ttx: {\n\t\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\t\tsender: tx.sender,\n\t\t\t\t\t\ttype: tx.type,\n\t\t\t\t\t\tstatus: tx.status,\n\t\t\t\t\t\tcontractId: tx.contract_id,\n\t\t\t\t\t\tfunctionName: tx.function_name,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tawait handler(eventPayload, ctx);\n\t\t\t\tprocessed++;\n\t\t\t} catch (err) {\n\t\t\t\terrors++;\n\t\t\t\tlogger.error(\"Subgraph handler error\", {\n\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\tsourceKey,\n\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\teventId: event.id,\n\t\t\t\t\teventType: event.type,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { processed, errors };\n}\n",
9
- "import { type SubgraphSource, sourceKey } from \"../types.ts\";\n\nexport interface MatchedTx {\n\ttx: {\n\t\ttx_id: string;\n\t\ttype: string;\n\t\tsender: string;\n\t\tstatus: string;\n\t\tcontract_id?: string | null;\n\t\tfunction_name?: string | null;\n\t};\n\tevents: {\n\t\tid: string;\n\t\ttx_id: string;\n\t\ttype: string;\n\t\tevent_index: number;\n\t\tdata: unknown;\n\t}[];\n\t/** Which source produced this match — used for handler dispatch */\n\tsourceKey: string;\n}\n\n/**\n * Check if a string matches a pattern with `*` wildcard support.\n */\nfunction matchPattern(value: string, pattern: string): boolean {\n\tif (!pattern.includes(\"*\")) return value === pattern;\n\tconst regex = pattern\n\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t.replace(/\\*/g, \".*\");\n\treturn new RegExp(`^${regex}$`).test(value);\n}\n\ntype TxRecord = {\n\ttx_id: string;\n\ttype: string;\n\tsender: string;\n\tstatus: string;\n\tcontract_id?: string | null;\n\tfunction_name?: string | null;\n};\ntype EventRecord = {\n\tid: string;\n\ttx_id: string;\n\ttype: string;\n\tevent_index: number;\n\tdata: unknown;\n};\n\n/**\n * Match a single source against transactions and events.\n */\nfunction matchSource(\n\tsource: SubgraphSource,\n\ttransactions: TxRecord[],\n\teventsByTx: Map<string, EventRecord[]>,\n): MatchedTx[] {\n\tconst results: MatchedTx[] = [];\n\tconst key = sourceKey(source);\n\n\tfor (const tx of transactions) {\n\t\t// Type-based matching (e.g., token_transfer → matches tx.type)\n\t\tif (source.type) {\n\t\t\tif (!matchPattern(tx.type, source.type)) continue;\n\n\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\n\t\t\t// Collect all events for this tx (type-based sources match the whole tx)\n\t\t\tlet matchedEvents = txEvents;\n\n\t\t\t// minAmount filter — check events with an amount field\n\t\t\tif (source.minAmount !== undefined) {\n\t\t\t\tconst amountEvents = matchedEvents.filter((e) => {\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst rawAmount = data?.amount as string | number | undefined;\n\t\t\t\t\tif (rawAmount === undefined) return false;\n\t\t\t\t\tconst amount = BigInt(rawAmount);\n\t\t\t\t\treturn amount >= source.minAmount!;\n\t\t\t\t});\n\t\t\t\tif (amountEvents.length === 0) continue;\n\t\t\t\tmatchedEvents = amountEvents;\n\t\t\t}\n\n\t\t\tresults.push({ tx, events: matchedEvents, sourceKey: key });\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Contract-based matching\n\t\tif (source.contract) {\n\t\t\tconst txContractMatch =\n\t\t\t\ttx.contract_id && matchPattern(tx.contract_id, source.contract);\n\n\t\t\t// Function filter\n\t\t\tif (source.function && tx.function_name) {\n\t\t\t\tif (!matchPattern(tx.function_name, source.function)) continue;\n\t\t\t} else if (source.function && !tx.function_name) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\tlet matchedEvents = txEvents;\n\n\t\t\tif (!txContractMatch) {\n\t\t\t\t// Check if any events match the contract\n\t\t\t\tmatchedEvents = txEvents.filter((e) => {\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst contractIdentifier = data?.contract_identifier as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tcontractIdentifier &&\n\t\t\t\t\t\tmatchPattern(contractIdentifier, source.contract!)\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tif (matchedEvents.length === 0) continue;\n\t\t\t}\n\n\t\t\t// Event type / topic filter\n\t\t\tif (source.event) {\n\t\t\t\tmatchedEvents = matchedEvents.filter((e) => {\n\t\t\t\t\tif (matchPattern(e.type, source.event!)) return true;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst topic = data?.topic as string | undefined;\n\t\t\t\t\treturn topic ? matchPattern(topic, source.event!) : false;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (txContractMatch || matchedEvents.length > 0) {\n\t\t\t\tresults.push({ tx, events: matchedEvents, sourceKey: key });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Match all sources against a block's transactions and events.\n * Deduplicates by (txId, sourceKey) — each handler key fires at most once per tx.\n */\nexport function matchSources(\n\tsources: SubgraphSource[],\n\ttransactions: TxRecord[],\n\tevents: EventRecord[],\n): MatchedTx[] {\n\t// Index events by txId\n\tconst eventsByTx = new Map<string, EventRecord[]>();\n\tfor (const event of events) {\n\t\tconst list = eventsByTx.get(event.tx_id) ?? [];\n\t\tlist.push(event);\n\t\teventsByTx.set(event.tx_id, list);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst results: MatchedTx[] = [];\n\n\tfor (const source of sources) {\n\t\tconst matches = matchSource(source, transactions, eventsByTx);\n\t\tfor (const match of matches) {\n\t\t\tconst dedupeKey = `${match.tx.tx_id}:${match.sourceKey}`;\n\t\t\tif (!seen.has(dedupeKey)) {\n\t\t\t\tseen.add(dedupeKey);\n\t\t\t\tresults.push(match);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n",
10
- "import { type Database, getDb } from \"@secondlayer/shared/db\";\nimport {\n\trecordSubgraphProcessed,\n\tupdateSubgraphStatus,\n} from \"@secondlayer/shared/db/queries/subgraphs\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Transaction, sql } from \"kysely\";\nimport { pgSchemaName } from \"../schema/utils.ts\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { type BlockMeta, SubgraphContext, type TxMeta } from \"./context.ts\";\nimport { runHandlers } from \"./runner.ts\";\nimport { matchSources } from \"./source-matcher.ts\";\n\n// Cache schema_name per subgraph to avoid per-block DB lookups\nconst schemaNameCache = new Map<string, string>();\n\nexport interface ProcessBlockTiming {\n\ttotalMs: number;\n\thandlerMs: number;\n\tflushMs: number;\n}\n\nexport interface ProcessBlockResult {\n\tblockHeight: number;\n\tmatched: number;\n\tprocessed: number;\n\terrors: number;\n\tskipped: boolean;\n\ttiming?: ProcessBlockTiming;\n}\n\n/**\n * Process a single block through a single subgraph's pipeline.\n *\n * Flow:\n * 1. Load block + txs + events from DB\n * 2. Run source matcher\n * 3. Run handlers with SubgraphContext\n * 4. Flush context (commit writes atomically)\n * 5. Update subgraph.last_processed_block\n */\nexport interface PreloadedBlockData {\n\tblock: import(\"@secondlayer/shared/db\").Block;\n\ttxs: import(\"@secondlayer/shared/db\").Transaction[];\n\tevents: import(\"@secondlayer/shared/db\").Event[];\n}\n\nexport interface ProcessBlockOptions {\n\t/** Skip updating last_processed_block in DB (reindex batches this externally). */\n\tskipProgressUpdate?: boolean;\n\t/** Pre-loaded block data — skips DB reads when provided (used by batch catch-up). */\n\tpreloaded?: PreloadedBlockData;\n}\n\nexport async function processBlock(\n\tsubgraph: SubgraphDefinition,\n\tsubgraphName: string,\n\tblockHeight: number,\n\topts?: ProcessBlockOptions,\n): Promise<ProcessBlockResult> {\n\tconst db = getDb();\n\tconst blockStart = performance.now();\n\tconst result: ProcessBlockResult = {\n\t\tblockHeight,\n\t\tmatched: 0,\n\t\tprocessed: 0,\n\t\terrors: 0,\n\t\tskipped: false,\n\t};\n\n\t// 1. Load block (use pre-loaded data if available, otherwise fetch from DB)\n\tlet block, txs, evts;\n\tif (opts?.preloaded) {\n\t\tblock = opts.preloaded.block;\n\t\ttxs = opts.preloaded.txs;\n\t\tevts = opts.preloaded.events;\n\t} else {\n\t\tblock = await db\n\t\t\t.selectFrom(\"blocks\")\n\t\t\t.selectAll()\n\t\t\t.where(\"height\", \"=\", blockHeight)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!block) {\n\t\t\tlogger.warn(\"Block not found for subgraph processing\", {\n\t\t\t\tsubgraph: subgraphName,\n\t\t\t\tblockHeight,\n\t\t\t});\n\t\t\tresult.skipped = true;\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!block.canonical) {\n\t\t\tlogger.debug(\"Skipping non-canonical block\", {\n\t\t\t\tsubgraph: subgraphName,\n\t\t\t\tblockHeight,\n\t\t\t});\n\t\t\tresult.skipped = true;\n\t\t\treturn result;\n\t\t}\n\n\t\t// 2. Load txs + events\n\t\ttxs = await db\n\t\t\t.selectFrom(\"transactions\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \"=\", blockHeight)\n\t\t\t.execute();\n\n\t\tevts = await db\n\t\t\t.selectFrom(\"events\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \"=\", blockHeight)\n\t\t\t.execute();\n\t}\n\n\t// 3. Match source\n\tconst matched = matchSources(subgraph.sources, txs, evts);\n\tresult.matched = matched.length;\n\n\tif (matched.length === 0) {\n\t\tif (!opts?.skipProgressUpdate) {\n\t\t\tawait updateSubgraphStatus(db, subgraphName, \"active\", blockHeight);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// 4. Create context and run handlers\n\t// Use cached schema_name (fetched once per subgraph, not per block)\n\tlet schemaName = schemaNameCache.get(subgraphName);\n\tif (!schemaName) {\n\t\tconst subgraphRecord = await db\n\t\t\t.selectFrom(\"subgraphs\")\n\t\t\t.select(\"schema_name\")\n\t\t\t.where(\"name\", \"=\", subgraphName)\n\t\t\t.executeTakeFirst();\n\t\tschemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);\n\t\tschemaNameCache.set(subgraphName, schemaName);\n\t}\n\tconst blockMeta: BlockMeta = {\n\t\theight: block.height,\n\t\thash: block.hash,\n\t\ttimestamp: block.timestamp,\n\t\tburnBlockHeight: block.burn_block_height,\n\t};\n\tconst initialTx: TxMeta = {\n\t\ttxId: \"\",\n\t\tsender: \"\",\n\t\ttype: \"\",\n\t\tstatus: \"\",\n\t};\n\n\t// Wrap entire block processing in a single transaction\n\tlet handlerMs = 0;\n\tlet flushMs = 0;\n\n\tawait db.transaction().execute(async (tx: Transaction<Database>) => {\n\t\tconst ctx = new SubgraphContext(\n\t\t\ttx,\n\t\t\tschemaName,\n\t\t\tsubgraph.schema,\n\t\t\tblockMeta,\n\t\t\tinitialTx,\n\t\t);\n\n\t\tconst handlerStart = performance.now();\n\t\tconst runResult = await runHandlers(subgraph, matched, ctx);\n\t\thandlerMs = performance.now() - handlerStart;\n\n\t\tresult.processed = runResult.processed;\n\t\tresult.errors = runResult.errors;\n\n\t\t// 5. Flush writes\n\t\tif (ctx.pendingOps > 0) {\n\t\t\tconst flushStart = performance.now();\n\t\t\tawait ctx.flush();\n\t\t\tflushMs = performance.now() - flushStart;\n\t\t}\n\n\t\t// 6. Update progress + health metrics (same transaction)\n\t\tif (!opts?.skipProgressUpdate) {\n\t\t\tconst status =\n\t\t\t\trunResult.errors > 0 && runResult.processed === 0 ? \"error\" : \"active\";\n\t\t\tawait updateSubgraphStatus(tx, subgraphName, status, blockHeight);\n\t\t}\n\n\t\tif (\n\t\t\t!opts?.skipProgressUpdate &&\n\t\t\t(runResult.processed > 0 || runResult.errors > 0)\n\t\t) {\n\t\t\tconst lastError =\n\t\t\t\trunResult.errors > 0\n\t\t\t\t\t? `${runResult.errors} error(s) at block ${blockHeight}`\n\t\t\t\t\t: undefined;\n\t\t\tawait recordSubgraphProcessed(\n\t\t\t\ttx,\n\t\t\t\tsubgraphName,\n\t\t\t\trunResult.processed,\n\t\t\t\trunResult.errors,\n\t\t\t\tlastError,\n\t\t\t);\n\t\t}\n\t});\n\n\tconst totalMs = performance.now() - blockStart;\n\tresult.timing = {\n\t\ttotalMs: Math.round(totalMs),\n\t\thandlerMs: Math.round(handlerMs),\n\t\tflushMs: Math.round(flushMs),\n\t};\n\n\t// 7. Row count warning — sample every 1000 blocks\n\tif (blockHeight % 1000 === 0) {\n\t\ttry {\n\t\t\tconst tables = Object.keys(subgraph.schema);\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst { rows } = await sql\n\t\t\t\t\t.raw(`SELECT COUNT(*) as count FROM \"${schemaName}\".\"${table}\"`)\n\t\t\t\t\t.execute(db);\n\t\t\t\tconst count = Number((rows[0] as Record<string, unknown>).count);\n\t\t\t\tif (count >= 10_000_000) {\n\t\t\t\t\tlogger.warn(\"Subgraph table exceeds 10M rows\", {\n\t\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\t\ttable,\n\t\t\t\t\t\tcount,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Table may not exist yet\n\t\t}\n\t}\n\n\treturn result;\n}\n",
9
+ "import { type SubgraphSource, sourceKey } from \"../types.ts\";\n\nexport interface MatchedTx {\n\ttx: {\n\t\ttx_id: string;\n\t\ttype: string;\n\t\tsender: string;\n\t\tstatus: string;\n\t\tcontract_id?: string | null;\n\t\tfunction_name?: string | null;\n\t};\n\tevents: {\n\t\tid: string;\n\t\ttx_id: string;\n\t\ttype: string;\n\t\tevent_index: number;\n\t\tdata: unknown;\n\t}[];\n\t/** Which source produced this match — used for handler dispatch */\n\tsourceKey: string;\n}\n\n/**\n * Check if a string matches a pattern with `*` wildcard support.\n * Compiled RegExp objects are cached to avoid recompilation on every call.\n */\nconst patternCache = new Map<string, RegExp>();\n\nfunction matchPattern(value: string, pattern: string): boolean {\n\tif (!pattern.includes(\"*\")) return value === pattern;\n\tlet re = patternCache.get(pattern);\n\tif (!re) {\n\t\tconst regex = pattern\n\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t.replace(/\\*/g, \".*\");\n\t\tre = new RegExp(`^${regex}$`);\n\t\tpatternCache.set(pattern, re);\n\t}\n\treturn re.test(value);\n}\n\ntype TxRecord = {\n\ttx_id: string;\n\ttype: string;\n\tsender: string;\n\tstatus: string;\n\tcontract_id?: string | null;\n\tfunction_name?: string | null;\n};\ntype EventRecord = {\n\tid: string;\n\ttx_id: string;\n\ttype: string;\n\tevent_index: number;\n\tdata: unknown;\n};\n\n/**\n * Match a single source against transactions and events.\n */\nfunction matchSource(\n\tsource: SubgraphSource,\n\ttransactions: TxRecord[],\n\teventsByTx: Map<string, EventRecord[]>,\n): MatchedTx[] {\n\tconst results: MatchedTx[] = [];\n\tconst key = sourceKey(source);\n\n\tfor (const tx of transactions) {\n\t\t// Type-based matching (e.g., token_transfer → matches tx.type)\n\t\tif (source.type) {\n\t\t\tif (!matchPattern(tx.type, source.type)) continue;\n\n\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\n\t\t\t// Collect all events for this tx (type-based sources match the whole tx)\n\t\t\tlet matchedEvents = txEvents;\n\n\t\t\t// minAmount filter — check events with an amount field\n\t\t\tif (source.minAmount !== undefined) {\n\t\t\t\tconst amountEvents = matchedEvents.filter((e) => {\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst rawAmount = data?.amount as string | number | undefined;\n\t\t\t\t\tif (rawAmount === undefined) return false;\n\t\t\t\t\tconst amount = BigInt(rawAmount);\n\t\t\t\t\treturn amount >= source.minAmount!;\n\t\t\t\t});\n\t\t\t\tif (amountEvents.length === 0) continue;\n\t\t\t\tmatchedEvents = amountEvents;\n\t\t\t}\n\n\t\t\tresults.push({ tx, events: matchedEvents, sourceKey: key });\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Contract-based matching\n\t\tif (source.contract) {\n\t\t\tconst txContractMatch =\n\t\t\t\ttx.contract_id && matchPattern(tx.contract_id, source.contract);\n\n\t\t\t// Function filter\n\t\t\tif (source.function && tx.function_name) {\n\t\t\t\tif (!matchPattern(tx.function_name, source.function)) continue;\n\t\t\t} else if (source.function && !tx.function_name) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\tlet matchedEvents = txEvents;\n\n\t\t\tif (!txContractMatch) {\n\t\t\t\t// Check if any events match the contract\n\t\t\t\tmatchedEvents = txEvents.filter((e) => {\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst contractIdentifier = data?.contract_identifier as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tcontractIdentifier &&\n\t\t\t\t\t\tmatchPattern(contractIdentifier, source.contract!)\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tif (matchedEvents.length === 0) continue;\n\t\t\t}\n\n\t\t\t// Event type / topic filter\n\t\t\tif (source.event) {\n\t\t\t\tmatchedEvents = matchedEvents.filter((e) => {\n\t\t\t\t\tif (matchPattern(e.type, source.event!)) return true;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tconst topic = data?.topic as string | undefined;\n\t\t\t\t\treturn topic ? matchPattern(topic, source.event!) : false;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (txContractMatch || matchedEvents.length > 0) {\n\t\t\t\tresults.push({ tx, events: matchedEvents, sourceKey: key });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Match all sources against a block's transactions and events.\n * Deduplicates by (txId, sourceKey) — each handler key fires at most once per tx.\n */\nexport function matchSources(\n\tsources: SubgraphSource[],\n\ttransactions: TxRecord[],\n\tevents: EventRecord[],\n): MatchedTx[] {\n\t// Index events by txId\n\tconst eventsByTx = new Map<string, EventRecord[]>();\n\tfor (const event of events) {\n\t\tconst list = eventsByTx.get(event.tx_id) ?? [];\n\t\tlist.push(event);\n\t\teventsByTx.set(event.tx_id, list);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst results: MatchedTx[] = [];\n\n\tfor (const source of sources) {\n\t\tconst matches = matchSource(source, transactions, eventsByTx);\n\t\tfor (const match of matches) {\n\t\t\tconst dedupeKey = `${match.tx.tx_id}:${match.sourceKey}`;\n\t\t\tif (!seen.has(dedupeKey)) {\n\t\t\t\tseen.add(dedupeKey);\n\t\t\t\tresults.push(match);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n",
10
+ "import { type Database, getDb } from \"@secondlayer/shared/db\";\nimport {\n\trecordSubgraphProcessed,\n\tupdateSubgraphStatus,\n} from \"@secondlayer/shared/db/queries/subgraphs\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Transaction, sql } from \"kysely\";\nimport { pgSchemaName } from \"../schema/utils.ts\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { type BlockMeta, SubgraphContext, type TxMeta } from \"./context.ts\";\nimport { runHandlers } from \"./runner.ts\";\nimport { matchSources } from \"./source-matcher.ts\";\n\n// Cache schema_name per subgraph to avoid per-block DB lookups\nconst schemaNameCache = new Map<string, string>();\n\nexport interface ProcessBlockTiming {\n\ttotalMs: number;\n\thandlerMs: number;\n\tflushMs: number;\n}\n\nexport interface ProcessBlockResult {\n\tblockHeight: number;\n\tmatched: number;\n\tprocessed: number;\n\terrors: number;\n\tskipped: boolean;\n\ttiming?: ProcessBlockTiming;\n}\n\n/**\n * Process a single block through a single subgraph's pipeline.\n *\n * Flow:\n * 1. Load block + txs + events from DB\n * 2. Run source matcher\n * 3. Run handlers with SubgraphContext\n * 4. Flush context (commit writes atomically)\n * 5. Update subgraph.last_processed_block\n */\nexport interface PreloadedBlockData {\n\tblock: import(\"@secondlayer/shared/db\").Block;\n\ttxs: import(\"@secondlayer/shared/db\").Transaction[];\n\tevents: import(\"@secondlayer/shared/db\").Event[];\n}\n\nexport interface ProcessBlockOptions {\n\t/** Skip updating last_processed_block in DB (reindex batches this externally). */\n\tskipProgressUpdate?: boolean;\n\t/** Pre-loaded block data — skips DB reads when provided (used by batch catch-up). */\n\tpreloaded?: PreloadedBlockData;\n}\n\nexport async function processBlock(\n\tsubgraph: SubgraphDefinition,\n\tsubgraphName: string,\n\tblockHeight: number,\n\topts?: ProcessBlockOptions,\n): Promise<ProcessBlockResult> {\n\tconst db = getDb();\n\tconst blockStart = performance.now();\n\tconst result: ProcessBlockResult = {\n\t\tblockHeight,\n\t\tmatched: 0,\n\t\tprocessed: 0,\n\t\terrors: 0,\n\t\tskipped: false,\n\t};\n\n\t// 1. Load block (use pre-loaded data if available, otherwise fetch from DB)\n\tlet block, txs, evts;\n\tif (opts?.preloaded) {\n\t\tblock = opts.preloaded.block;\n\t\ttxs = opts.preloaded.txs;\n\t\tevts = opts.preloaded.events;\n\t} else {\n\t\tblock = await db\n\t\t\t.selectFrom(\"blocks\")\n\t\t\t.selectAll()\n\t\t\t.where(\"height\", \"=\", blockHeight)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!block) {\n\t\t\tlogger.warn(\"Block not found for subgraph processing\", {\n\t\t\t\tsubgraph: subgraphName,\n\t\t\t\tblockHeight,\n\t\t\t});\n\t\t\tresult.skipped = true;\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!block.canonical) {\n\t\t\tlogger.debug(\"Skipping non-canonical block\", {\n\t\t\t\tsubgraph: subgraphName,\n\t\t\t\tblockHeight,\n\t\t\t});\n\t\t\tresult.skipped = true;\n\t\t\treturn result;\n\t\t}\n\n\t\t// 2. Load txs + events\n\t\ttxs = await db\n\t\t\t.selectFrom(\"transactions\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \"=\", blockHeight)\n\t\t\t.execute();\n\n\t\tevts = await db\n\t\t\t.selectFrom(\"events\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \"=\", blockHeight)\n\t\t\t.execute();\n\t}\n\n\t// 3. Match source\n\tconst matched = matchSources(subgraph.sources, txs, evts);\n\tresult.matched = matched.length;\n\n\tif (matched.length === 0) {\n\t\tif (!opts?.skipProgressUpdate) {\n\t\t\tawait updateSubgraphStatus(db, subgraphName, \"active\", blockHeight);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// 4. Create context and run handlers\n\t// Use cached schema_name (fetched once per subgraph, not per block)\n\tlet schemaName = schemaNameCache.get(subgraphName);\n\tif (!schemaName) {\n\t\tconst subgraphRecord = await db\n\t\t\t.selectFrom(\"subgraphs\")\n\t\t\t.select(\"schema_name\")\n\t\t\t.where(\"name\", \"=\", subgraphName)\n\t\t\t.executeTakeFirst();\n\t\tschemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);\n\t\tschemaNameCache.set(subgraphName, schemaName);\n\t}\n\tconst blockMeta: BlockMeta = {\n\t\theight: block.height,\n\t\thash: block.hash,\n\t\ttimestamp: block.timestamp,\n\t\tburnBlockHeight: block.burn_block_height,\n\t};\n\tconst initialTx: TxMeta = {\n\t\ttxId: \"\",\n\t\tsender: \"\",\n\t\ttype: \"\",\n\t\tstatus: \"\",\n\t};\n\n\t// Wrap entire block processing in a single transaction\n\tlet handlerMs = 0;\n\tlet flushMs = 0;\n\n\tawait db.transaction().execute(async (tx: Transaction<Database>) => {\n\t\tconst ctx = new SubgraphContext(\n\t\t\ttx,\n\t\t\tschemaName,\n\t\t\tsubgraph.schema,\n\t\t\tblockMeta,\n\t\t\tinitialTx,\n\t\t);\n\n\t\tconst handlerStart = performance.now();\n\t\tconst runResult = await runHandlers(subgraph, matched, ctx);\n\t\thandlerMs = performance.now() - handlerStart;\n\n\t\tresult.processed = runResult.processed;\n\t\tresult.errors = runResult.errors;\n\n\t\t// 5. Flush writes\n\t\tif (ctx.pendingOps > 0) {\n\t\t\tconst flushStart = performance.now();\n\t\t\tawait ctx.flush();\n\t\t\tflushMs = performance.now() - flushStart;\n\t\t}\n\n\t\t// 6. Update progress + health metrics (same transaction)\n\t\tif (!opts?.skipProgressUpdate) {\n\t\t\tconst status =\n\t\t\t\trunResult.errors > 0 && runResult.processed === 0 ? \"error\" : \"active\";\n\t\t\tawait updateSubgraphStatus(tx, subgraphName, status, blockHeight);\n\t\t}\n\n\t\tif (\n\t\t\t!opts?.skipProgressUpdate &&\n\t\t\t(runResult.processed > 0 || runResult.errors > 0)\n\t\t) {\n\t\t\tconst lastError =\n\t\t\t\trunResult.errors > 0\n\t\t\t\t\t? `${runResult.errors} error(s) at block ${blockHeight}`\n\t\t\t\t\t: undefined;\n\t\t\tawait recordSubgraphProcessed(\n\t\t\t\ttx,\n\t\t\t\tsubgraphName,\n\t\t\t\trunResult.processed,\n\t\t\t\trunResult.errors,\n\t\t\t\tlastError,\n\t\t\t);\n\t\t}\n\t});\n\n\tconst totalMs = performance.now() - blockStart;\n\tresult.timing = {\n\t\ttotalMs: Math.round(totalMs),\n\t\thandlerMs: Math.round(handlerMs),\n\t\tflushMs: Math.round(flushMs),\n\t};\n\n\t// 7. Row count warning — sample every 1000 blocks (uses pg_stat estimate, not COUNT(*))\n\tif (blockHeight % 1000 === 0) {\n\t\ttry {\n\t\t\tconst tables = Object.keys(subgraph.schema);\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst { rows } = await sql\n\t\t\t\t\t.raw(\n\t\t\t\t\t\t`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`,\n\t\t\t\t\t)\n\t\t\t\t\t.execute(db);\n\t\t\t\tconst count = Number(\n\t\t\t\t\t(rows[0] as Record<string, unknown>)?.count ?? 0,\n\t\t\t\t);\n\t\t\t\tif (count >= 10_000_000) {\n\t\t\t\t\tlogger.warn(\"Subgraph table exceeds 10M rows (estimate)\", {\n\t\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\t\ttable,\n\t\t\t\t\t\tcount,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Table may not exist yet\n\t\t}\n\t}\n\n\treturn result;\n}\n",
11
11
  "// Re-export canonical pgSchemaName from shared\nexport { pgSchemaName } from \"@secondlayer/shared/db/queries/subgraphs\";\n",
12
12
  "import type { Database } from \"@secondlayer/shared/db\";\nimport type { Kysely } from \"kysely\";\nimport type { ProcessBlockTiming } from \"./block-processor.ts\";\n\ninterface StatsEntry {\n\tsubgraphName: string;\n\tapiKeyId: string | null;\n\tbucketStart: Date;\n\tblocksProcessed: number;\n\ttotalTimeMs: number;\n\thandlerTimeMs: number;\n\tflushTimeMs: number;\n\tmaxBlockTimeMs: number;\n\tmaxHandlerTimeMs: number;\n\ttotalOps: number;\n\tisCatchup: boolean;\n}\n\nconst FLUSH_INTERVAL_BLOCKS = 100;\nconst FLUSH_INTERVAL_MS = 60_000;\n\n/**\n * Accumulates per-block timing stats and flushes to DB periodically.\n * One instance per subgraph during catchup/reindex/live processing.\n */\nexport class StatsAccumulator {\n\tprivate current: StatsEntry;\n\tprivate lastFlush = Date.now();\n\n\tconstructor(\n\t\tprivate subgraphName: string,\n\t\tprivate apiKeyId: string | null,\n\t\tprivate isCatchup: boolean,\n\t) {\n\t\tthis.current = this.newEntry();\n\t}\n\n\trecord(timing: ProcessBlockTiming, opsCount: number): void {\n\t\tthis.current.blocksProcessed++;\n\t\tthis.current.totalTimeMs += timing.totalMs;\n\t\tthis.current.handlerTimeMs += timing.handlerMs;\n\t\tthis.current.flushTimeMs += timing.flushMs;\n\t\tthis.current.maxBlockTimeMs = Math.max(\n\t\t\tthis.current.maxBlockTimeMs,\n\t\t\ttiming.totalMs,\n\t\t);\n\t\tthis.current.maxHandlerTimeMs = Math.max(\n\t\t\tthis.current.maxHandlerTimeMs,\n\t\t\ttiming.handlerMs,\n\t\t);\n\t\tthis.current.totalOps += opsCount;\n\t}\n\n\tshouldFlush(): boolean {\n\t\treturn (\n\t\t\tthis.current.blocksProcessed >= FLUSH_INTERVAL_BLOCKS ||\n\t\t\tDate.now() - this.lastFlush >= FLUSH_INTERVAL_MS\n\t\t);\n\t}\n\n\tasync flush(db: Kysely<Database>): Promise<void> {\n\t\tif (this.current.blocksProcessed === 0) return;\n\n\t\tconst entry = this.current;\n\t\tthis.current = this.newEntry();\n\t\tthis.lastFlush = Date.now();\n\n\t\tconst avgOpsPerBlock =\n\t\t\tentry.blocksProcessed > 0 ? entry.totalOps / entry.blocksProcessed : 0;\n\n\t\tawait db\n\t\t\t.insertInto(\"subgraph_processing_stats\")\n\t\t\t.values({\n\t\t\t\tsubgraph_name: entry.subgraphName,\n\t\t\t\tapi_key_id: entry.apiKeyId,\n\t\t\t\tbucket_start: entry.bucketStart,\n\t\t\t\tbucket_end: new Date(),\n\t\t\t\tblocks_processed: entry.blocksProcessed,\n\t\t\t\ttotal_time_ms: Math.round(entry.totalTimeMs),\n\t\t\t\thandler_time_ms: Math.round(entry.handlerTimeMs),\n\t\t\t\tflush_time_ms: Math.round(entry.flushTimeMs),\n\t\t\t\tmax_block_time_ms: Math.round(entry.maxBlockTimeMs),\n\t\t\t\tmax_handler_time_ms: Math.round(entry.maxHandlerTimeMs),\n\t\t\t\tavg_ops_per_block: Number.parseFloat(avgOpsPerBlock.toFixed(2)),\n\t\t\t\tis_catchup: entry.isCatchup,\n\t\t\t})\n\t\t\t.execute();\n\t}\n\n\tprivate newEntry(): StatsEntry {\n\t\treturn {\n\t\t\tsubgraphName: this.subgraphName,\n\t\t\tapiKeyId: this.apiKeyId,\n\t\t\tbucketStart: new Date(),\n\t\t\tblocksProcessed: 0,\n\t\t\ttotalTimeMs: 0,\n\t\t\thandlerTimeMs: 0,\n\t\t\tflushTimeMs: 0,\n\t\t\tmaxBlockTimeMs: 0,\n\t\t\tmaxHandlerTimeMs: 0,\n\t\t\ttotalOps: 0,\n\t\t\tisCatchup: this.isCatchup,\n\t\t};\n\t}\n}\n",
13
13
  "import { getDb } from \"@secondlayer/shared/db\";\nimport {\n\ttype GapRange,\n\trecordGapBatch,\n} from \"@secondlayer/shared/db/queries/subgraph-gaps\";\nimport { getSubgraph } from \"@secondlayer/shared/db/queries/subgraphs\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { avgEventsPerBlock, loadBlockRange } from \"./batch-loader.ts\";\nimport { type ProcessBlockResult, processBlock } from \"./block-processor.ts\";\nimport { StatsAccumulator } from \"./stats.ts\";\n\nconst LOG_INTERVAL = 1000;\nconst DEFAULT_BATCH_SIZE = 500;\nconst MIN_BATCH_SIZE = 100;\nconst MAX_BATCH_SIZE = 1000;\n\nconst catchingUp = new Set<string>();\n\n/**\n * Coalesce individual block heights + reasons into contiguous gap ranges.\n */\nfunction coalesceGaps(\n\tblocks: { height: number; reason: string }[],\n): GapRange[] {\n\tif (blocks.length === 0) return [];\n\tblocks.sort((a, b) => a.height - b.height);\n\n\tconst ranges: GapRange[] = [];\n\tlet start = blocks[0].height;\n\tlet end = blocks[0].height;\n\tlet reason = blocks[0].reason;\n\n\tfor (let i = 1; i < blocks.length; i++) {\n\t\tconst b = blocks[i];\n\t\tif (b.height === end + 1 && b.reason === reason) {\n\t\t\tend = b.height;\n\t\t} else {\n\t\t\tranges.push({ start, end, reason });\n\t\t\tstart = b.height;\n\t\t\tend = b.height;\n\t\t\treason = b.reason;\n\t\t}\n\t}\n\tranges.push({ start, end, reason });\n\treturn ranges;\n}\n\n/**\n * Adjust batch size based on event density.\n * Sparse blocks (early chain) → larger batches. Dense blocks → smaller batches.\n */\nfunction adjustBatchSize(current: number, avgEvents: number): number {\n\tif (avgEvents > 50)\n\t\treturn Math.max(Math.round(current * 0.5), MIN_BATCH_SIZE);\n\tif (avgEvents < 10)\n\t\treturn Math.min(Math.round(current * 1.5), MAX_BATCH_SIZE);\n\treturn current;\n}\n\n/**\n * Catch a subgraph up from its last_processed_block to the chain tip.\n * Uses batch loading (3 queries per batch instead of 3 per block) and\n * pipeline prefetching (loads next batch while processing current).\n */\nexport async function catchUpSubgraph(\n\tsubgraph: SubgraphDefinition,\n\tsubgraphName: string,\n): Promise<number> {\n\tif (catchingUp.has(subgraphName)) return 0;\n\tcatchingUp.add(subgraphName);\n\n\ttry {\n\t\tconst db = getDb();\n\n\t\t// Re-read from DB to avoid stale lastProcessedBlock\n\t\tconst subgraphRow = await getSubgraph(db, subgraphName);\n\t\tif (!subgraphRow) return 0;\n\t\tconst lastProcessedBlock = Number(subgraphRow.last_processed_block);\n\n\t\t// Get chain tip from indexProgress\n\t\tconst progress = await db\n\t\t\t.selectFrom(\"index_progress\")\n\t\t\t.selectAll()\n\t\t\t.where(\"network\", \"=\", process.env.NETWORK ?? \"mainnet\")\n\t\t\t.executeTakeFirst();\n\n\t\tif (!progress) return 0;\n\n\t\tconst chainTip = Number(progress.highest_seen_block);\n\t\tif (lastProcessedBlock >= chainTip) return 0;\n\n\t\tconst subgraphStart = Number(subgraphRow.start_block) || 1;\n\t\tconst startBlock = Math.max(lastProcessedBlock + 1, subgraphStart);\n\t\tconst totalBlocks = chainTip - lastProcessedBlock;\n\n\t\tlogger.info(\"Subgraph catch-up starting\", {\n\t\t\tsubgraph: subgraphName,\n\t\t\tfrom: startBlock,\n\t\t\tto: chainTip,\n\t\t\tblocks: totalBlocks,\n\t\t});\n\n\t\tconst stats = new StatsAccumulator(\n\t\t\tsubgraphName,\n\t\t\tsubgraphRow.api_key_id,\n\t\t\ttrue,\n\t\t);\n\t\tlet processed = 0;\n\t\tlet batchSize = DEFAULT_BATCH_SIZE;\n\t\tlet currentHeight = startBlock;\n\n\t\t// Pipeline: start loading first batch\n\t\tlet nextBatchPromise = loadBlockRange(\n\t\t\tdb,\n\t\t\tcurrentHeight,\n\t\t\tMath.min(currentHeight + batchSize - 1, chainTip),\n\t\t);\n\n\t\twhile (currentHeight <= chainTip) {\n\t\t\t// Check if subgraph status changed (e.g. reindex started) — bail if so\n\t\t\tconst currentRow = await getSubgraph(db, subgraphName);\n\t\t\tif (!currentRow || currentRow.status !== \"active\") {\n\t\t\t\tlogger.info(\"Subgraph status changed, stopping catch-up\", {\n\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\tstatus: currentRow?.status ?? \"deleted\",\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Await current batch\n\t\t\tconst batch = await nextBatchPromise;\n\t\t\tconst batchEnd = Math.min(currentHeight + batchSize - 1, chainTip);\n\n\t\t\t// Start prefetching next batch while we process this one\n\t\t\tconst nextStart = batchEnd + 1;\n\t\t\tif (nextStart <= chainTip) {\n\t\t\t\tconst nextEnd = Math.min(nextStart + batchSize - 1, chainTip);\n\t\t\t\tnextBatchPromise = loadBlockRange(db, nextStart, nextEnd);\n\t\t\t}\n\n\t\t\t// Process each block from pre-loaded data\n\t\t\tconst batchFailedBlocks: { height: number; reason: string }[] = [];\n\n\t\t\tfor (let height = currentHeight; height <= batchEnd; height++) {\n\t\t\t\tconst blockData = batch.get(height);\n\t\t\t\tif (!blockData) {\n\t\t\t\t\t// Block missing (gap) — skip\n\t\t\t\t\tbatchFailedBlocks.push({ height, reason: \"block_missing\" });\n\t\t\t\t\tprocessed++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlet result: ProcessBlockResult;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await processBlock(subgraph, subgraphName, height, {\n\t\t\t\t\t\tpreloaded: blockData,\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger.error(\"Block processing error during catch-up\", {\n\t\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\t\tblockHeight: height,\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t\tbatchFailedBlocks.push({ height, reason: \"processing_error\" });\n\t\t\t\t\t// Update progress past this block so we don't retry it forever\n\t\t\t\t\tconst { updateSubgraphStatus } = await import(\n\t\t\t\t\t\t\"@secondlayer/shared/db/queries/subgraphs\"\n\t\t\t\t\t);\n\t\t\t\t\tawait updateSubgraphStatus(db, subgraphName, \"active\", height).catch(\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t);\n\t\t\t\t\tprocessed++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tprocessed++;\n\n\t\t\t\tif (result.timing) {\n\t\t\t\t\tstats.record(result.timing, result.processed);\n\t\t\t\t\tif (stats.shouldFlush()) {\n\t\t\t\t\t\tawait stats.flush(db);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (processed % LOG_INTERVAL === 0) {\n\t\t\t\t\tlogger.info(\"Subgraph catch-up progress\", {\n\t\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\t\tprocessed,\n\t\t\t\t\t\ttotal: totalBlocks,\n\t\t\t\t\t\tcurrentBlock: height,\n\t\t\t\t\t\tpct: Math.round((processed / totalBlocks) * 100),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Record any gaps from this batch\n\t\t\tif (batchFailedBlocks.length > 0) {\n\t\t\t\tconst gaps = coalesceGaps(batchFailedBlocks);\n\t\t\t\tawait recordGapBatch(db, subgraphRow.id, subgraphName, gaps).catch(\n\t\t\t\t\t(err: unknown) => {\n\t\t\t\t\t\tlogger.warn(\"Failed to record subgraph gaps\", {\n\t\t\t\t\t\t\tsubgraph: subgraphName,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Adaptive batch sizing based on event density\n\t\t\tconst avg = avgEventsPerBlock(batch);\n\t\t\tbatchSize = adjustBatchSize(batchSize, avg);\n\n\t\t\tcurrentHeight = batchEnd + 1;\n\t\t}\n\n\t\t// Flush remaining stats\n\t\tawait stats.flush(db);\n\n\t\tlogger.info(\"Subgraph catch-up complete\", {\n\t\t\tsubgraph: subgraphName,\n\t\t\tprocessed,\n\t\t});\n\n\t\treturn processed;\n\t} finally {\n\t\tcatchingUp.delete(subgraphName);\n\t}\n}\n",
@@ -15,7 +15,7 @@
15
15
  "import { getErrorMessage } from \"@secondlayer/shared\";\nimport { getDb, getRawClient } from \"@secondlayer/shared/db\";\nimport type { Subgraph } from \"@secondlayer/shared/db\";\nimport { listSubgraphs } from \"@secondlayer/shared/db/queries/subgraphs\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { pgSchemaName } from \"../schema/utils.ts\";\nimport type { SubgraphDefinition, SubgraphSchema } from \"../types.ts\";\nimport { processBlock } from \"./block-processor.ts\";\n\n/**\n * Handle a chain reorg for all active subgraphs.\n * Deletes rows at the reorged block height from all subgraph tables,\n * then reprocesses the new canonical block.\n */\nexport async function handleSubgraphReorg(\n\tblockHeight: number,\n\tloadSubgraphDef: (handlerPath: string) => Promise<SubgraphDefinition>,\n): Promise<void> {\n\tconst db = getDb();\n\tconst client = getRawClient();\n\tconst activeSubgraphs = (await listSubgraphs(db)).filter(\n\t\t(v: Subgraph) => v.status === \"active\",\n\t);\n\n\tif (activeSubgraphs.length === 0) return;\n\n\tlogger.info(\"Propagating reorg to subgraphs\", {\n\t\tblockHeight,\n\t\tsubgraphCount: activeSubgraphs.length,\n\t});\n\n\tfor (const sg of activeSubgraphs) {\n\t\ttry {\n\t\t\tconst schema = sg.definition.schema as SubgraphSchema | undefined;\n\t\t\tif (!schema) continue;\n\n\t\t\tconst schemaName = sg.schema_name ?? pgSchemaName(sg.name);\n\n\t\t\t// Delete rows at the reorged block height from all tables\n\t\t\tfor (const tableName of Object.keys(schema)) {\n\t\t\t\tawait client.unsafe(\n\t\t\t\t\t`DELETE FROM \"${schemaName}\".\"${tableName}\" WHERE \"_block_height\" = $1`,\n\t\t\t\t\t[blockHeight],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlogger.info(\"Subgraph reorg cleanup done\", {\n\t\t\t\tsubgraph: sg.name,\n\t\t\t\tblockHeight,\n\t\t\t});\n\n\t\t\t// Reprocess the new canonical block\n\t\t\tconst def = await loadSubgraphDef(sg.handler_path);\n\t\t\tawait processBlock(def, sg.name, blockHeight);\n\n\t\t\tlogger.info(\"Subgraph reorg reprocessed\", {\n\t\t\t\tsubgraph: sg.name,\n\t\t\t\tblockHeight,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tlogger.error(\"Subgraph reorg handling failed\", {\n\t\t\t\tsubgraph: sg.name,\n\t\t\t\tblockHeight,\n\t\t\t\terror: getErrorMessage(err),\n\t\t\t});\n\t\t}\n\t}\n}\n",
16
16
  "import { getErrorMessage } from \"@secondlayer/shared\";\nimport { getDb } from \"@secondlayer/shared/db\";\nimport type { Subgraph } from \"@secondlayer/shared/db\";\nimport {\n\tlistSubgraphs,\n\tupdateSubgraphStatus,\n} from \"@secondlayer/shared/db/queries/subgraphs\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { listen } from \"@secondlayer/shared/queue/listener\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { catchUpSubgraph } from \"./catchup.ts\";\nimport { handleSubgraphReorg } from \"./reorg.ts\";\n\nconst CHANNEL_NEW_BLOCK = \"streams:new_job\";\nconst DEFAULT_CONCURRENCY = 5;\nconst POLL_INTERVAL_MS = 5_000;\n\nfunction isHandlerNotFoundError(err: unknown): boolean {\n\tif (!(err instanceof Error)) return false;\n\tconst code = (err as NodeJS.ErrnoException).code;\n\tif (\n\t\tcode === \"MODULE_NOT_FOUND\" ||\n\t\tcode === \"ERR_MODULE_NOT_FOUND\" ||\n\t\tcode === \"ENOENT\"\n\t)\n\t\treturn true;\n\t// fallback: Bun may not always set code on dynamic import failures\n\treturn (\n\t\terr.message.includes(\"Cannot find module\") || err.message.includes(\"ENOENT\")\n\t);\n}\n\n/**\n * Load a SubgraphDefinition from its handler file path.\n */\nasync function loadSubgraphDefinition(\n\thandlerPath: string,\n): Promise<SubgraphDefinition> {\n\tconst mod = await import(handlerPath);\n\treturn mod.default ?? mod;\n}\n\n/**\n * Start the subgraph processor service.\n * Listens for new blocks via NOTIFY and processes them through all active subgraphs.\n */\nexport async function startSubgraphProcessor(opts?: {\n\tconcurrency?: number;\n}): Promise<() => Promise<void>> {\n\tconst concurrency = opts?.concurrency ?? DEFAULT_CONCURRENCY;\n\tlet running = true;\n\n\tlogger.info(\"Starting subgraph processor\", { concurrency });\n\n\t// Catch-up all subgraphs on startup\n\tconst db = getDb();\n\tconst activeSubgraphs = (await listSubgraphs(db)).filter(\n\t\t(v: Subgraph) => v.status === \"active\",\n\t);\n\tfor (const sg of activeSubgraphs) {\n\t\ttry {\n\t\t\tconst def = await loadSubgraphDefinition(sg.handler_path);\n\t\t\tawait catchUpSubgraph(def, sg.name);\n\t\t} catch (err) {\n\t\t\tconst msg = getErrorMessage(err);\n\t\t\tif (isHandlerNotFoundError(err)) {\n\t\t\t\tawait updateSubgraphStatus(db, sg.name, \"error\");\n\t\t\t}\n\t\t\tlogger.error(\"Subgraph catch-up failed on startup\", {\n\t\t\t\tsubgraph: sg.name,\n\t\t\t\terror: msg,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Listen for new blocks\n\tconst stopListening = await listen(CHANNEL_NEW_BLOCK, async () => {\n\t\tif (!running) return;\n\t\t// The NOTIFY payload doesn't include block height — we rely on\n\t\t// each subgraph's last_processed_block to determine what to process.\n\t\t// Trigger catch-up for all subgraphs.\n\t\tconst db = getDb();\n\t\tconst subgraphs = (await listSubgraphs(db)).filter(\n\t\t\t(v: Subgraph) => v.status === \"active\",\n\t\t);\n\t\tfor (const sg of subgraphs) {\n\t\t\ttry {\n\t\t\t\tconst def = await loadSubgraphDefinition(sg.handler_path);\n\t\t\t\tawait catchUpSubgraph(def, sg.name);\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = getErrorMessage(err);\n\t\t\t\tif (isHandlerNotFoundError(err)) {\n\t\t\t\t\tawait updateSubgraphStatus(db, sg.name, \"error\");\n\t\t\t\t}\n\t\t\t\tlogger.error(\"Subgraph processing failed\", {\n\t\t\t\t\tsubgraph: sg.name,\n\t\t\t\t\terror: msg,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\n\t// Listen for reorgs\n\tconst stopReorgListening = await listen(\n\t\t\"subgraph_reorg\",\n\t\tasync (payload: string | undefined) => {\n\t\t\tif (!running) return;\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(payload ?? \"{}\");\n\t\t\t\tconst blockHeight = data.blockHeight;\n\t\t\t\tif (typeof blockHeight === \"number\") {\n\t\t\t\t\tawait handleSubgraphReorg(blockHeight, loadSubgraphDefinition);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tlogger.error(\"Subgraph reorg handling failed\", {\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n\n\t// Poll as backup\n\tconst pollInterval = setInterval(async () => {\n\t\tif (!running) return;\n\t\tconst db = getDb();\n\t\tconst subgraphs = (await listSubgraphs(db)).filter(\n\t\t\t(v: Subgraph) => v.status === \"active\",\n\t\t);\n\t\tfor (const sg of subgraphs) {\n\t\t\ttry {\n\t\t\t\tconst def = await loadSubgraphDefinition(sg.handler_path);\n\t\t\t\tawait catchUpSubgraph(def, sg.name);\n\t\t\t} catch (err) {\n\t\t\t\tlogger.error(\"Subgraph poll processing failed\", {\n\t\t\t\t\tsubgraph: sg.name,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, POLL_INTERVAL_MS);\n\n\tlogger.info(\"Subgraph processor ready\");\n\n\t// Return shutdown function\n\treturn async () => {\n\t\trunning = false;\n\t\tclearInterval(pollInterval);\n\t\tawait stopListening();\n\t\tawait stopReorgListening();\n\t\tlogger.info(\"Subgraph processor stopped\");\n\t};\n}\n"
17
17
  ],
18
- "mappings": "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",
19
- "debugId": "5F33BE7F1A25C9CB64756E2164756E21",
18
+ "mappings": "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",
19
+ "debugId": "24ABE3B55CB51E2464756E2164756E21",
20
20
  "names": []
21
21
  }
@@ -75,15 +75,28 @@ interface ReindexOptions {
75
75
  fromBlock?: number;
76
76
  toBlock?: number;
77
77
  schemaName?: string;
78
+ signal?: AbortSignal;
78
79
  }
79
80
  /**
80
81
  * Reindex a subgraph by dropping its tables, recreating them, and reprocessing
81
82
  * all historical blocks through the handler pipeline.
83
+ * Supports cancellation via AbortSignal — on shutdown abort, status stays
84
+ * "reindexing" for auto-resume; on user cancel, status resets to "active".
82
85
  */
83
86
  declare function reindexSubgraph(def: SubgraphDefinition, opts?: ReindexOptions): Promise<{
84
87
  processed: number
85
88
  }>;
86
89
  /**
90
+ * Resume a previously interrupted reindex. Skips schema drop (already done)
91
+ * and continues from last_processed_block + 1.
92
+ */
93
+ declare function resumeReindex(def: SubgraphDefinition, opts: {
94
+ schemaName: string
95
+ signal?: AbortSignal
96
+ }): Promise<{
97
+ processed: number
98
+ }>;
99
+ /**
87
100
  * Backfill a subgraph by re-processing a block range WITHOUT dropping the schema.
88
101
  * Uses upserts so existing data is updated, not duplicated. Safe to run while
89
102
  * the subgraph is actively syncing.
@@ -92,7 +105,8 @@ declare function backfillSubgraph(def: SubgraphDefinition, opts: {
92
105
  fromBlock: number
93
106
  toBlock: number
94
107
  schemaName?: string
108
+ signal?: AbortSignal
95
109
  }): Promise<{
96
110
  processed: number
97
111
  }>;
98
- export { reindexSubgraph, backfillSubgraph, ReindexOptions };
112
+ export { resumeReindex, reindexSubgraph, backfillSubgraph, ReindexOptions };
@@ -367,11 +367,17 @@ async function runHandlers(subgraph, matched, ctx, opts) {
367
367
  }
368
368
 
369
369
  // src/runtime/source-matcher.ts
370
+ var patternCache = new Map;
370
371
  function matchPattern(value, pattern) {
371
372
  if (!pattern.includes("*"))
372
373
  return value === pattern;
373
- const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
374
- return new RegExp(`^${regex}$`).test(value);
374
+ let re = patternCache.get(pattern);
375
+ if (!re) {
376
+ const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
377
+ re = new RegExp(`^${regex}$`);
378
+ patternCache.set(pattern, re);
379
+ }
380
+ return re.test(value);
375
381
  }
376
382
  function matchSource(source, transactions, eventsByTx) {
377
383
  const results = [];
@@ -564,10 +570,10 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
564
570
  try {
565
571
  const tables = Object.keys(subgraph.schema);
566
572
  for (const table of tables) {
567
- const { rows } = await sql2.raw(`SELECT COUNT(*) as count FROM "${schemaName}"."${table}"`).execute(db);
568
- const count = Number(rows[0].count);
573
+ const { rows } = await sql2.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(db);
574
+ const count = Number(rows[0]?.count ?? 0);
569
575
  if (count >= 1e7) {
570
- logger3.warn("Subgraph table exceeds 10M rows", {
576
+ logger3.warn("Subgraph table exceeds 10M rows (estimate)", {
571
577
  subgraph: subgraphName,
572
578
  table,
573
579
  count
@@ -821,8 +827,18 @@ async function processBlockRange(def, opts) {
821
827
  let totalErrors = 0;
822
828
  let batchSize = DEFAULT_BATCH_SIZE;
823
829
  let currentHeight = fromBlock;
830
+ let aborted = false;
824
831
  let nextBatchPromise = loadBlockRange(db, currentHeight, Math.min(currentHeight + batchSize - 1, toBlock));
825
832
  while (currentHeight <= toBlock) {
833
+ if (opts.signal?.aborted) {
834
+ aborted = true;
835
+ logger4.info("Block processing aborted", {
836
+ subgraph: subgraphName,
837
+ currentBlock: currentHeight,
838
+ reason: String(opts.signal.reason ?? "unknown")
839
+ });
840
+ break;
841
+ }
826
842
  const batch = await nextBatchPromise;
827
843
  const batchEnd = Math.min(currentHeight + batchSize - 1, toBlock);
828
844
  const nextStart = batchEnd + 1;
@@ -895,7 +911,7 @@ async function processBlockRange(def, opts) {
895
911
  currentHeight = batchEnd + 1;
896
912
  }
897
913
  await stats.flush(db);
898
- return { blocksProcessed, totalEventsProcessed, totalErrors };
914
+ return { blocksProcessed, totalEventsProcessed, totalErrors, aborted };
899
915
  }
900
916
  async function resolveBlockRange(db, def, opts) {
901
917
  const fromBlock = opts?.fromBlock ?? def.startBlock ?? 1;
@@ -908,6 +924,9 @@ async function resolveBlockRange(db, def, opts) {
908
924
  }
909
925
  return { fromBlock, toBlock };
910
926
  }
927
+ async function clearReindexMetadata(db, subgraphName) {
928
+ await db.updateTable("subgraphs").set({ reindex_from_block: null, reindex_to_block: null }).where("name", "=", subgraphName).execute();
929
+ }
911
930
  async function reindexSubgraph(def, opts) {
912
931
  const db = getDb2();
913
932
  const client = getRawClient();
@@ -916,12 +935,6 @@ async function reindexSubgraph(def, opts) {
916
935
  await updateSubgraphStatus2(db, subgraphName, "reindexing");
917
936
  logger4.info("Reindex starting", { subgraph: subgraphName });
918
937
  try {
919
- await client.unsafe(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`);
920
- const { statements } = generateSubgraphSQL(def, schemaName);
921
- for (const stmt of statements) {
922
- await client.unsafe(stmt);
923
- }
924
- logger4.info("Schema recreated for reindex", { subgraph: subgraphName });
925
938
  const { fromBlock, toBlock } = await resolveBlockRange(db, def, opts);
926
939
  if (fromBlock > toBlock) {
927
940
  logger4.info("No blocks to reindex", {
@@ -932,6 +945,13 @@ async function reindexSubgraph(def, opts) {
932
945
  await updateSubgraphStatus2(db, subgraphName, "active", 0);
933
946
  return { processed: 0 };
934
947
  }
948
+ await db.updateTable("subgraphs").set({ reindex_from_block: fromBlock, reindex_to_block: toBlock }).where("name", "=", subgraphName).execute();
949
+ await client.unsafe(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`);
950
+ const { statements } = generateSubgraphSQL(def, schemaName);
951
+ for (const stmt of statements) {
952
+ await client.unsafe(stmt);
953
+ }
954
+ logger4.info("Schema recreated for reindex", { subgraph: subgraphName });
935
955
  logger4.info("Reindexing blocks", {
936
956
  subgraph: subgraphName,
937
957
  fromBlock,
@@ -945,13 +965,28 @@ async function reindexSubgraph(def, opts) {
945
965
  status: "reindexing",
946
966
  isCatchup: false,
947
967
  apiKeyId: subgraphRow?.api_key_id ?? null,
948
- subgraphId: subgraphRow?.id
968
+ subgraphId: subgraphRow?.id,
969
+ signal: opts?.signal
949
970
  });
971
+ if (result.aborted) {
972
+ const reason = String(opts?.signal?.reason ?? "unknown");
973
+ if (reason === "user-cancelled") {
974
+ await updateSubgraphStatus2(db, subgraphName, "active");
975
+ await clearReindexMetadata(db, subgraphName);
976
+ logger4.info("Reindex cancelled by user", { subgraph: subgraphName });
977
+ } else {
978
+ logger4.info("Reindex interrupted by shutdown, will resume", {
979
+ subgraph: subgraphName
980
+ });
981
+ }
982
+ return { processed: result.blocksProcessed };
983
+ }
950
984
  const { recordSubgraphProcessed: recordSubgraphProcessed2 } = await import("@secondlayer/shared/db/queries/subgraphs");
951
985
  if (result.totalEventsProcessed > 0 || result.totalErrors > 0) {
952
986
  await recordSubgraphProcessed2(db, subgraphName, result.totalEventsProcessed, result.totalErrors, result.totalErrors > 0 ? `${result.totalErrors} error(s) during reindex` : undefined);
953
987
  }
954
988
  await updateSubgraphStatus2(db, subgraphName, "active", toBlock);
989
+ await clearReindexMetadata(db, subgraphName);
955
990
  logger4.info("Reindex complete", {
956
991
  subgraph: subgraphName,
957
992
  blocks: result.blocksProcessed,
@@ -968,6 +1003,84 @@ async function reindexSubgraph(def, opts) {
968
1003
  throw err;
969
1004
  }
970
1005
  }
1006
+ async function resumeReindex(def, opts) {
1007
+ const db = getDb2();
1008
+ const subgraphName = def.name;
1009
+ const row = await db.selectFrom("subgraphs").select([
1010
+ "id",
1011
+ "api_key_id",
1012
+ "last_processed_block",
1013
+ "reindex_from_block",
1014
+ "reindex_to_block"
1015
+ ]).where("name", "=", subgraphName).executeTakeFirst();
1016
+ if (!row)
1017
+ throw new Error(`Subgraph "${subgraphName}" not found`);
1018
+ if (row.reindex_from_block == null || row.reindex_to_block == null) {
1019
+ logger4.info("No reindex metadata, starting fresh reindex", {
1020
+ subgraph: subgraphName
1021
+ });
1022
+ return reindexSubgraph(def, {
1023
+ schemaName: opts.schemaName,
1024
+ signal: opts.signal
1025
+ });
1026
+ }
1027
+ const fromBlock = Math.max(row.last_processed_block + 1, row.reindex_from_block);
1028
+ const toBlock = row.reindex_to_block;
1029
+ if (fromBlock > toBlock) {
1030
+ logger4.info("Resume: no remaining blocks", { subgraph: subgraphName });
1031
+ await updateSubgraphStatus2(db, subgraphName, "active", toBlock);
1032
+ await clearReindexMetadata(db, subgraphName);
1033
+ return { processed: 0 };
1034
+ }
1035
+ logger4.info("Resuming reindex", {
1036
+ subgraph: subgraphName,
1037
+ fromBlock,
1038
+ toBlock,
1039
+ remaining: toBlock - fromBlock + 1
1040
+ });
1041
+ try {
1042
+ const result = await processBlockRange(def, {
1043
+ fromBlock,
1044
+ toBlock,
1045
+ status: "reindexing",
1046
+ isCatchup: false,
1047
+ apiKeyId: row.api_key_id ?? null,
1048
+ subgraphId: row.id,
1049
+ signal: opts.signal
1050
+ });
1051
+ if (result.aborted) {
1052
+ const reason = String(opts.signal?.reason ?? "unknown");
1053
+ if (reason === "user-cancelled") {
1054
+ await updateSubgraphStatus2(db, subgraphName, "active");
1055
+ await clearReindexMetadata(db, subgraphName);
1056
+ logger4.info("Resume cancelled by user", { subgraph: subgraphName });
1057
+ } else {
1058
+ logger4.info("Resume interrupted by shutdown, will resume again", {
1059
+ subgraph: subgraphName
1060
+ });
1061
+ }
1062
+ return { processed: result.blocksProcessed };
1063
+ }
1064
+ const { recordSubgraphProcessed: recordSubgraphProcessed2 } = await import("@secondlayer/shared/db/queries/subgraphs");
1065
+ if (result.totalEventsProcessed > 0 || result.totalErrors > 0) {
1066
+ await recordSubgraphProcessed2(db, subgraphName, result.totalEventsProcessed, result.totalErrors, result.totalErrors > 0 ? `${result.totalErrors} error(s) during resumed reindex` : undefined);
1067
+ }
1068
+ await updateSubgraphStatus2(db, subgraphName, "active", toBlock);
1069
+ await clearReindexMetadata(db, subgraphName);
1070
+ logger4.info("Resumed reindex complete", {
1071
+ subgraph: subgraphName,
1072
+ blocks: result.blocksProcessed
1073
+ });
1074
+ return { processed: result.blocksProcessed };
1075
+ } catch (err) {
1076
+ logger4.error("Resumed reindex failed", {
1077
+ subgraph: subgraphName,
1078
+ error: getErrorMessage2(err)
1079
+ });
1080
+ await updateSubgraphStatus2(db, subgraphName, "error");
1081
+ throw err;
1082
+ }
1083
+ }
971
1084
  async function backfillSubgraph(def, opts) {
972
1085
  const db = getDb2();
973
1086
  const subgraphName = def.name;
@@ -984,8 +1097,13 @@ async function backfillSubgraph(def, opts) {
984
1097
  status: "active",
985
1098
  isCatchup: false,
986
1099
  apiKeyId: subgraphRow?.api_key_id ?? null,
987
- subgraphId: subgraphRow?.id
1100
+ subgraphId: subgraphRow?.id,
1101
+ signal: opts.signal
988
1102
  });
1103
+ if (result.aborted) {
1104
+ logger4.info("Backfill aborted", { subgraph: subgraphName });
1105
+ return { processed: result.blocksProcessed };
1106
+ }
989
1107
  const resolved = await resolveGaps(db, subgraphName, opts.fromBlock, opts.toBlock).catch(() => 0);
990
1108
  if (resolved > 0) {
991
1109
  logger4.info("Resolved subgraph gaps via backfill", {
@@ -1013,9 +1131,10 @@ async function backfillSubgraph(def, opts) {
1013
1131
  }
1014
1132
  }
1015
1133
  export {
1134
+ resumeReindex,
1016
1135
  reindexSubgraph,
1017
1136
  backfillSubgraph
1018
1137
  };
1019
1138
 
1020
- //# debugId=4FA0EA096CCF4F4264756E2164756E21
1139
+ //# debugId=258FF6B1EDF5AD3464756E2164756E21
1021
1140
  //# sourceMappingURL=reindex.js.map