Skip to content

Implement reconcilePendingSettlements() and dead-letter orphaned usage events #378

@greatest0fallt1me

Description

@greatest0fallt1me

Description

The scheduled settlement sync job calls service.reconcilePendingSettlements() (src/services/settlementStatusSyncJob.ts:28) and five unit tests in src/__tests__/revenueSettlementService.test.ts:266,295,324,367,400 assert its behavior, yet RevenueSettlementService (src/services/revenueSettlementService.ts:29-207) does not define that method — only runBatch, runBatchOnce, recordFailedSettlement, and getErrorMessage exist, and there is a dangling unused reconcileTail field at src/services/revenueSettlementService.ts:31. Separately, runBatchOnce silently drops orphaned events whose API has no registry entry (src/services/revenueSettlementService.ts:80-83 simply continues), so they never settle and never surface. This issue implements reconciliation and adds dead-letter handling for orphaned events.

Requirements and context

  • Implement reconcilePendingSettlements() on RevenueSettlementService returning { checked, completed, failed, errors }, exactly as the existing tests expect (src/__tests__/revenueSettlementService.test.ts:268,297).
  • It must read pending settlements (the SettlementStore exposes getPendingSettlements() — see src/services/settlementStore.ts), query Horizon for each tx_hash using the horizonUrl/fetchImpl options already on RevenueSettlementOptions (src/services/revenueSettlementService.ts:18-19), and transition settlements to completed when successful: true, to failed when successful: false, and treat a 404/missing transaction as failed (per the test at src/__tests__/revenueSettlementService.test.ts:305).
  • Serialize reconciliation runs using the existing reconcileTail promise field, mirroring how runBatch serializes via batchTail (src/services/revenueSettlementService.ts:49-61).
  • Replace the silent continue for orphaned events (src/services/revenueSettlementService.ts:80-83) with explicit dead-letter handling: record/log the orphan with its usageEventId and apiId so operators can act, instead of dropping it.
  • Non-functional: use the bounded withRetry/transient-error helpers from src/lib/retry.js (already imported) for Horizon calls; never mark events settled on a failed payout (current behavior at src/services/revenueSettlementService.ts:161-165 must be preserved).

Acceptance criteria

  • reconcilePendingSettlements() exists and the five existing reconciliation tests pass without modification.
  • Pending settlements move to completed/failed based on Horizon successful, and missing transactions are treated as failed.
  • Concurrent reconciliation calls are serialized via reconcileTail.
  • Orphaned usage events are recorded to a dead-letter path (not silently dropped) with identifying fields.
  • npm run typecheck passes (the file currently references an undefined method).
  • New tests cover the orphaned-event dead-letter path.

Suggested execution

1. Fork the repo and create a branch

git checkout -b feature/settlement-reconciliation-deadletter

2. Implement changes — add the method and dead-letter handling in src/services/revenueSettlementService.ts.
3. Write/extend tests — extend src/__tests__/revenueSettlementService.test.ts.
4. Test and commit

npm run lint
npm run typecheck
npm test -- revenueSettlementService --runInBand

Example commit message

fix(settlement): implement reconcilePendingSettlements and dead-letter orphans

Guidelines

Maintain the repo's 90%+ coverage target (README.md). Add JSDoc to reconcilePendingSettlements documenting the return shape and Horizon semantics, and align SETTLEMENT_STORE_DOCUMENTATION.md. Timeframe: 96 hours.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GRANTFOX OSSGrantFox OSS programMAYBE REWARDEDGrantFox — potentially rewardedOFFICIAL CAMPAIGNGrantFox official campaignadvancedHigh complexity / deep contextbackendBackend serviceimprovementRefactor, performance, or tech-debt

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions