Skip to content

Commit 4130db2

Browse files
committed
fix: indexer jumps to recent ledger instead of incrementing by 1
1 parent 422992b commit 4130db2

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

src/indexer/indexer.processor.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,20 @@ export class IndexerProcessor extends WorkerHost {
3030
private readonly logger = new Logger(IndexerProcessor.name);
3131

3232
/**
33-
* Soroban RPC only retains contract events for a limited window of recent
34-
* ledgers. If our stored cursor falls further behind the network head than
35-
* this, the RPC rejects `getEvents` with
36-
* "startLedger must be within the ledger range". We keep this safety margin
37-
* below the head and fast-forward the cursor to it when needed.
33+
* How far behind the network head a cursor may fall before we treat it as
34+
* stale. Soroban RPC only retains contract events for a limited window of
35+
* recent ledgers; once the cursor drops more than this below the head, the RPC
36+
* rejects `getEvents` with "startLedger must be within the ledger range".
3837
*/
3938
private static readonly LEDGER_RETENTION_BUFFER = 100_000;
4039

40+
/**
41+
* When a stale cursor is healed, how far below the network head we jump to.
42+
* A small buffer keeps the catch-up point comfortably inside the retention
43+
* window so recovery completes in a single cycle.
44+
*/
45+
private static readonly CATCH_UP_BUFFER = 1_000;
46+
4147
private readonly loanContractId: string;
4248
private readonly reputationContractId: string;
4349

@@ -431,8 +437,9 @@ export class IndexerProcessor extends WorkerHost {
431437
* Proactively fast-forwards a stale cursor.
432438
*
433439
* A checkpoint that has fallen too far behind the network head would be
434-
* rejected by the RPC, so we advance both the start ledger we return and the
435-
* persisted cursor to a safe point just inside the retention window.
440+
* rejected by the RPC. When that happens we jump close to the network head
441+
* (leaving a small buffer inside the retention window) so the indexer catches
442+
* up in a single cycle rather than crawling forward.
436443
*
437444
* @returns The ledger the caller should start fetching from.
438445
*/
@@ -463,19 +470,23 @@ export class IndexerProcessor extends WorkerHost {
463470
return startLedger;
464471
}
465472

473+
// Too far behind to recover full history from the RPC, so jump close to the
474+
// network head and catch up in a single cycle.
475+
const catchUpLedger = latestLedger - IndexerProcessor.CATCH_UP_BUFFER;
476+
466477
this.logger.warn({
467478
context: 'IndexerProcessor',
468479
action: 'healStaleCursor',
469480
label,
470481
startLedger,
471-
minValidLedger,
482+
catchUpLedger,
472483
latestLedger,
473-
}, `Stale ledger checkpoint for ${label}: ${startLedger} is below minimum valid ${minValidLedger}. Fast-forwarding.`);
484+
}, `Stale cursor detected for ${label}. Jumping from ${startLedger} directly to ${catchUpLedger} (latest: ${latestLedger})`);
474485

475-
// Persist (minValidLedger - 1) so the next resume starts exactly at
476-
// minValidLedger, matching the cursor+1 semantics used elsewhere.
477-
await this.updateCursor(contractId, minValidLedger - 1);
478-
return minValidLedger;
486+
// Persist (catchUpLedger - 1) so the next resume starts exactly at
487+
// catchUpLedger, matching the cursor+1 semantics used elsewhere.
488+
await this.updateCursor(contractId, catchUpLedger - 1);
489+
return catchUpLedger;
479490
}
480491

481492
/**

0 commit comments

Comments
 (0)