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
18 changes: 18 additions & 0 deletions backend/src/services/indexerService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/**
* Indexer control-plane helpers (status / reset / replay).
*
* NOTE ON NAMING: Despite the `indexerService` name, this file is NOT an
* indexer. It is the admin/control-plane helper for the source-of-truth
* indexer, `SorobanEventWorker` (backend/src/workers/soroban-event-worker.ts).
* The functions here only read/reset the shared `IndexerState` cursor row and
* trigger the worker's poll loop. It is intentionally named like the legacy
* indexer below to document that this helper is the "other" indexer entry
* point — see backend/src/services/soroban-indexer.service.ts, which is the
* LEGACY indexer being phased out. See docs/ARCHITECTURE.md for the full
* indexer ownership model.
*
* NAMING CONVENTION PLAN: once the functional consolidation of the two
* indexers lands (issue #801), this file is expected to be renamed to
* `indexer.service.ts` so every service is kebab-case with a `.service.ts`
* suffix.
*/
import { prisma } from '../lib/prisma.js';
import { INDEXER_STATE_ID } from '../lib/indexer-state.js';
import { sorobanEventWorker } from '../workers/soroban-event-worker.js';
Expand Down
22 changes: 22 additions & 0 deletions backend/src/services/soroban-indexer.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
/**
* LEGACY indexer — being phased out.
*
* The source of truth for event indexing is `SorobanEventWorker`
* (backend/src/workers/soroban-event-worker.ts). That worker handles the full
* event surface (created / topped_up / withdrawn / paused / resumed /
* cancelled / completed / fee_collected / fee_config_updated /
* admin_transferred), uses cursor-based pagination, persists the `IndexerState`
* cursor, and broadcasts SSE updates.
*
* This service is a simpler, second indexer that polls the Soroban RPC on its
* own interval and writes to the same rows as the worker, which means both run
* concurrently and can race on the same Stream / StreamEvent rows (see issue
* #801). It is kept only for backwards compatibility and is being phased out.
* Until the functional consolidation (issue #801) lands, do not extend this
* service with new behavior — mirror any changes in `SorobanEventWorker`
* instead. Once consolidation lands, this file is expected to be removed.
*
* NAMING CONVENTION PLAN: this file already follows the kebab-case `.service.ts`
* convention. The helper file backend/src/services/indexerService.ts (which is
* NOT an indexer) is expected to be renamed to `indexer.service.ts` to match.
*/
import { prisma } from '../lib/prisma.js';
import logger from '../logger.js';
import { withRpcRetry, withRpcTimeout } from './sorobanService.js';
Expand Down
18 changes: 18 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,24 @@ Frontend useStreamEvents hook (frontend/src/hooks/useStreamEvents.ts)
Dashboard / NotificationDropdown re-render with live data
```

### Indexer Ownership & Naming

Three files with overlapping names live next to each other, but only one of them is the indexer that writes stream state. This section documents which is the source of truth and which is legacy so contributors know where to start when debugging indexing.

| File | Role | Status |
|------|------|--------|
| `backend/src/workers/soroban-event-worker.ts` (`SorobanEventWorker`) | **Source-of-truth indexer.** Polls Soroban RPC, decodes XDR, persists `Stream` / `StreamEvent`, advances the `IndexerState` cursor, and broadcasts SSE. | Active / source of truth. Started by `backend/src/workers/index.ts` |
| `backend/src/services/soroban-indexer.service.ts` (`SorobanIndexerService`) | **Legacy indexer being phased out.** A simpler duplicate poller that writes to the same rows and races with the worker. | **Legacy — do not extend.** Removal tracked with the functional consolidation (issue #801). Started directly from `backend/src/index.ts` |
| `backend/src/services/indexerService.ts` | **Not an indexer at all.** Admin control-plane helpers (`getIndexerStatus`, `resetIndexer`, `replayFromLedger`) that read/reset `IndexerState` and trigger the worker's poll loop. | Active. The name is misleading; it was kept alongside the legacy indexer above |

Key points:

1. **When debugging indexing, read `backend/src/workers/soroban-event-worker.ts` first.** It is the only file that persists canonical stream state.
2. **Do not add new behavior to `soroban-indexer.service.ts`.** It exists only for backwards compatibility while the double-indexer race (issue #801) is consolidated.
3. **`indexerService.ts` is control-plane only** — it never reads the chain; it manages the shared cursor and triggers replays.

**Naming convention plan:** the team convention is kebab-case with a `.service.ts` suffix (e.g. `soroban-indexer.service.ts`, `claimable.service.ts`, `sse.service.ts`). The helper file `indexerService.ts` breaks that convention and is also a misleading name. Once the functional consolidation (issue #801) lands, `indexerService.ts` is expected to be renamed to `indexer.service.ts`.

### Deduplication

`StreamEvent` rows carry a compound unique constraint:
Expand Down
Loading