Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions indexer/common/src/handlers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Event } from '../rpc';

export interface EventHandler {
name: string;
supports(event: Event): boolean;
handle(event: Event): Promise<void>;
}
6 changes: 6 additions & 0 deletions indexer/common/src/poller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Event Poller

The Event Poller is responsible for continuously fetching Soroban events from the Stellar network and dispatching them to registered handlers.

## Architecture

1 change: 1 addition & 0 deletions indexer/common/src/poller/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './EventPoller';
4 changes: 4 additions & 0 deletions indexer/common/src/repositories/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface CursorRepository {
getCursor(): Promise<number>;
saveCursor(ledger: number): Promise<void>;
}
Comment on lines +1 to +4

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Ledger-only cursoring can skip or replay events.

Persisting only a ledger number is not enough once polling is batched with limit: if a single ledger contains more events than one poll returns, the next resume point cannot distinguish “mid-ledger” from “fully processed.” That makes replay or event loss dependent on how startLedger is interpreted downstream. Please promote the cursor contract to a stable event-level position (for example event.id/paging token plus ledger) or define resume semantics that make partial-ledger progress unambiguous.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/common/src/repositories/index.ts` around lines 1 - 4, The
CursorRepository contract only stores a ledger number, which is ambiguous when
polling in batches and can cause skipped or replayed events. Update the cursor
model used by getCursor and saveCursor to persist a stable event-level position,
such as event.id or a paging token together with the ledger, and adjust any
callers/implementations to resume from that unambiguous position instead of
relying on ledger-only start semantics.

20 changes: 20 additions & 0 deletions indexer/common/src/rpc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface Event {
id: string;
ledger: number;
contractId: string;
topics: string[];
data: any;
timestamp: Date;
}

export interface GetEventsParams {
startLedger: number;
limit?: number;
contractId?: string;
topics?: string[];
}

export interface SorobanRpc {
getEvents(params: GetEventsParams): Promise<Event[]>;
getLatestLedger(): Promise<number>;
}