diff --git a/routstr/wallet.py b/routstr/wallet.py index 24b146ab..0eb091ce 100644 --- a/routstr/wallet.py +++ b/routstr/wallet.py @@ -996,6 +996,7 @@ async def _request_mint_with_fallback( lambda: wallet.request_mint(amount), op_name=op_name, mint_url=mint_url, + retry_timeouts=False, retry_on_rate_limit=False, ) logger.info( diff --git a/tests/unit/test_wallet.py b/tests/unit/test_wallet.py index 54e8d4dd..3b8b3569 100644 --- a/tests/unit/test_wallet.py +++ b/tests/unit/test_wallet.py @@ -2636,6 +2636,43 @@ async def test_wallet_fallback_on_429_no_in_place_retry() -> None: mock_sleep.assert_not_called() +@pytest.mark.asyncio +async def test_wallet_fallback_on_timeout_no_in_place_retry() -> None: + """A timeout from one destination must immediately try the next mint.""" + from routstr.core.settings import settings + from routstr.wallet import _request_mint_with_fallback + + primary = "http://primary:3338" + secondary = "http://secondary:3338" + primary_wallet = Mock( + request_mint=AsyncMock(side_effect=httpx.TimeoutException("timed out")) + ) + quote = Mock(quote="q_secondary", request="lnbc1secondary") + secondary_wallet = Mock(request_mint=AsyncMock(return_value=quote)) + wallets = {primary: primary_wallet, secondary: secondary_wallet} + + with ( + patch.object(settings, "primary_mint", primary), + patch.object(settings, "cashu_mints", [primary, secondary]), + patch.object(settings, "mint_retry_max_attempts", 3), + patch.object(settings, "mint_max_concurrency", 0), + patch.object(settings, "mint_operation_timeout_seconds", 0), + patch("routstr.mint.asyncio.sleep", AsyncMock()) as sleep, + patch( + "routstr.wallet.get_wallet", + AsyncMock(side_effect=lambda mint, *args, **kwargs: wallets[mint]), + ), + ): + _, mint_url, _ = await _request_mint_with_fallback( + 1000, op_name="test_timeout_fallback" + ) + + assert mint_url == secondary + primary_wallet.request_mint.assert_awaited_once_with(1000) + secondary_wallet.request_mint.assert_awaited_once_with(1000) + sleep.assert_not_awaited() + + @pytest.mark.asyncio async def test_wallet_fallback_skips_mint_during_cooldown() -> None: from routstr.core.settings import settings