@secondlayer/subgraphs 0.11.6 → 0.11.8

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.
@@ -849,7 +849,10 @@ function matchSources(sources, transactions, events) {
849
849
  }
850
850
 
851
851
  // src/runtime/block-processor.ts
852
- import { getDb } from "@secondlayer/shared/db";
852
+ import {
853
+ getSourceDb,
854
+ getTargetDb
855
+ } from "@secondlayer/shared/db";
853
856
  import {
854
857
  recordSubgraphProcessed,
855
858
  updateSubgraphStatus
@@ -863,7 +866,8 @@ import { pgSchemaName } from "@secondlayer/shared/db/queries/subgraphs";
863
866
  // src/runtime/block-processor.ts
864
867
  var schemaNameCache = new Map;
865
868
  async function processBlock(subgraph, subgraphName, blockHeight, opts) {
866
- const db = getDb();
869
+ const sourceDb = getSourceDb();
870
+ const targetDb = getTargetDb();
867
871
  const blockStart = performance.now();
868
872
  const result = {
869
873
  blockHeight,
@@ -872,13 +876,15 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
872
876
  errors: 0,
873
877
  skipped: false
874
878
  };
875
- let block, txs, evts;
879
+ let block;
880
+ let txs;
881
+ let evts;
876
882
  if (opts?.preloaded) {
877
883
  block = opts.preloaded.block;
878
884
  txs = opts.preloaded.txs;
879
885
  evts = opts.preloaded.events;
880
886
  } else {
881
- block = await db.selectFrom("blocks").selectAll().where("height", "=", blockHeight).executeTakeFirst();
887
+ block = await sourceDb.selectFrom("blocks").selectAll().where("height", "=", blockHeight).executeTakeFirst();
882
888
  if (!block) {
883
889
  logger3.warn("Block not found for subgraph processing", {
884
890
  subgraph: subgraphName,
@@ -895,20 +901,20 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
895
901
  result.skipped = true;
896
902
  return result;
897
903
  }
898
- txs = await db.selectFrom("transactions").selectAll().where("block_height", "=", blockHeight).execute();
899
- evts = await db.selectFrom("events").selectAll().where("block_height", "=", blockHeight).execute();
904
+ txs = await sourceDb.selectFrom("transactions").selectAll().where("block_height", "=", blockHeight).execute();
905
+ evts = await sourceDb.selectFrom("events").selectAll().where("block_height", "=", blockHeight).execute();
900
906
  }
901
907
  const matched = matchSources(subgraph.sources, txs, evts);
902
908
  result.matched = matched.length;
903
909
  if (matched.length === 0) {
904
910
  if (!opts?.skipProgressUpdate) {
905
- await updateSubgraphStatus(db, subgraphName, "active", blockHeight);
911
+ await updateSubgraphStatus(targetDb, subgraphName, "active", blockHeight);
906
912
  }
907
913
  return result;
908
914
  }
909
915
  let schemaName = schemaNameCache.get(subgraphName);
910
916
  if (!schemaName) {
911
- const subgraphRecord = await db.selectFrom("subgraphs").select("schema_name").where("name", "=", subgraphName).executeTakeFirst();
917
+ const subgraphRecord = await targetDb.selectFrom("subgraphs").select("schema_name").where("name", "=", subgraphName).executeTakeFirst();
912
918
  schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);
913
919
  schemaNameCache.set(subgraphName, schemaName);
914
920
  }
@@ -926,7 +932,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
926
932
  };
927
933
  let handlerMs = 0;
928
934
  let flushMs = 0;
929
- await db.transaction().execute(async (tx) => {
935
+ await targetDb.transaction().execute(async (tx) => {
930
936
  const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx);
931
937
  const handlerStart = performance.now();
932
938
  const runResult = await runHandlers(subgraph, matched, ctx);
@@ -957,7 +963,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
957
963
  try {
958
964
  const tables = Object.keys(subgraph.schema);
959
965
  for (const table of tables) {
960
- const { rows } = await sql2.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(db);
966
+ const { rows } = await sql2.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(targetDb);
961
967
  const count = Number(rows[0]?.count ?? 0);
962
968
  if (count >= 1e7) {
963
969
  logger3.warn("Subgraph table exceeds 10M rows (estimate)", {
@@ -978,13 +984,11 @@ var FLUSH_INTERVAL_MS = 60000;
978
984
 
979
985
  class StatsAccumulator {
980
986
  subgraphName;
981
- apiKeyId;
982
987
  isCatchup;
983
988
  current;
984
989
  lastFlush = Date.now();
985
- constructor(subgraphName, apiKeyId, isCatchup) {
990
+ constructor(subgraphName, isCatchup) {
986
991
  this.subgraphName = subgraphName;
987
- this.apiKeyId = apiKeyId;
988
992
  this.isCatchup = isCatchup;
989
993
  this.current = this.newEntry();
990
994
  }
@@ -1009,7 +1013,6 @@ class StatsAccumulator {
1009
1013
  const avgOpsPerBlock = entry.blocksProcessed > 0 ? entry.totalOps / entry.blocksProcessed : 0;
1010
1014
  await db.insertInto("subgraph_processing_stats").values({
1011
1015
  subgraph_name: entry.subgraphName,
1012
- api_key_id: entry.apiKeyId,
1013
1016
  bucket_start: entry.bucketStart,
1014
1017
  bucket_end: new Date,
1015
1018
  blocks_processed: entry.blocksProcessed,
@@ -1025,7 +1028,6 @@ class StatsAccumulator {
1025
1028
  newEntry() {
1026
1029
  return {
1027
1030
  subgraphName: this.subgraphName,
1028
- apiKeyId: this.apiKeyId,
1029
1031
  bucketStart: new Date,
1030
1032
  blocksProcessed: 0,
1031
1033
  totalTimeMs: 0,
@@ -1040,7 +1042,7 @@ class StatsAccumulator {
1040
1042
  }
1041
1043
 
1042
1044
  // src/runtime/catchup.ts
1043
- import { getDb as getDb2 } from "@secondlayer/shared/db";
1045
+ import { getSourceDb as getSourceDb2, getTargetDb as getTargetDb2 } from "@secondlayer/shared/db";
1044
1046
  import {
1045
1047
  recordGapBatch
1046
1048
  } from "@secondlayer/shared/db/queries/subgraph-gaps";
@@ -1129,12 +1131,13 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1129
1131
  return 0;
1130
1132
  catchingUp.add(subgraphName);
1131
1133
  try {
1132
- const db = getDb2();
1133
- const subgraphRow = await getSubgraph(db, subgraphName);
1134
+ const sourceDb = getSourceDb2();
1135
+ const targetDb = getTargetDb2();
1136
+ const subgraphRow = await getSubgraph(targetDb, subgraphName);
1134
1137
  if (!subgraphRow)
1135
1138
  return 0;
1136
1139
  const lastProcessedBlock = Number(subgraphRow.last_processed_block);
1137
- const progress = await db.selectFrom("index_progress").selectAll().where("network", "=", process.env.NETWORK ?? "mainnet").executeTakeFirst();
1140
+ const progress = await sourceDb.selectFrom("index_progress").selectAll().where("network", "=", process.env.NETWORK ?? "mainnet").executeTakeFirst();
1138
1141
  if (!progress)
1139
1142
  return 0;
1140
1143
  const chainTip = Number(progress.highest_seen_block);
@@ -1149,14 +1152,14 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1149
1152
  to: chainTip,
1150
1153
  blocks: totalBlocks
1151
1154
  });
1152
- const stats = new StatsAccumulator(subgraphName, subgraphRow.api_key_id, true);
1155
+ const stats = new StatsAccumulator(subgraphName, true);
1153
1156
  let processed = 0;
1154
1157
  let batchSize = DEFAULT_BATCH_SIZE;
1155
1158
  let currentHeight = startBlock;
1156
1159
  let nextBatchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
1157
- let nextBatchPromise = loadBlockRange(db, currentHeight, nextBatchEnd);
1160
+ let nextBatchPromise = loadBlockRange(sourceDb, currentHeight, nextBatchEnd);
1158
1161
  while (currentHeight <= chainTip) {
1159
- const currentRow = await getSubgraph(db, subgraphName);
1162
+ const currentRow = await getSubgraph(targetDb, subgraphName);
1160
1163
  if (!currentRow || currentRow.status !== "active") {
1161
1164
  logger4.info("Subgraph status changed, stopping catch-up", {
1162
1165
  subgraph: subgraphName,
@@ -1169,7 +1172,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1169
1172
  const nextStart = batchEnd + 1;
1170
1173
  if (nextStart <= chainTip) {
1171
1174
  nextBatchEnd = Math.min(nextStart + batchSize - 1, chainTip);
1172
- nextBatchPromise = loadBlockRange(db, nextStart, nextBatchEnd);
1175
+ nextBatchPromise = loadBlockRange(sourceDb, nextStart, nextBatchEnd);
1173
1176
  }
1174
1177
  const batchFailedBlocks = [];
1175
1178
  for (let height = currentHeight;height <= batchEnd; height++) {
@@ -1192,7 +1195,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1192
1195
  });
1193
1196
  batchFailedBlocks.push({ height, reason: "processing_error" });
1194
1197
  const { updateSubgraphStatus: updateSubgraphStatus2 } = await import("@secondlayer/shared/db/queries/subgraphs");
1195
- await updateSubgraphStatus2(db, subgraphName, "active", height).catch(() => {});
1198
+ await updateSubgraphStatus2(targetDb, subgraphName, "active", height).catch(() => {});
1196
1199
  processed++;
1197
1200
  continue;
1198
1201
  }
@@ -1200,7 +1203,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1200
1203
  if (result.timing) {
1201
1204
  stats.record(result.timing, result.processed);
1202
1205
  if (stats.shouldFlush()) {
1203
- await stats.flush(db);
1206
+ await stats.flush(targetDb);
1204
1207
  }
1205
1208
  }
1206
1209
  if (processed % LOG_INTERVAL === 0) {
@@ -1215,7 +1218,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1215
1218
  }
1216
1219
  if (batchFailedBlocks.length > 0) {
1217
1220
  const gaps = coalesceGaps(batchFailedBlocks);
1218
- await recordGapBatch(db, subgraphRow.id, subgraphName, gaps).catch((err) => {
1221
+ await recordGapBatch(targetDb, subgraphRow.id, subgraphName, gaps).catch((err) => {
1219
1222
  logger4.warn("Failed to record subgraph gaps", {
1220
1223
  subgraph: subgraphName,
1221
1224
  error: err instanceof Error ? err.message : String(err)
@@ -1226,7 +1229,7 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1226
1229
  batchSize = adjustBatchSize(batchSize, avg);
1227
1230
  currentHeight = batchEnd + 1;
1228
1231
  }
1229
- await stats.flush(db);
1232
+ await stats.flush(targetDb);
1230
1233
  logger4.info("Subgraph catch-up complete", {
1231
1234
  subgraph: subgraphName,
1232
1235
  processed
@@ -1239,13 +1242,13 @@ async function catchUpSubgraph(subgraph, subgraphName) {
1239
1242
 
1240
1243
  // src/runtime/reorg.ts
1241
1244
  import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
1242
- import { getDb as getDb3, getRawClient } from "@secondlayer/shared/db";
1245
+ import { getRawClient, getTargetDb as getTargetDb3 } from "@secondlayer/shared/db";
1243
1246
  import { listSubgraphs } from "@secondlayer/shared/db/queries/subgraphs";
1244
1247
  import { logger as logger5 } from "@secondlayer/shared/logger";
1245
1248
  async function handleSubgraphReorg(blockHeight, loadSubgraphDef) {
1246
- const db = getDb3();
1247
- const client = getRawClient();
1248
- const activeSubgraphs = (await listSubgraphs(db)).filter((v) => v.status === "active");
1249
+ const targetDb = getTargetDb3();
1250
+ const client = getRawClient("target");
1251
+ const activeSubgraphs = (await listSubgraphs(targetDb)).filter((v) => v.status === "active");
1249
1252
  if (activeSubgraphs.length === 0)
1250
1253
  return;
1251
1254
  logger5.info("Propagating reorg to subgraphs", {
@@ -1283,7 +1286,7 @@ async function handleSubgraphReorg(blockHeight, loadSubgraphDef) {
1283
1286
 
1284
1287
  // src/runtime/processor.ts
1285
1288
  import { getErrorMessage as getErrorMessage3 } from "@secondlayer/shared";
1286
- import { getDb as getDb4 } from "@secondlayer/shared/db";
1289
+ import { getTargetDb as getTargetDb4 } from "@secondlayer/shared/db";
1287
1290
  import {
1288
1291
  listSubgraphs as listSubgraphs2,
1289
1292
  updateSubgraphStatus as updateSubgraphStatus2
@@ -1293,6 +1296,9 @@ import { listen } from "@secondlayer/shared/queue/listener";
1293
1296
  var CHANNEL_NEW_BLOCK = "indexer:new_block";
1294
1297
  var DEFAULT_CONCURRENCY = 5;
1295
1298
  var POLL_INTERVAL_MS = 5000;
1299
+ function sourceListenerUrl() {
1300
+ return process.env.SOURCE_DATABASE_URL ?? process.env.DATABASE_URL;
1301
+ }
1296
1302
  function isHandlerNotFoundError(err) {
1297
1303
  if (!(err instanceof Error))
1298
1304
  return false;
@@ -1341,8 +1347,8 @@ async function startSubgraphProcessor(opts) {
1341
1347
  const concurrency = opts?.concurrency ?? DEFAULT_CONCURRENCY;
1342
1348
  let running = true;
1343
1349
  logger6.info("Starting subgraph processor", { concurrency });
1344
- const db = getDb4();
1345
- const activeSubgraphs = (await listSubgraphs2(db)).filter((v) => v.status === "active");
1350
+ const targetDb = getTargetDb4();
1351
+ const activeSubgraphs = (await listSubgraphs2(targetDb)).filter((v) => v.status === "active");
1346
1352
  for (const sg of activeSubgraphs) {
1347
1353
  try {
1348
1354
  const def = await loadSubgraphDefinition(sg);
@@ -1350,7 +1356,7 @@ async function startSubgraphProcessor(opts) {
1350
1356
  } catch (err) {
1351
1357
  const msg = getErrorMessage3(err);
1352
1358
  if (isHandlerNotFoundError(err)) {
1353
- await updateSubgraphStatus2(db, sg.name, "error");
1359
+ await updateSubgraphStatus2(targetDb, sg.name, "error");
1354
1360
  }
1355
1361
  logger6.error("Subgraph catch-up failed on startup", {
1356
1362
  subgraph: sg.name,
@@ -1361,8 +1367,8 @@ async function startSubgraphProcessor(opts) {
1361
1367
  const stopListening = await listen(CHANNEL_NEW_BLOCK, async () => {
1362
1368
  if (!running)
1363
1369
  return;
1364
- const db2 = getDb4();
1365
- const subgraphs = (await listSubgraphs2(db2)).filter((v) => v.status === "active");
1370
+ const db = getTargetDb4();
1371
+ const subgraphs = (await listSubgraphs2(db)).filter((v) => v.status === "active");
1366
1372
  cleanupCaches(subgraphs);
1367
1373
  for (const sg of subgraphs) {
1368
1374
  try {
@@ -1371,7 +1377,7 @@ async function startSubgraphProcessor(opts) {
1371
1377
  } catch (err) {
1372
1378
  const msg = getErrorMessage3(err);
1373
1379
  if (isHandlerNotFoundError(err)) {
1374
- await updateSubgraphStatus2(db2, sg.name, "error");
1380
+ await updateSubgraphStatus2(db, sg.name, "error");
1375
1381
  }
1376
1382
  logger6.error("Subgraph processing failed", {
1377
1383
  subgraph: sg.name,
@@ -1379,7 +1385,7 @@ async function startSubgraphProcessor(opts) {
1379
1385
  });
1380
1386
  }
1381
1387
  }
1382
- });
1388
+ }, { connectionString: sourceListenerUrl() });
1383
1389
  const stopReorgListening = await listen("subgraph_reorg", async (payload) => {
1384
1390
  if (!running)
1385
1391
  return;
@@ -1394,12 +1400,12 @@ async function startSubgraphProcessor(opts) {
1394
1400
  error: getErrorMessage3(err)
1395
1401
  });
1396
1402
  }
1397
- });
1403
+ }, { connectionString: sourceListenerUrl() });
1398
1404
  const pollInterval = setInterval(async () => {
1399
1405
  if (!running)
1400
1406
  return;
1401
- const db2 = getDb4();
1402
- const subgraphs = (await listSubgraphs2(db2)).filter((v) => v.status === "active");
1407
+ const db = getTargetDb4();
1408
+ const subgraphs = (await listSubgraphs2(db)).filter((v) => v.status === "active");
1403
1409
  cleanupCaches(subgraphs);
1404
1410
  for (const sg of subgraphs) {
1405
1411
  try {
@@ -1436,5 +1442,5 @@ var shutdown = async () => {
1436
1442
  process.on("SIGINT", shutdown);
1437
1443
  process.on("SIGTERM", shutdown);
1438
1444
 
1439
- //# debugId=6B8A7042CE1346D164756E2164756E21
1445
+ //# debugId=403B5FB854EE82EB64756E2164756E21
1440
1446
  //# sourceMappingURL=service.js.map