Skip to content

Persist Stellar listener cursor in Postgres and add contract-event idempotency guard - #2

Merged
d3vobed merged 2 commits into
mainfrom
copilot/fix-cursor-persistence-bug
Jun 20, 2026
Merged

d3vobed merged 2 commits into
mainfrom
copilot/fix-cursor-persistence-bug

Conversation

Copilot AI commented Jun 20, 2026

Copy link
Copy Markdown

The Stellar event listener stored its cursor in Redis with a global 60s TTL, so restarts could lose cursor state and either skip unprocessed events or reprocess historical ones. This change makes cursor state durable and adds duplicate-suppression for contract-event job dispatch.

  • Durable cursor persistence

    • Introduced EventCursor persistence in Postgres (event_cursors) and moved cursor load/save from cache to Prisma.
    • StellarEventService now reads/writes a stable cursor record keyed by stellar:event_listener:cursor.
  • Startup cursor validation and safe roll-forward

    • On bootstrap, the saved cursor is validated against current STELLAR_HORIZON_URL and STELLAR_NETWORK_PASSPHRASE.
    • If cursor is missing, mismatched, or invalid, listener rolls forward to now and persists that state before streaming.
  • Idempotent contract-event dispatch

    • Added ProcessedContractEvent table (processed_contract_events) with unique (txHash, eventType).
    • Before enqueueing process-event, service checks for existing processed key; duplicates are skipped.
    • Queue jobs are assigned deterministic jobId (${txHash}:${eventType}) to reduce duplicate enqueue pressure.
  • Schema additions

    • Added Prisma models:
      • EventCursor (durable stream cursor + network metadata)
      • ProcessedContractEvent (dedupe key history)
await this.contractEventsQueue.add(process-event, payload, {
  jobId: `${payload.txHash}:${payload.eventType}`,
});

await this.prisma.processedContractEvent.create({
  data: {
    contractId: payload.contractId,
    eventType: payload.eventType,
    txHash: payload.txHash,
    pagingToken: payload.pagingToken,
  },
});

Closes OrbitChainLabs#13

Copilot AI changed the title Fix Stellar cursor durability and contract-event idempotency (Closes #13) Persist Stellar listener cursor in Postgres and add contract-event idempotency guard Jun 20, 2026
Copilot AI requested a review from d3vobed June 20, 2026 12:00
@d3vobed
d3vobed marked this pull request as ready for review June 20, 2026 12:02
@d3vobed
d3vobed merged commit b57f901 into main Jun 20, 2026
Copilot stopped work on behalf of d3vobed due to an error June 20, 2026 12:05
@d3vobed
d3vobed deleted the copilot/fix-cursor-persistence-bug branch July 1, 2026 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants