@thru/indexer 0.2.18 → 0.2.20

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/index.cjs CHANGED
@@ -371,7 +371,7 @@ async function runEventStreamProcessor(stream, options, abortSignal) {
371
371
  };
372
372
  log("info", `Starting stream processor: ${stream.description}`);
373
373
  const checkpoint = await getCheckpoint(db, stream.name);
374
- const startSlot = checkpoint ? checkpoint.slot + 1n : defaultStartSlot;
374
+ const startSlot = checkpoint ? checkpoint.slot : defaultStartSlot;
375
375
  log(
376
376
  "info",
377
377
  `Starting from slot ${startSlot}${checkpoint ? " (resuming)" : " (fresh start)"}`
@@ -386,6 +386,7 @@ async function runEventStreamProcessor(stream, options, abortSignal) {
386
386
  const replay$1 = replay.createEventReplay({
387
387
  clientFactory,
388
388
  startSlot,
389
+ resumeAfter: checkpoint?.eventId ? { slot: checkpoint.slot, eventId: checkpoint.eventId } : void 0,
389
390
  safetyMargin: BigInt(safetyMargin),
390
391
  pageSize,
391
392
  filter: stream.getFilter(),
@@ -401,6 +402,8 @@ async function runEventStreamProcessor(stream, options, abortSignal) {
401
402
  let lastLogTime = Date.now();
402
403
  let eventsReceivedSinceLastLog = 0;
403
404
  const commitBatch = async (batch) => {
405
+ const lastSeenEvent = batch.events[batch.events.length - 1];
406
+ const lastSeenEventId = lastSeenEvent?.id ?? null;
404
407
  let eventsToCommit = batch.events;
405
408
  if (stream.filterBatch) {
406
409
  try {
@@ -413,6 +416,8 @@ async function runEventStreamProcessor(stream, options, abortSignal) {
413
416
  "debug",
414
417
  `All ${batch.events.length} events filtered out at slot ${batch.slot}`
415
418
  );
419
+ await updateCheckpoint(db, stream.name, batch.slot, lastSeenEventId);
420
+ stats.lastSlot = batch.slot;
416
421
  return;
417
422
  }
418
423
  if (eventsToCommit.length < batch.events.length) {
@@ -429,21 +434,23 @@ async function runEventStreamProcessor(stream, options, abortSignal) {
429
434
  return;
430
435
  }
431
436
  }
437
+ const lastEventToCommit = eventsToCommit[eventsToCommit.length - 1];
438
+ const lastEventToCommitId = lastEventToCommit?.id ?? null;
439
+ let committedEvents = eventsToCommit;
432
440
  await db.transaction(async (tx) => {
433
- await tx.insert(stream.table).values(eventsToCommit).onConflictDoNothing();
434
- const lastEvent = eventsToCommit[eventsToCommit.length - 1];
441
+ committedEvents = await tx.insert(stream.table).values(eventsToCommit).onConflictDoNothing().returning();
435
442
  await updateCheckpoint(
436
443
  tx,
437
444
  stream.name,
438
445
  batch.slot,
439
- lastEvent.id
446
+ lastEventToCommitId
440
447
  );
441
448
  });
442
449
  stats.batchesCommitted++;
443
450
  stats.lastSlot = batch.slot;
444
- if (stream.onCommit) {
451
+ if (stream.onCommit && committedEvents.length > 0) {
445
452
  try {
446
- await stream.onCommit({ ...batch, events: eventsToCommit }, { db });
453
+ await stream.onCommit({ ...batch, events: committedEvents }, { db });
447
454
  } catch (hookErr) {
448
455
  log(
449
456
  "error",
@@ -617,7 +624,6 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
617
624
  "info",
618
625
  `Backfill complete. Highest slot: ${highestSlot}, accounts processed: ${stats.accountsProcessed}`
619
626
  );
620
- lastProcessedSlot = highestSlot;
621
627
  }
622
628
  });
623
629
  for await (const event of replay$1) {
@@ -643,6 +649,9 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
643
649
  await db.delete(stream.table).where(drizzleOrm.eq(table[idField], idValue));
644
650
  stats.accountsDeleted++;
645
651
  log("info", `Deleted row for account ${account.addressHex}`);
652
+ if (account.slot > lastProcessedSlot) {
653
+ lastProcessedSlot = account.slot;
654
+ }
646
655
  } catch (err) {
647
656
  log("error", `Failed to delete account ${account.addressHex}: ${err}`);
648
657
  }
@@ -654,6 +663,9 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
654
663
  "debug",
655
664
  `Skipped account ${account.addressHex} - parser returned null (dataLen=${account.data.length})`
656
665
  );
666
+ if (account.slot > lastProcessedSlot) {
667
+ lastProcessedSlot = account.slot;
668
+ }
657
669
  continue;
658
670
  }
659
671
  if (validateParse) {
@@ -663,14 +675,18 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
663
675
  continue;
664
676
  }
665
677
  }
678
+ let upserted = false;
666
679
  try {
667
- await db.insert(stream.table).values(parsed).onConflictDoUpdate({
680
+ const upsertedRows = await db.insert(stream.table).values(parsed).onConflictDoUpdate({
668
681
  target: table[idField],
669
682
  set: parsed,
670
683
  where: drizzleOrm.sql`${table.slot} <= ${parsed.slot}`
671
- });
672
- stats.accountsUpdated++;
673
- if (stats.accountsUpdated <= 3) {
684
+ }).returning();
685
+ upserted = upsertedRows.length > 0;
686
+ if (upserted) {
687
+ stats.accountsUpdated++;
688
+ }
689
+ if (upserted && stats.accountsUpdated <= 3) {
674
690
  log(
675
691
  "info",
676
692
  `Successfully inserted account ${stats.accountsUpdated}`
@@ -682,7 +698,7 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
682
698
  `Failed to upsert account ${account.addressHex}: ${err}`
683
699
  );
684
700
  }
685
- if (account.slot > lastProcessedSlot) {
701
+ if (upserted && account.slot > lastProcessedSlot) {
686
702
  lastProcessedSlot = account.slot;
687
703
  }
688
704
  if (stats.accountsProcessed % 100 === 0) {
@@ -693,11 +709,18 @@ async function runAccountStreamProcessor(stream, options, abortSignal) {
693
709
  }
694
710
  } else if (event.type === "blockFinished") {
695
711
  const slot = event.block.slot;
696
- if (slot > lastProcessedSlot) {
697
- lastProcessedSlot = slot;
712
+ if (lastProcessedSlot > 0n) {
713
+ await updateCheckpoint(db, checkpointName, lastProcessedSlot, null);
714
+ log(
715
+ "debug",
716
+ `Block finished: slot ${slot}, checkpoint saved at account slot ${lastProcessedSlot}`
717
+ );
718
+ } else {
719
+ log(
720
+ "debug",
721
+ `Block finished: slot ${slot}, no checkpoint yet (no accounts handled)`
722
+ );
698
723
  }
699
- await updateCheckpoint(db, checkpointName, lastProcessedSlot, null);
700
- log("debug", `Block finished: slot ${slot}, checkpoint saved`);
701
724
  }
702
725
  }
703
726
  if (lastProcessedSlot > 0n) {