You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the current hardcoded retry logic in StellarSplitClient with a configurable adaptive retry engine that applies different strategies per error class, integrates with the existing TelemetryCollector, and includes a circuit breaker that opens after N consecutive failures.
Acceptance Criteria
Create src/retryEngine.ts with RetryEngine class accepting RetryConfig
Circuit breaker: after circuitBreakerThreshold consecutive transient failures, circuit opens and all calls fail immediately with "circuit open" for circuitResetMs milliseconds
RetryEngine.execute<T>(fn: () => Promise<T>, methodName: string): Promise<T> — runs fn with retry logic and records each attempt via TelemetryCollector.recordMethod
StellarSplitClient constructor accepts optional retry?: RetryConfig and uses RetryEngine for all contract-submitting methods (pay, cloneInvoice, release, refund)
Circuit state is per-RetryEngine instance (not global)
Tests: transient error retries with backoff, contract error not retried, circuit opens after threshold, circuit resets after timeout, jitter produces non-deterministic delays (test range not exact value)
Context
Current retry is inline in src/client.tspay() method — extract and replace
TelemetryCollector is in src/telemetryCollector.ts
src/circuitBreakerMonitor.ts already exists — integrate or extend rather than duplicate
Description
Replace the current hardcoded retry logic in
StellarSplitClientwith a configurable adaptive retry engine that applies different strategies per error class, integrates with the existingTelemetryCollector, and includes a circuit breaker that opens after N consecutive failures.Acceptance Criteria
src/retryEngine.tswithRetryEngineclass acceptingRetryConfigRetryConfigsupports per-error-class strategies:{ transient: RetryStrategy, rateLimit: RetryStrategy, contract: RetryStrategy }whereRetryStrategy = { maxAttempts: number, initialDelayMs: number, backoffMultiplier: number, jitterMs?: number }transient; HTTP 429 →rateLimit; Soroban contract errors (Error(Contract, #N)) →contract(never retried)circuitBreakerThresholdconsecutivetransientfailures, circuit opens and all calls fail immediately with"circuit open"forcircuitResetMsmillisecondsRetryEngine.execute<T>(fn: () => Promise<T>, methodName: string): Promise<T>— runs fn with retry logic and records each attempt viaTelemetryCollector.recordMethodStellarSplitClientconstructor accepts optionalretry?: RetryConfigand usesRetryEnginefor all contract-submitting methods (pay,cloneInvoice,release,refund)RetryEngineinstance (not global)Context
src/client.tspay()method — extract and replaceTelemetryCollectoris insrc/telemetryCollector.tssrc/circuitBreakerMonitor.tsalready exists — integrate or extend rather than duplicate