Skip to content

feat(indexer): implement persistent Soroban polling - #1066

Merged
BigBen-7 merged 1 commit into
PinSpace-Org:mainfrom
kiel997:feature/indexer-polling
Aug 19, 2026
Merged

feat(indexer): implement persistent Soroban polling#1066
BigBen-7 merged 1 commit into
PinSpace-Org:mainfrom
kiel997:feature/indexer-polling

Conversation

@kiel997

@kiel997 kiel997 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

closes #1035

Summary

Implements the Soroban indexer polling and scheduling plumbing so that
IndexerModule runs as part of the backend application.

Changes

  • Imported IndexerModule into AppModule
  • Added scheduled Soroban event polling
  • Added persistent indexer ledger state
  • Added IndexerState entity and migration
  • Resume polling from the persisted ledger after restart
  • Added error handling for malformed events
  • Prevented a bad event from stopping subsequent polling
  • Added unit tests for normal polling and malformed events

Testing

npm run build
npm test

@BigBen-7 BigBen-7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough, well-designed work, kiel997. Reviewed and tested locally: npm run build clean, full suite 14 suites, 128 passed + 1 todo, 0 failures.

Highlights: the cursor is genuinely persisted (IndexerState entity + migration), correctly seeded from the current ledger rather than genesis (with a note that Soroban RPC rejects startLedger: 0 — good catch), the poll loop advances the cursor based on ledger regardless of per-event success so one bad event can't wedge it, and there's an overlap guard preventing concurrent poll cycles. 17 tests cover all of this, including cursor seeding, malformed events, DB write failures, and the overlap guard — well beyond the minimum bar.

Two small non-blocking nits for a future pass: handleEvent(event: any) could use the GistRegistryEvent union type from #1058 instead of any for better type safety, and getLastProcessedLedger's idempotency check calls both findByStellarGistId and existsByStellarGistId where one would do. Neither affects correctness.

Approving and merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wire IndexerModule into the app and implement the Soroban polling loop

2 participants