fix(contract-sync): close reliability gaps in Soroban event indexer - #165
Merged
SudiptaPaul-31 merged 2 commits intoJul 26, 2026
Merged
Conversation
|
@modecodes Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Soroban contract-sync pipeline (
lib/contract-sync/) already existed and covered most of this issue's scope — a listener polling for on-chain events, a retry queue, an event-to-DB mapper, and an audit table (contract_sync_log). However, two of the acceptance criteria were not actually being met in practice, so this PR closes those gaps rather than rebuilding the indexer from scratch.What was broken
updateSyncLog, so any event that failed and was retried — or exhausted its retries and went to the dead-letter queue — stayed stuck atstatus = 'pending'incontract_sync_logforever. Failures and retries were invisible in the audit trail.What changed
lib/contract-sync/queue.ts— addedonRetry/onDeadLetterhooks so every retry attempt and terminal failure is reported, not just successes.lib/contract-sync/service.ts— wires those hooks toupdateSyncLog, socontract_sync_lognow accurately reflectsfailedanddead_letterstates with the error message and retry count.lib/contract-sync/listener.ts— added a persisted ledger checkpoint (initialLedger/setInitialLedger/onCheckpoint), so on restart polling resumes from where it left off instead of jumping to "now". The checkpoint only advances after the event callback is awaited, so a crash mid-processing can't advance past an event that was never durably logged.lib/contract-sync/types.ts— addedbuildSyncDedupeKey, a single shared identity (txHash:event:milestoneId) used by both the in-memory queue and the audit table.lib/db/migrations/007_contract_sync_durability.sql— addsdedupe_key(+ unique index) tocontract_sync_logand a newcontract_sync_checkpointtable.Acceptance criteria
dedupe_key+ unique index, durable across restarts (previously only in-memory).onRetry/onDeadLetter(previously silently lost).contract_sync_lognow reflects every outcome (success, failed, dead_letter), not just success.Testing
Added/updated unit tests across
__tests__/contract-sync/(listener checkpoint behavior, queue retry/dead-letter hooks, and a newservice.test.tscovering dedup + checkpoint persistence + failure logging). Full suite passes; no new lint or type errors introduced.Closes #157