@secondlayer/subgraphs 3.26.1 → 3.26.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.
package/dist/src/index.js CHANGED
@@ -3259,9 +3259,278 @@ class StatsAccumulator {
3259
3259
  }
3260
3260
  }
3261
3261
 
3262
+ // src/runtime/catchup.ts
3263
+ import { getTargetDb as getTargetDb2, sql as sql4 } from "@secondlayer/shared/db";
3264
+ import { getSubgraph } from "@secondlayer/shared/db/queries/subgraphs";
3265
+ import { logger as logger8 } from "@secondlayer/shared/logger";
3266
+
3267
+ // src/runtime/catchup-leader.ts
3268
+ import {
3269
+ SUBGRAPH_CATCHUP_LOCK_KEY,
3270
+ createPostgresLeaderBackend,
3271
+ withLeaderLock
3272
+ } from "@secondlayer/shared/leader";
3273
+ import { targetListenerUrl } from "@secondlayer/shared/queue/listener";
3274
+ var catchUpLeader = false;
3275
+ function isCatchUpLeader() {
3276
+ return catchUpLeader;
3277
+ }
3278
+ function startCatchUpLeader(opts = {}) {
3279
+ return withLeaderLock(SUBGRAPH_CATCHUP_LOCK_KEY, async () => {
3280
+ catchUpLeader = true;
3281
+ await opts.onAcquire?.();
3282
+ return () => {
3283
+ catchUpLeader = false;
3284
+ };
3285
+ }, {
3286
+ pollMs: opts.pollMs,
3287
+ heartbeatMs: opts.heartbeatMs,
3288
+ createBackend: opts.createBackend ?? (() => createPostgresLeaderBackend(targetListenerUrl()))
3289
+ });
3290
+ }
3291
+
3292
+ // src/runtime/catchup.ts
3293
+ var LOG_INTERVAL = 1000;
3294
+ var STANDARD_CATCHUP_BATCH_CONFIG = {
3295
+ defaultBatchSize: 500,
3296
+ minBatchSize: 100,
3297
+ maxBatchSize: 1000,
3298
+ prefetch: true
3299
+ };
3300
+ var catchingUp = new Set;
3301
+ var subgraphBlockLockHeld = new Set;
3302
+ var subgraphBlockLockWaiters = new Map;
3303
+ var reorgEpoch = new Map;
3304
+ async function acquireSubgraphBlockLock(name) {
3305
+ if (!subgraphBlockLockHeld.has(name)) {
3306
+ subgraphBlockLockHeld.add(name);
3307
+ return () => releaseSubgraphBlockLock(name);
3308
+ }
3309
+ return new Promise((resolve) => {
3310
+ const waiters = subgraphBlockLockWaiters.get(name) ?? [];
3311
+ waiters.push(() => resolve(() => releaseSubgraphBlockLock(name)));
3312
+ subgraphBlockLockWaiters.set(name, waiters);
3313
+ });
3314
+ }
3315
+ function releaseSubgraphBlockLock(name) {
3316
+ const waiters = subgraphBlockLockWaiters.get(name);
3317
+ if (waiters && waiters.length > 0) {
3318
+ const next = waiters.shift();
3319
+ if (waiters.length === 0)
3320
+ subgraphBlockLockWaiters.delete(name);
3321
+ next();
3322
+ return;
3323
+ }
3324
+ subgraphBlockLockHeld.delete(name);
3325
+ }
3326
+ async function withSubgraphBlockLock(name, fn) {
3327
+ const release = await acquireSubgraphBlockLock(name);
3328
+ try {
3329
+ return await fn();
3330
+ } finally {
3331
+ release();
3332
+ }
3333
+ }
3334
+ async function withSubgraphBlockAdvisoryLock(name, fn) {
3335
+ return getTargetDb2().transaction().execute(async (lockTx) => {
3336
+ await sql4`SELECT pg_advisory_xact_lock(hashtext(${`subgraph-block:${name}`}))`.execute(lockTx);
3337
+ return fn();
3338
+ });
3339
+ }
3340
+ async function withSubgraphBlockWriteLock(name, fn) {
3341
+ return withSubgraphBlockLock(name, () => withSubgraphBlockAdvisoryLock(name, fn));
3342
+ }
3343
+ function bumpReorgEpoch(name) {
3344
+ reorgEpoch.set(name, (reorgEpoch.get(name) ?? 0) + 1);
3345
+ }
3346
+ function getReorgEpoch(name) {
3347
+ return reorgEpoch.get(name) ?? 0;
3348
+ }
3349
+
3350
+ class ReorgEpochChangedError extends Error {
3351
+ constructor(name) {
3352
+ super(`reorg epoch changed for ${name} mid catch-up`);
3353
+ this.name = "ReorgEpochChangedError";
3354
+ }
3355
+ }
3356
+ function parsePositiveInt(value) {
3357
+ if (value == null || value.trim() === "")
3358
+ return;
3359
+ const parsed = Number.parseInt(value, 10);
3360
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
3361
+ }
3362
+ function parseBoolean(value) {
3363
+ if (value == null || value.trim() === "")
3364
+ return;
3365
+ const normalized = value.trim().toLowerCase();
3366
+ if (normalized === "true")
3367
+ return true;
3368
+ if (normalized === "false")
3369
+ return false;
3370
+ return;
3371
+ }
3372
+ function resolveCatchupBatchConfig(env = process.env) {
3373
+ const base = STANDARD_CATCHUP_BATCH_CONFIG;
3374
+ const minBatchSize = parsePositiveInt(env.SUBGRAPH_CATCHUP_MIN_BATCH_SIZE) ?? base.minBatchSize;
3375
+ const maxBatchSize = parsePositiveInt(env.SUBGRAPH_CATCHUP_MAX_BATCH_SIZE) ?? base.maxBatchSize;
3376
+ const defaultBatchSize = parsePositiveInt(env.SUBGRAPH_CATCHUP_BATCH_SIZE) ?? base.defaultBatchSize;
3377
+ return {
3378
+ minBatchSize,
3379
+ maxBatchSize,
3380
+ defaultBatchSize: Math.min(Math.max(defaultBatchSize, minBatchSize), maxBatchSize),
3381
+ prefetch: parseBoolean(env.SUBGRAPH_CATCHUP_PREFETCH) ?? base.prefetch
3382
+ };
3383
+ }
3384
+ function adjustBatchSize(current, avgEvents, config) {
3385
+ if (avgEvents > 50)
3386
+ return Math.max(Math.round(current * 0.5), config.minBatchSize);
3387
+ if (avgEvents < 10)
3388
+ return Math.min(Math.round(current * 1.5), config.maxBatchSize);
3389
+ return current;
3390
+ }
3391
+ async function catchUpSubgraph(subgraph, subgraphName) {
3392
+ if (catchingUp.has(subgraphName))
3393
+ return 0;
3394
+ catchingUp.add(subgraphName);
3395
+ try {
3396
+ const source = resolveBlockSource(subgraph);
3397
+ const targetDb = getTargetDb2();
3398
+ const subgraphRow = await getSubgraph(targetDb, subgraphName);
3399
+ if (!subgraphRow)
3400
+ return 0;
3401
+ const lastProcessedBlock = Number(subgraphRow.last_processed_block);
3402
+ const chainTip = await source.getTip();
3403
+ if (chainTip <= 0 || lastProcessedBlock >= chainTip)
3404
+ return 0;
3405
+ const subgraphStart = Number(subgraphRow.start_block) || 1;
3406
+ const startBlock = Math.max(lastProcessedBlock + 1, subgraphStart);
3407
+ const totalBlocks = chainTip - lastProcessedBlock;
3408
+ logger8.info("Subgraph catch-up starting", {
3409
+ subgraph: subgraphName,
3410
+ from: startBlock,
3411
+ to: chainTip,
3412
+ blocks: totalBlocks
3413
+ });
3414
+ const stats = new StatsAccumulator(subgraphName, true);
3415
+ let processed = 0;
3416
+ const batchConfig = resolveCatchupBatchConfig();
3417
+ let batchSize = batchConfig.defaultBatchSize;
3418
+ let currentHeight = startBlock;
3419
+ const walkEpoch = getReorgEpoch(subgraphName);
3420
+ let prefetchedBatchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
3421
+ let nextBatchPromise = batchConfig.prefetch ? source.loadBlockRange(currentHeight, prefetchedBatchEnd) : undefined;
3422
+ while (currentHeight <= chainTip) {
3423
+ if (!isCatchUpLeader()) {
3424
+ logger8.info("Lost catch-up leadership, stopping catch-up", {
3425
+ subgraph: subgraphName,
3426
+ processed
3427
+ });
3428
+ break;
3429
+ }
3430
+ const currentRow = await getSubgraph(targetDb, subgraphName);
3431
+ if (!currentRow || currentRow.status !== "active") {
3432
+ logger8.info("Subgraph status changed, stopping catch-up", {
3433
+ subgraph: subgraphName,
3434
+ status: currentRow?.status ?? "deleted"
3435
+ });
3436
+ break;
3437
+ }
3438
+ let batchEnd;
3439
+ let batch;
3440
+ if (nextBatchPromise) {
3441
+ batch = await nextBatchPromise;
3442
+ batchEnd = prefetchedBatchEnd;
3443
+ const nextStart = batchEnd + 1;
3444
+ if (nextStart <= chainTip) {
3445
+ prefetchedBatchEnd = Math.min(nextStart + batchSize - 1, chainTip);
3446
+ nextBatchPromise = source.loadBlockRange(nextStart, prefetchedBatchEnd);
3447
+ } else {
3448
+ nextBatchPromise = undefined;
3449
+ }
3450
+ } else {
3451
+ batchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
3452
+ batch = await source.loadBlockRange(currentHeight, batchEnd);
3453
+ }
3454
+ let stopCatchup = false;
3455
+ for (let height = currentHeight;height <= batchEnd; height++) {
3456
+ let blockData = batch.get(height);
3457
+ if (!blockData) {
3458
+ blockData = (await source.loadBlockRange(height, height)).get(height);
3459
+ }
3460
+ if (!blockData) {
3461
+ logger8.warn("Block missing during catch-up, deferring to next tick", {
3462
+ subgraph: subgraphName,
3463
+ blockHeight: height
3464
+ });
3465
+ stopCatchup = true;
3466
+ break;
3467
+ }
3468
+ const preloaded = blockData;
3469
+ let result;
3470
+ try {
3471
+ result = await withSubgraphBlockWriteLock(subgraphName, async () => {
3472
+ if (getReorgEpoch(subgraphName) !== walkEpoch) {
3473
+ throw new ReorgEpochChangedError(subgraphName);
3474
+ }
3475
+ return processBlockWithRetry(subgraph, subgraphName, height, {
3476
+ preloaded
3477
+ });
3478
+ });
3479
+ } catch (err) {
3480
+ if (err instanceof ReorgEpochChangedError) {
3481
+ logger8.info("Reorg detected mid catch-up, aborting walk without writing further progress", { subgraph: subgraphName, blockHeight: height });
3482
+ stopCatchup = true;
3483
+ break;
3484
+ }
3485
+ const errorMsg = err instanceof Error ? err.message : String(err);
3486
+ logger8.error("Block processing failed persistently during catch-up", {
3487
+ subgraph: subgraphName,
3488
+ blockHeight: height,
3489
+ error: errorMsg
3490
+ });
3491
+ const { updateSubgraphStatus: updateSubgraphStatus2, recordSubgraphProcessed: recordSubgraphProcessed2 } = await import("@secondlayer/shared/db/queries/subgraphs");
3492
+ await recordSubgraphProcessed2(targetDb, subgraphName, 0, 1, `catch-up halted at block ${height}: ${errorMsg}`).catch(() => {});
3493
+ await updateSubgraphStatus2(targetDb, subgraphName, "error").catch(() => {});
3494
+ stopCatchup = true;
3495
+ break;
3496
+ }
3497
+ processed++;
3498
+ if (result.timing) {
3499
+ stats.record(result.timing, result.processed);
3500
+ if (stats.shouldFlush()) {
3501
+ await stats.flush(targetDb);
3502
+ }
3503
+ }
3504
+ if (processed % LOG_INTERVAL === 0) {
3505
+ logger8.info("Subgraph catch-up progress", {
3506
+ subgraph: subgraphName,
3507
+ processed,
3508
+ total: totalBlocks,
3509
+ currentBlock: height,
3510
+ pct: Math.round(processed / totalBlocks * 100)
3511
+ });
3512
+ }
3513
+ }
3514
+ if (stopCatchup)
3515
+ break;
3516
+ const avg = avgEventsPerBlock(batch);
3517
+ batchSize = adjustBatchSize(batchSize, avg, batchConfig);
3518
+ currentHeight = batchEnd + 1;
3519
+ }
3520
+ await stats.flush(targetDb);
3521
+ logger8.info("Subgraph catch-up complete", {
3522
+ subgraph: subgraphName,
3523
+ processed
3524
+ });
3525
+ return processed;
3526
+ } finally {
3527
+ catchingUp.delete(subgraphName);
3528
+ }
3529
+ }
3530
+
3262
3531
  // src/runtime/reindex.ts
