Skip to content

feat(wallets): degrade gracefully when IBEX is unreachable (#302) - #524

Closed
nul-quill wants to merge 1 commit into
lnflash:mainfrom
nul-quill:ibex-degradation-302
Closed

nul-quill wants to merge 1 commit into
lnflash:mainfrom
nul-quill:ibex-degradation-302

Conversation

@nul-quill

Copy link
Copy Markdown

Implements the re-scoped ask in #302: graceful degradation instead of full IBEX independence.\n\n- new src/services/ibex/availability.ts: 3s half-open circuit around IBEX. First unanswered call opens it; calls inside the window take the degraded path immediately (no per-field fetch timeout), then the circuit half-opens for one probe.\n- errorHandler() trips the breaker only on a network-level ApiError (no httpCode) and wraps it in IbexUnavailableError, so IBEX is down is distinguishable from his account is odd.\n- getBalanceForWallet(): circuit open -> BTC wallet reads the mongo ledger and converts at the mid price (same unit as the healthy path); cash wallets report unavailable, since only IBEX is authoritative there.\n- getTransactionsForWallets(): circuit open -> history from the ledger. If IBEX fails for some wallets but the ledger has rows, those rows are returned as a success with the error recorded on the span rather than failing the whole list.\n- usd/usdt wallet resolvers render IbexUnavailableError as a null balance (explicit unavailable state) instead of throwing; error-map maps it to IBEX_UNAVAILABLE.\n\nWhen IBEX is available nothing changes: same calls, same mapping.\n\nVerification (isolated Linux sandbox, node 20.18.1):\n
px jest --config ./test/flash/unit/jest.config.js --ci test/flash/unit/services test/flash/unit/domain test/flash/unit/app test/flash/unit/graphql -> 256 suites / 3307 tests passed, exit 0. sc --noEmit unchanged from main (same 2 pre-existing Express/Application errors in src/servers).\n\nHandle: nul-quill. Payout wallets: Solana USDC BdznDjc4xwt5Y6WJT5UnrFQzDptka8YnC9oqmmkKpwkd, TRC20 TNEHCVwR2aPMrj5AKfWCQ2rFL3bEDQmsg7.

Basic wallet functionality (BTC balance + history) depended on IBEX
answering, so a blip on that one host made every wallet screen error out
until the next request. This adds a small circuit breaker around the IBEX
reads and gives each wallet surface a defined degraded mode:

- src/services/ibex/availability.ts: a 3s half-open circuit. The first
  unanswered IBEX call marks it unavailable; calls inside the window
  return the degraded path immediately instead of each paying its own
  fetch timeout, then the circuit half-opens for a single probe.
- errorHandler() trips the breaker only for a network-level ApiError
  (no httpCode), and wraps it in IbexUnavailableError so callers can
  distinguish "IBEX is down" from "this account/invoice is odd".
- getBalanceForWallet(): while open, a BTC wallet reads the mongo ledger
  and converts at the mid price (same unit as the healthy path); cash
  wallets report IbexUnavailableError, since only IBEX is authoritative
  for those.
- getTransactionsForWallets(): while open, history comes from the ledger.
  When IBEX fails for some wallets but the ledger has rows, those rows are
  returned as a success with the error recorded on the span, rather than
  failing the whole list.
- usd/usdt wallet resolvers render IbexUnavailableError as a null balance
  (an explicit "unavailable" state) instead of throwing; error-map gives
  it an IBEX_UNAVAILABLE code.

When IBEX is available nothing changes: the same Ibex.getAccountDetails /
getAccountTransactions calls, the same mapping.

Covered by test/flash/unit/services/ibex/availability.spec.ts plus new
cases in the two wallet specs (breaker-open BTC read, ledger-failure
propagation, cash-unavailable, breaker-open history, both-sources-empty).
@nul-quill

Copy link
Copy Markdown
Author

PR: #524 - circuit breaker on IBEX health (3s half-open), BTC balance + wallet history served from the ledger while it is open, cash wallets show an explicit unavailable (null) state instead of erroring, and a network-level ApiError is what trips the breaker. 256 suites / 3307 tests green in an isolated sandbox; tsc unchanged from main. Handle: nul-quill. Payout wallets: Solana USDC BdznDjc4xwt5Y6WJT5UnrFQzDptka8YnC9oqmmkKpwkd, TRC20 TNEHCVwR2aPMrj5AKfWCQ2rFL3bEDQmsg7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants