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