3263
3532
  import { getErrorMessage as getErrorMessage3 } from "@secondlayer/shared";
3264
- import { getRawClient, getTargetDb as getTargetDb2 } from "@secondlayer/shared/db";
3533
+ import { getRawClient, getTargetDb as getTargetDb3 } from "@secondlayer/shared/db";
3265
3534
  import {
3266
3535
  recordGapBatch,
3267
3536
  resolveGaps
@@ -3274,11 +3543,11 @@ import {
3274
3543
  recordSubgraphProcessed as recordSubgraphProcessed2,
3275
3544
  updateSubgraphStatus as updateSubgraphStatus2
3276
3545
  } from "@secondlayer/shared/db/queries/subgraphs";
3277
- import { logger as logger9 } from "@secondlayer/shared/logger";
3546
+ import { logger as logger10 } from "@secondlayer/shared/logger";
3278
3547
 
3279
3548
  // src/runtime/reindex-notify.ts
3280
3549
  import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
3281
- import { logger as logger8 } from "@secondlayer/shared/logger";
3550
+ import { logger as logger9 } from "@secondlayer/shared/logger";
3282
3551
  async function notifyReindexComplete(db, subgraphName, stats) {
3283
3552
  try {
3284
3553
  const subgraph = await db.selectFrom("subgraphs").select(["account_id"]).where("name", "=", subgraphName).executeTakeFirst();
@@ -3289,7 +3558,7 @@ async function notifyReindexComplete(db, subgraphName, stats) {
3289
3558
  return;
3290
3559
  const resendKey = process.env.RESEND_API_KEY;
3291
3560
  if (!resendKey) {
3292
- logger8.warn("RESEND_API_KEY unset — skipping reindex-complete email", {
3561
+ logger9.warn("RESEND_API_KEY unset — skipping reindex-complete email", {
3293
3562
  subgraph: subgraphName
3294
3563
  });
3295
3564
  return;
@@ -3311,14 +3580,14 @@ async function notifyReindexComplete(db, subgraphName, stats) {
3311
3580
  });
3312
3581
  if (!res.ok) {
3313
3582
  const text = await res.text().catch(() => "");
3314
- logger8.warn("reindex-complete email failed", {
3583
+ logger9.warn("reindex-complete email failed", {
3315
3584
  subgraph: subgraphName,
3316
3585
  status: res.status,
3317
3586
  body: text.slice(0, 200)
3318
3587
  });
3319
3588
  }
3320
3589
  } catch (err) {
3321
- logger8.warn("reindex-complete email threw", {
3590
+ logger9.warn("reindex-complete email threw", {
3322
3591
  subgraph: subgraphName,
3323
3592
  error: getErrorMessage2(err)
3324
3593
  });
@@ -3326,7 +3595,7 @@ async function notifyReindexComplete(db, subgraphName, stats) {
3326
3595
  }
3327
3596
 
3328
3597
  // src/runtime/reindex.ts
3329
- var LOG_INTERVAL = 1000;
3598
+ var LOG_INTERVAL2 = 1000;
3330
3599
  var HEALTH_FLUSH_INTERVAL = 1000;
3331
3600
  var PROGRESS_FLUSH_INTERVAL_MS = 5000;
3332
3601
  var EMPTY_BATCH_HALT_THRESHOLD = 3;
@@ -3346,7 +3615,7 @@ function resolveReindexResumeBlock(row) {
3346
3615
  const reindexFromBlock = Number(row.reindex_from_block);
3347
3616
  return Math.max(lastProcessedBlock + 1, reindexFromBlock);
3348
3617
  }
3349
- function parsePositiveInt(value) {
3618
+ function parsePositiveInt2(value) {
3350
3619
  if (value == null || value.trim() === "")
3351
3620
  return;
3352
3621
  const parsed = Number.parseInt(value, 10);
@@ -3354,9 +3623,9 @@ function parsePositiveInt(value) {
3354
3623
  }
3355
3624
  function resolveReindexBatchConfig(env = process.env) {
3356
3625
  const base = STANDARD_REINDEX_BATCH_CONFIG;
3357
- const minBatchSize = parsePositiveInt(env.SUBGRAPH_REINDEX_MIN_BATCH_SIZE) ?? base.minBatchSize;
3358
- const maxBatchSize = parsePositiveInt(env.SUBGRAPH_REINDEX_MAX_BATCH_SIZE) ?? base.maxBatchSize;
3359
- const defaultBatchSize = parsePositiveInt(env.SUBGRAPH_REINDEX_BATCH_SIZE) ?? base.defaultBatchSize;
3626
+ const minBatchSize = parsePositiveInt2(env.SUBGRAPH_REINDEX_MIN_BATCH_SIZE) ?? base.minBatchSize;
3627
+ const maxBatchSize = parsePositiveInt2(env.SUBGRAPH_REINDEX_MAX_BATCH_SIZE) ?? base.maxBatchSize;
3628
+ const defaultBatchSize = parsePositiveInt2(env.SUBGRAPH_REINDEX_BATCH_SIZE) ?? base.defaultBatchSize;
3360
3629
  return {
3361
3630
  minBatchSize,
3362
3631
  maxBatchSize,
@@ -3387,7 +3656,7 @@ function coalesceFailedBlocks(blocks) {
3387
3656
  }
3388
3657
  async function processBlockRange(def, opts) {
3389
3658
  const source = resolveBlockSource(def);
3390
- const targetDb = getTargetDb2();
3659
+ const targetDb = getTargetDb3();
3391
3660
  const subgraphName = def.name;
3392
3661
  const { fromBlock, toBlock, status } = opts;
3393
3662
  const totalBlocks = toBlock - fromBlock + 1;
@@ -3430,7 +3699,7 @@ async function processBlockRange(def, opts) {
3430
3699
  while (currentHeight <= toBlock) {
3431
3700
  if (opts.signal?.aborted) {
3432
3701
  aborted = true;
3433
- logger9.info("Block processing aborted", {
3702
+ logger10.info("Block processing aborted", {
3434
3703
  subgraph: subgraphName,
3435
3704
  currentBlock: currentHeight,
3436
3705
  reason: String(opts.signal.reason ?? "unknown")
@@ -3472,14 +3741,16 @@ async function processBlockRange(def, opts) {
3472
3741
  }
3473
3742
  let result;
3474
3743
  try {
3475
- result = await processBlockWithRetry(def, subgraphName, height, {
3744
+ const mayWrite = blockData.txs.length > 0 || blockData.events.length > 0;
3745
+ const runBlock = () => processBlockWithRetry(def, subgraphName, height, {
3476
3746
  skipProgressUpdate: true,
3477
3747
  atomicProgress,
3478
3748
  preloaded: blockData
3479
3749
  });
3750
+ result = mayWrite ? await withSubgraphBlockWriteLock(subgraphName, runBlock) : await runBlock();
3480
3751
  } catch (err) {
3481
3752
  const errorMsg = getErrorMessage3(err);
3482
- logger9.error("Block processing failed persistently", {
3753
+ logger10.error("Block processing failed persistently", {
3483
3754
  subgraph: subgraphName,
3484
3755
  blockHeight: height,
3485
3756
  error: errorMsg
@@ -3524,8 +3795,8 @@ async function processBlockRange(def, opts) {
3524
3795
  }
3525
3796
  lastProgressFlushAt = now;
3526
3797
  }
3527
- if (blocksProcessed % LOG_INTERVAL === 0) {
3528
- logger9.info(`${status === "reindexing" ? "Reindex" : "Backfill"} progress`, {
3798
+ if (blocksProcessed % LOG_INTERVAL2 === 0) {
3799
+ logger10.info(`${status === "reindexing" ? "Reindex" : "Backfill"} progress`, {
3529
3800
  subgraph: subgraphName,
3530
3801
  processed: blocksProcessed,
3531
3802
  total: totalBlocks,
@@ -3545,7 +3816,7 @@ async function processBlockRange(def, opts) {
3545
3816
  if (batchFailedBlocks.length > 0 && opts.subgraphId) {
3546
3817
  const gaps = coalesceFailedBlocks(batchFailedBlocks);
3547
3818
  await recordGapBatch(targetDb, opts.subgraphId, subgraphName, gaps).catch((err) => {
3548
- logger9.warn("Failed to record subgraph gaps", {
3819
+ logger10.warn("Failed to record subgraph gaps", {
3549
3820
  subgraph: subgraphName,
3550
3821
  error: err instanceof Error ? err.message : String(err)
3551
3822
  });
@@ -3562,7 +3833,7 @@ async function processBlockRange(def, opts) {
3562
3833
  } else {
3563
3834
  await updateSubgraphStatus2(targetDb, subgraphName, status, jumpTo - 1);
3564
3835
  }
3565
- logger9.info("Sparse skip", {
3836
+ logger10.info("Sparse skip", {
3566
3837
  subgraph: subgraphName,
3567
3838
  from: batchEnd + 1,
3568
3839
  to: jumpTo - 1,
@@ -3597,16 +3868,16 @@ async function clearReindexMetadata(db, subgraphName) {
3597
3868
  }
3598
3869
  async function reindexSubgraph(def, opts) {
3599
3870
  const source = resolveBlockSource(def);
3600
- const targetDb = getTargetDb2();
3871
+ const targetDb = getTargetDb3();
3601
3872
  const client = getRawClient("target");
3602
3873
  const subgraphName = def.name;
3603
3874
  const schemaName = opts?.schemaName ?? pgSchemaName(subgraphName);
3604
3875
  await updateSubgraphStatus2(targetDb, subgraphName, "reindexing");
3605
- logger9.info("Reindex starting", { subgraph: subgraphName });
3876
+ logger10.info("Reindex starting", { subgraph: subgraphName });
3606
3877
  try {
3607
3878
  const { fromBlock, toBlock } = await resolveBlockRange(source, def, opts);
3608
3879
  if (fromBlock > toBlock) {
3609
- logger9.info("No blocks to reindex", {
3880
+ logger10.info("No blocks to reindex", {
3610
3881
  subgraph: subgraphName,
3611
3882
  fromBlock,
3612
3883
  toBlock
@@ -3620,7 +3891,7 @@ async function reindexSubgraph(def, opts) {
3620
3891
  await client.unsafe(stmt);
3621
3892
  }
3622
3893
  await updateSubgraphStatus2(targetDb, subgraphName, "reindexing", Math.max(0, fromBlock - 1));
3623
- logger9.info("Schema recreated for reindex", {
3894
+ logger10.info("Schema recreated for reindex", {
3624
3895
  subgraph: subgraphName,
3625
3896
  cursorResetTo: Math.max(0, fromBlock - 1)
3626
3897
  });
@@ -3634,7 +3905,7 @@ async function reindexSubgraph(def, opts) {
3634
3905
  last_error_at: null,
3635
3906
  updated_at: new Date
3636
3907
  }).where("name", "=", subgraphName).execute();
3637
- logger9.info("Reindexing blocks", {
3908
+ logger10.info("Reindexing blocks", {
3638
3909
  subgraph: subgraphName,
3639
3910
  fromBlock,
3640
3911
  toBlock,
@@ -3656,9 +3927,9 @@ async function reindexSubgraph(def, opts) {
3656
3927
  if (reason === "user-cancelled") {
3657
3928
  await updateSubgraphStatus2(targetDb, subgraphName, "active");
3658
3929
  await clearReindexMetadata(targetDb, subgraphName);
3659
- logger9.info("Reindex cancelled by user", { subgraph: subgraphName });
3930
+ logger10.info("Reindex cancelled by user", { subgraph: subgraphName });
3660
3931
  } else {
3661
- logger9.info("Reindex interrupted by shutdown, will resume", {
3932
+ logger10.info("Reindex interrupted by shutdown, will resume", {
3662
3933
  subgraph: subgraphName
3663
3934
  });
3664
3935
  }
@@ -3666,7 +3937,7 @@ async function reindexSubgraph(def, opts) {
3666
3937
  }
3667
3938
  await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
3668
3939
  await clearReindexMetadata(targetDb, subgraphName);
3669
- logger9.info("Reindex complete", {
3940
+ logger10.info("Reindex complete", {
3670
3941
  subgraph: subgraphName,
3671
3942
  blocks: result.blocksProcessed,
3672
3943
  events: result.totalEventsProcessed,
@@ -3679,7 +3950,7 @@ async function reindexSubgraph(def, opts) {
3679
3950
  });
3680
3951
  return { processed: result.blocksProcessed };
3681
3952
  } catch (err) {
3682
- logger9.error("Reindex failed", {
3953
+ logger10.error("Reindex failed", {
3683
3954
  subgraph: subgraphName,
3684
3955
  error: getErrorMessage3(err)
3685
3956
  });
@@ -3688,7 +3959,7 @@ async function reindexSubgraph(def, opts) {
3688
3959
  }
3689
3960
  }
3690
3961
  async function resumeReindex(def, opts) {
3691
- const targetDb = getTargetDb2();
3962
+ const targetDb = getTargetDb3();
3692
3963
  const subgraphName = def.name;
3693
3964
  const row = await targetDb.selectFrom("subgraphs").select([
3694
3965
  "id",
@@ -3701,7 +3972,7 @@ async function resumeReindex(def, opts) {
3701
3972
  const fromBlock = resolveReindexResumeBlock(row);
3702
3973
  const toBlock = Number(row.reindex_to_block);
3703
3974
  if (fromBlock == null) {
3704
- logger9.info("No reindex metadata, starting fresh reindex", {
3975
+ logger10.info("No reindex metadata, starting fresh reindex", {
3705
3976
  subgraph: subgraphName
3706
3977
  });
3707
3978
  return reindexSubgraph(def, {
@@ -3710,12 +3981,12 @@ async function resumeReindex(def, opts) {
3710
3981
  });
3711
3982
  }
3712
3983
  if (fromBlock > toBlock) {
3713
- logger9.info("Resume: no remaining blocks", { subgraph: subgraphName });
3984
+ logger10.info("Resume: no remaining blocks", { subgraph: subgraphName });
3714
3985
  await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
3715
3986
  await clearReindexMetadata(targetDb, subgraphName);
3716
3987
  return { processed: 0 };
3717
3988
  }
3718
- logger9.info("Resuming reindex", {
3989
+ logger10.info("Resuming reindex", {
3719
3990
  subgraph: subgraphName,
3720
3991
  fromBlock,
3721
3992
  toBlock,
@@ -3737,9 +4008,9 @@ async function resumeReindex(def, opts) {
3737
4008
  if (reason === "user-cancelled") {
3738
4009
  await updateSubgraphStatus2(targetDb, subgraphName, "active");
3739
4010
  await clearReindexMetadata(targetDb, subgraphName);
3740
- logger9.info("Resume cancelled by user", { subgraph: subgraphName });
4011
+ logger10.info("Resume cancelled by user", { subgraph: subgraphName });
3741
4012
  } else {
3742
- logger9.info("Resume interrupted by shutdown, will resume again", {
4013
+ logger10.info("Resume interrupted by shutdown, will resume again", {
3743
4014
  subgraph: subgraphName
3744
4015
  });
3745
4016
  }
@@ -3747,13 +4018,13 @@ async function resumeReindex(def, opts) {
3747
4018
  }
3748
4019
  await updateSubgraphStatus2(targetDb, subgraphName, "active", toBlock);
3749
4020
  await clearReindexMetadata(targetDb, subgraphName);
3750
- logger9.info("Resumed reindex complete", {
4021
+ logger10.info("Resumed reindex complete", {
3751
4022
  subgraph: subgraphName,
3752
4023
  blocks: result.blocksProcessed
3753
4024
  });
3754
4025
  return { processed: result.blocksProcessed };
3755
4026
  } catch (err) {
3756
- logger9.error("Resumed reindex failed", {
4027
+ logger10.error("Resumed reindex failed", {
3757
4028
  subgraph: subgraphName,
3758
4029
  error: getErrorMessage3(err)
3759
4030
  });
@@ -3762,9 +4033,9 @@ async function resumeReindex(def, opts) {
3762
4033
  }
3763
4034
  }
3764
4035
  async function backfillSubgraph(def, opts) {
3765
- const targetDb = getTargetDb2();
4036
+ const targetDb = getTargetDb3();
3766
4037
  const subgraphName = def.name;
3767
- logger9.info("Backfill starting", {
4038
+ logger10.info("Backfill starting", {
3768
4039
  subgraph: subgraphName,
3769
4040
  from: opts.fromBlock,
3770
4041
  to: opts.toBlock
@@ -3782,17 +4053,17 @@ async function backfillSubgraph(def, opts) {
3782
4053
  signal: opts.signal
3783
4054
  });
3784
4055
  if (result.aborted) {
3785
- logger9.info("Backfill aborted", { subgraph: subgraphName });
4056
+ logger10.info("Backfill aborted", { subgraph: subgraphName });
3786
4057
  return { processed: result.blocksProcessed };
3787
4058
  }
3788
4059
  const resolved = await resolveGaps(targetDb, subgraphName, opts.fromBlock, opts.toBlock).catch(() => 0);
3789
4060
  if (resolved > 0) {
3790
- logger9.info("Resolved subgraph gaps via backfill", {
4061
+ logger10.info("Resolved subgraph gaps via backfill", {
3791
4062
  subgraph: subgraphName,
3792
4063
  resolved
3793
4064
  });
3794
4065
  }
3795
- logger9.info("Backfill complete", {
4066
+ logger10.info("Backfill complete", {
3796
4067
  subgraph: subgraphName,
3797
4068
  blocks: result.blocksProcessed,
3798
4069
  events: result.totalEventsProcessed,
@@ -3800,7 +4071,7 @@ async function backfillSubgraph(def, opts) {
3800
4071
  });
3801
4072
  return { processed: result.blocksProcessed };
3802
4073
  } catch (err) {
3803
- logger9.error("Backfill failed", {
4074
+ logger10.error("Backfill failed", {
3804
4075
  subgraph: subgraphName,
3805
4076
  error: getErrorMessage3(err)
3806
4077
  });
@@ -4721,7 +4992,7 @@ function generateIndexSchema(target, opts = {}) {
4721
4992
  }
4722
4993
  var INDEX_CODEGEN_TABLES = Object.keys(SOURCE_READ_TYPES);
4723
4994
  // src/schema/deployer.ts
4724
- import { sql as sql4 } from "kysely";
4995
+ import { sql as sql5 } from "kysely";
4725
4996
  function toJsonSafe(obj) {
4726
4997
  return JSON.parse(JSON.stringify(obj, (_key, value) => typeof value === "bigint" ? value.toString() : value));
4727
4998
  }
@@ -4836,7 +5107,7 @@ function renderDeployPlan(def, schemaName) {
4836
5107
  async function deploySchema(db, def, handlerPath, opts) {
4837
5108
  validateSubgraphDefinition(def);
4838
5109
  const { statements, hash } = generateSubgraphSQL(def, opts?.schemaName);
4839
- const { getSubgraph, registerSubgraph } = await import("@secondlayer/shared/db/queries/subgraphs");
5110
+ const { getSubgraph: getSubgraph2, registerSubgraph } = await import("@secondlayer/shared/db/queries/subgraphs");
4840
5111
  const ddlDb = opts?.dataDb ?? db;
4841
5112
  const byo = opts?.dataDb != null;
4842
5113
  const refuseDestructiveOnByo = (reasons, diff) => {
@@ -4848,7 +5119,7 @@ async function deploySchema(db, def, handlerPath, opts) {
4848
5119
  grantScript: plan.grantScript
4849
5120
  });
4850
5121
  };
4851
- const existing = await getSubgraph(db, def.name, opts?.accountId);
5122
+ const existing = await getSubgraph2(db, def.name, opts?.accountId);
4852
5123
  const schemaName = opts?.schemaName ?? pgSchemaName(def.name);
4853
5124
  const newVersion = opts?.version ?? (existing ? bumpPatch(existing.version) : "1.0.0");
4854
5125
  const regData = {
@@ -4873,7 +5144,7 @@ async function deploySchema(db, def, handlerPath, opts) {
4873
5144
  databaseUrlEnc: opts?.databaseUrlEnc ?? null
4874
5145
  };
4875
5146
  if (existing) {
4876
- const schemaExists = await sql4`
5147
+ const schemaExists = await sql5`
4877
5148
  SELECT EXISTS (
4878
5149
  SELECT 1 FROM information_schema.schemata
4879
5150
  WHERE schema_name = ${schemaName}
@@ -4881,7 +5152,7 @@ async function deploySchema(db, def, handlerPath, opts) {
4881
5152
  `.execute(ddlDb).then((r) => r.rows[0]?.exists ?? false);
4882
5153
  if (!schemaExists) {
4883
5154
  for (const stmt of statements) {
4884
- await sql4.raw(stmt).execute(ddlDb);
5155
+ await sql5.raw(stmt).execute(ddlDb);
4885
5156
  }
4886
5157
  const sg2 = await registerSubgraph(db, regData);
4887
5158
  return { action: "reindexed", subgraphId: sg2.id, version: newVersion };
@@ -4907,9 +5178,9 @@ async function deploySchema(db, def, handlerPath, opts) {
4907
5178
  if (existing.schema_hash === hash && opts?.forceReindex) {
4908
5179
  if (byo)
4909
5180
  refuseDestructiveOnByo(["force reindex"], null);
4910
- await sql4.raw(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`).execute(ddlDb);
5181
+ await sql5.raw(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`).execute(ddlDb);
4911
5182
  for (const stmt of statements) {
4912
- await sql4.raw(stmt).execute(ddlDb);
5183
+ await sql5.raw(stmt).execute(ddlDb);
4913
5184
  }
4914
5185
  const sg2 = await registerSubgraph(db, regData);
4915
5186
  return { action: "reindexed", subgraphId: sg2.id, version: newVersion };
@@ -4921,9 +5192,9 @@ async function deploySchema(db, def, handlerPath, opts) {
4921
5192
  if (byo) {
4922
5193
  refuseDestructiveOnByo(reasons.length > 0 ? reasons : ["force reindex"], diff);
4923
5194
  }
4924
- await sql4.raw(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`).execute(ddlDb);
5195
+ await sql5.raw(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`).execute(ddlDb);
4925
5196
  for (const stmt of statements) {
4926
- await sql4.raw(stmt).execute(ddlDb);
5197
+ await sql5.raw(stmt).execute(ddlDb);
4927
5198
  }
4928
5199
  const sg3 = await registerSubgraph(db, regData);
4929
5200
  const deployDiff2 = toDeployDiff(diff, reasons);
@@ -4936,16 +5207,16 @@ async function deploySchema(db, def, handlerPath, opts) {
4936
5207
  }
4937
5208
  const addedDefs = diff.addedTables.map((tableName) => ({ tableName, tableDef: def.schema[tableName] })).filter((t) => t.tableDef !== undefined);
4938
5209
  if (addedDefs.some(({ tableDef }) => tableNeedsTrgm(tableDef))) {
4939
- await sql4.raw("CREATE EXTENSION IF NOT EXISTS pg_trgm").execute(ddlDb);
5210
+ await sql5.raw("CREATE EXTENSION IF NOT EXISTS pg_trgm").execute(ddlDb);
4940
5211
  }
4941
5212
  for (const { tableName, tableDef } of addedDefs) {
4942
5213
  for (const stmt of emitTableDDL(schemaName, tableName, tableDef)) {
4943
- await sql4.raw(stmt).execute(ddlDb);
5214
+ await sql5.raw(stmt).execute(ddlDb);
4944
5215
  }
4945
5216
  }
4946
5217
  for (const { tableName, tableDef } of addedDefs) {
4947
5218
  for (const stmt of emitForeignKeyDDL(schemaName, tableName, tableDef)) {
4948
- await sql4.raw(stmt).execute(ddlDb);
5219
+ await sql5.raw(stmt).execute(ddlDb);
4949
5220
  }
4950
5221
  }
4951
5222
  for (const [tableName, colDiff] of Object.entries(diff.tables)) {
@@ -4963,12 +5234,12 @@ async function deploySchema(db, def, handlerPath, opts) {
4963
5234
  if (!sqlType)
4964
5235
  continue;
4965
5236
  const nullable = col.nullable ? "" : ` NOT NULL DEFAULT ${getDefault(col.type)}`;
4966
- await sql4.raw(`ALTER TABLE ${qualifiedName} ADD COLUMN ${colName} ${sqlType}${nullable}`).execute(ddlDb);
5237
+ await sql5.raw(`ALTER TABLE ${qualifiedName} ADD COLUMN ${colName} ${sqlType}${nullable}`).execute(ddlDb);
4967
5238
  if (col.indexed) {
4968
- await sql4.raw(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName} ON ${qualifiedName} (${colName})`).execute(ddlDb);
5239
+ await sql5.raw(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName} ON ${qualifiedName} (${colName})`).execute(ddlDb);
4969
5240
  }
4970
5241
  if (col.search) {
4971
- await sql4.raw(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName}_trgm ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`).execute(ddlDb);
5242
+ await sql5.raw(`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName}_trgm ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`).execute(ddlDb);
4972
5243
  }
4973
5244
  }
4974
5245
  }
@@ -4976,7 +5247,7 @@ async function deploySchema(db, def, handlerPath, opts) {
4976
5247
  const flagFlips = {};
4977
5248
  const needsTrgmForFlips = Object.entries(diff.tables).some(([tableName, colDiff]) => colDiff.indexChanged.some((colName) => def.schema[tableName]?.columns[colName]?.search && !existingSchema[tableName]?.columns[colName]?.search));
4978
5249
  if (needsTrgmForFlips) {
4979
- await sql4.raw("CREATE EXTENSION IF NOT EXISTS pg_trgm").execute(ddlDb);
5250
+ await sql5.raw("CREATE EXTENSION IF NOT EXISTS pg_trgm").execute(ddlDb);
4980
5251
  }
4981
5252
  for (const [tableName, colDiff] of Object.entries(diff.tables)) {
4982
5253
  if (colDiff.indexChanged.length === 0)
@@ -4991,14 +5262,14 @@ async function deploySchema(db, def, handlerPath, opts) {
4991
5262
  const plainIdx = `idx_${schemaName}_${tableName}_${colName}`;
4992
5263
  const trgmIdx = `idx_${schemaName}_${tableName}_${colName}_trgm`;
4993
5264
  if (now.indexed && !was?.indexed) {
4994
- await sql4.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${plainIdx} ON ${qualifiedName} (${colName})`).execute(ddlDb);
5265
+ await sql5.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${plainIdx} ON ${qualifiedName} (${colName})`).execute(ddlDb);
4995
5266
  } else if (!now.indexed && was?.indexed) {
4996
- await sql4.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${plainIdx}`).execute(ddlDb);
5267
+ await sql5.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${plainIdx}`).execute(ddlDb);
4997
5268
  }
4998
5269
  if (now.search && !was?.search) {
4999
- await sql4.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${trgmIdx} ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`).execute(ddlDb);
5270
+ await sql5.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${trgmIdx} ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`).execute(ddlDb);
5000
5271
  } else if (!now.search && was?.search) {
5001
- await sql4.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${trgmIdx}`).execute(ddlDb);
5272
+ await sql5.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${trgmIdx}`).execute(ddlDb);
5002
5273
  }
5003
5274
  }
5004
5275
  }
@@ -5007,28 +5278,28 @@ async function deploySchema(db, def, handlerPath, opts) {
5007
5278
  const qualifiedName = `${schemaName}.${tableName}`;
5008
5279
  for (const cols of conDiff.addedUniqueKeys) {
5009
5280
  const constraintName = `uq_${schemaName}_${tableName}_${cols.join("_")}`;
5010
- const exists = await sql4`
5281
+ const exists = await sql5`
5011
5282
  SELECT EXISTS (
5012
5283
  SELECT 1 FROM pg_constraint
5013
5284
  WHERE conname = ${constraintName}
5014
5285
  ) AS "exists"
5015
5286
  `.execute(ddlDb).then((r) => r.rows[0]?.exists ?? false);
5016
5287
  if (!exists) {
5017
- await sql4.raw(`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.join(", ")})`).execute(ddlDb);
5288
+ await sql5.raw(`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.join(", ")})`).execute(ddlDb);
5018
5289
  }
5019
5290
  addedUq[tableName] = [...addedUq[tableName] ?? [], cols];
5020
5291
  }
5021
5292
  for (const cols of conDiff.addedIndexes) {
5022
5293
  const i = (def.schema[tableName]?.indexes ?? []).findIndex((entry) => JSON.stringify(entry) === JSON.stringify(cols));
5023
5294
  const idxName = `idx_${schemaName}_${tableName}_composite_${i}`;
5024
- await sql4.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.join(", ")})`).execute(ddlDb);
5295
+ await sql5.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.join(", ")})`).execute(ddlDb);
5025
5296
  }
5026
5297
  for (const cols of conDiff.removedIndexes) {
5027
5298
  const i = (existingSchema[tableName]?.indexes ?? []).findIndex((entry) => JSON.stringify(entry) === JSON.stringify(cols));
5028
5299
  if (i < 0)
5029
5300
  continue;
5030
5301
  const idxName = `idx_${schemaName}_${tableName}_composite_${i}`;
5031
- await sql4.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${idxName}`).execute(ddlDb);
5302
+ await sql5.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${idxName}`).execute(ddlDb);
5032
5303
  }
5033
5304
  }
5034
5305
  const sg2 = await registerSubgraph(db, regData);
@@ -5054,7 +5325,7 @@ async function deploySchema(db, def, handlerPath, opts) {
5054
5325
  }
5055
5326
  }
5056
5327
  for (const stmt of statements) {
5057
- await sql4.raw(stmt).execute(ddlDb);
5328
+ await sql5.raw(stmt).execute(ddlDb);
5058
5329
  }
5059
5330
  const sg = await registerSubgraph(db, regData);
5060
5331
  return { action: "created", subgraphId: sg.id, version: newVersion };
@@ -5106,5 +5377,5 @@ export {
5106
5377
  ByoBreakingChangeError
5107
5378
  };
5108
5379
 
5109
- //# debugId=7F2918CDE1AF5BC064756E2164756E21
5380
+ //# debugId=99416B000428839064756E2164756E21
5110
5381
  //# sourceMappingURL=index.js.map