core: implement Horizon failover with multiple RPC endpoints#86
Conversation
Created src/stellar/horizon-client.service.ts with multi-endpoint support (configurable via STELLAR_HORIZON_URLS env var, comma-separated), a circuit breaker per endpoint (3 failures -> 30s cooldown -> half-open probe -> automatic recovery), and auto-failover to the next healthy endpoint on transient failures (timeouts, 5xx, rate limits, network errors). Created src/stellar/stellar.service.ts as a thin public-facing wrapper. Updated src/modules/health/health.service.ts to consume the horizon client and report per-endpoint circuit breaker statuses (closed/open/half-open, failure count, last error, primary indicator) in the GET /health response. Two new config keys are supported: STELLAR_HORIZON_URLS (comma-separated list) with fallback to the existing STELLAR_HORIZON_URL. Closed StepFi-app#27
EmeditWeb
left a comment
There was a problem hiding this comment.
Review verdict: ✅ APPROVE
Clean multi-RPC failover. withFailover<T> rotates through all configured endpoints, tries each on failure, and throws only once every endpoint is exhausted; endpoints come from env with a sensible testnet default. No any; 21 tests pass locally; CI green.
One note: submitTransaction also goes through withFailover, so if the first endpoint accepts the transaction but its response is lost, a retry could re-submit to a second endpoint. For Stellar this is largely idempotent (the same signed tx / sequence number yields the same result or tx_bad_seq), so it's low-risk — but a short code comment noting that submit-retries rely on ledger-level idempotency would be worth adding. Otherwise merge-ready.
EmeditWeb
left a comment
There was a problem hiding this comment.
Re-audited: clean multi-RPC failover (withFailover rotates all endpoints, throws only when all exhausted), no any, 10/10 tests pass, build clean. The submitTransaction-retry idempotency note from my review is now documented (commit beed70b). Approving and merging.
🔗 Related Issue
Closes #27
🔖 Title
Created src/stellar/horizon-client.service.ts with multi-endpoint support (configurable via STELLAR_HORIZON_URLS env var, comma-separated), a circuit breaker per endpoint (3 failures -> 30s cooldown -> half-open probe -> automatic recovery), and auto-failover to the next healthy endpoint on transient failures (timeouts, 5xx, rate limits, network errors). Created src/stellar/stellar.service.ts as a thin public-facing wrapper. Updated src/modules/health/health.service.ts to consume the horizon client and report per-endpoint circuit breaker statuses (closed/open/half-open, failure count, last error, primary indicator) in the GET /health response. Two new config keys are supported: STELLAR_HORIZON_URLS (comma-separated list) with fallback to the existing STELLAR_HORIZON_URL.
📝 Description
Replaces the single hardcoded Horizon endpoint with a multi-endpoint client that fails over automatically when the primary goes down, so the API doesn't stop working on a single endpoint outage. Adds a circuit breaker per endpoint to stop hammering a failing one, and surfaces per-endpoint health status through the existing /health route for monitoring.
🔄 Changes Made
-Added src/stellar/stellar.service.ts as a thin wrapper exposing the horizon client to the rest of the app
📸 Screenshots (if applicable)
🗒️ Additional Notes