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: 0 additions & 7 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import dotenv from "dotenv";
import app from "./app.js";
import logger from "./logger.js";
import { sorobanIndexerService } from "./services/soroban-indexer.service.js";
import { startWorkers, stopWorkers } from "./workers/index.js";
import { sseService } from "./services/sse.service.js";
import { connectRedis, disconnectRedis } from "./lib/redis.js";
Expand Down Expand Up @@ -29,7 +28,6 @@ const startServer = async () => {
);
});

sorobanIndexerService.start();
await startWorkers();

const shutdown = async (signal: string) => {
Expand All @@ -42,11 +40,6 @@ const startServer = async () => {
server.close();

// 3. Stop indexers (clears poll timers)
try {
sorobanIndexerService.stop?.();
} catch (err) {
logger.warn("Error while stopping soroban indexer:", err);
}
stopWorkers();

// 4. Wait for in-flight indexer batch to finish (max 30s)
Expand Down
9 changes: 2 additions & 7 deletions backend/src/services/indexerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,9 @@
* 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.
* trigger the worker's poll loop.
*
* NAMING CONVENTION PLAN: once the functional consolidation of the two
* indexers lands (issue #801), this file is expected to be renamed to
* NAMING CONVENTION PLAN: this file is expected to be renamed to
* `indexer.service.ts` so every service is kebab-case with a `.service.ts`
* suffix.
*/
Expand Down
281 changes: 0 additions & 281 deletions backend/src/services/soroban-indexer.service.ts

This file was deleted.

32 changes: 16 additions & 16 deletions backend/src/workers/soroban-event-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -806,22 +806,22 @@ export class SorobanEventWorker {
return;
}

const stream = await tx.stream.findUniqueOrThrow({
where: { streamId },
select: { withdrawnAmount: true },
});

const newWithdrawnAmount = (
BigInt(stream.withdrawnAmount) + BigInt(amount)
).toString();

await tx.stream.update({
where: { streamId },
data: {
withdrawnAmount: newWithdrawnAmount,
lastUpdateTime: timestamp,
},
});
// Use an atomic DB-level increment so that even under concurrent
// transactions the withdrawnAmount is never double-counted. Because
// Prisma models withdrawnAmount as String (not Int/BigInt), we use a
// raw UPDATE … SET "withdrawnAmount" = (CAST("withdrawnAmount" AS
// numeric) + $1)::text so the database performs the addition atomically.
//
// The idempotency guard above already prevents re-processing of the
// same event, but this atomic increment provides a safety net at the
// database level.
const amountBigInt = BigInt(amount);
await tx.$executeRaw`
UPDATE "Stream"
SET "withdrawnAmount" = (CAST("withdrawnAmount" AS numeric) + ${amountBigInt})::text,
"lastUpdateTime" = ${BigInt(timestamp)}
WHERE "streamId" = ${streamId}
`;

await tx.streamEvent.upsert({
where: { transactionHash_eventType: { transactionHash: event.txHash, eventType: 'WITHDRAWN' } },
Expand Down
Loading
Loading