feat(indexer): implement persistent Soroban polling - #1066
Conversation
BigBen-7
left a comment
There was a problem hiding this comment.
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.
closes #1035
Summary
Implements the Soroban indexer polling and scheduling plumbing so that
IndexerModule runs as part of the backend application.
Changes
IndexerModuleintoAppModuleIndexerStateentity and migrationTesting
npm run build npm test