From 6d780ef96dbb205134dde8963c67a08924805849 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Sat, 3 Jan 2026 22:12:55 +0100 Subject: [PATCH 1/3] feat: disable provider discovery by default --- routstr/core/settings.py | 2 +- routstr/discovery.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/routstr/core/settings.py b/routstr/core/settings.py index 302df24d..6cbec561 100644 --- a/routstr/core/settings.py +++ b/routstr/core/settings.py @@ -59,7 +59,7 @@ class Settings(BaseSettings): cors_origins: list[str] = Field(default_factory=lambda: ["*"], env="CORS_ORIGINS") tor_proxy_url: str = Field(default="socks5://127.0.0.1:9050", env="TOR_PROXY_URL") providers_refresh_interval_seconds: int = Field( - default=300, env="PROVIDERS_REFRESH_INTERVAL_SECONDS" + default=0, env="PROVIDERS_REFRESH_INTERVAL_SECONDS" ) pricing_refresh_interval_seconds: int = Field( default=120, env="PRICING_REFRESH_INTERVAL_SECONDS" diff --git a/routstr/discovery.py b/routstr/discovery.py index 03a82703..94375b63 100644 --- a/routstr/discovery.py +++ b/routstr/discovery.py @@ -6,7 +6,7 @@ from typing import Any import httpx import websockets -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException from .core.logging import get_logger from .core.settings import settings @@ -389,6 +389,9 @@ async def get_providers( Return cached providers. If include_json, return provider+health; otherwise provider only. Optional filter by pubkey. """ + if settings.providers_refresh_interval_seconds == 0: + raise HTTPException(status_code=404, detail="Provider discovery is disabled") + cache = await get_cache() if not cache: await refresh_providers_cache(pubkey=pubkey) From 9e9bc5bff8efd280c1fb4be5672e75515166b855 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Sat, 3 Jan 2026 22:49:46 +0100 Subject: [PATCH 2/3] fix pytests --- tests/integration/test_performance_load.py | 61 ++++++++++--------- tests/integration/test_provider_management.py | 7 +++ 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/tests/integration/test_performance_load.py b/tests/integration/test_performance_load.py index e5e5c3ce..bc74a60f 100644 --- a/tests/integration/test_performance_load.py +++ b/tests/integration/test_performance_load.py @@ -9,6 +9,7 @@ import gc import statistics import time from typing import Any, Dict, List +from unittest.mock import patch import psutil import pytest @@ -105,42 +106,46 @@ class TestPerformanceBaseline: ("GET", "/v1/wallet/info", authenticated_client, None), ] - # Warm up - for _ in range(10): - await integration_client.get("/") + # Enable provider discovery for this test + with patch( + "routstr.core.settings.settings.providers_refresh_interval_seconds", 300 + ): + # Warm up + for _ in range(10): + await integration_client.get("/") - # Test each endpoint - for method, path, client, data in endpoints: - response_times = [] + # Test each endpoint + for method, path, client, data in endpoints: + response_times = [] - for i in range(100): - start = time.time() + for i in range(100): + start = time.time() - if method == "GET": - response = await client.get(path) - else: - response = await client.post(path, json=data) + if method == "GET": + response = await client.get(path) + else: + response = await client.post(path, json=data) - duration = time.time() - start - response_times.append(duration * 1000) # Convert to ms + duration = time.time() - start + response_times.append(duration * 1000) # Convert to ms - assert response.status_code in [200, 201] + assert response.status_code in [200, 201] - if i % 10 == 0: - metrics.record_system_metrics() + if i % 10 == 0: + metrics.record_system_metrics() - # Verify 95th percentile < 500ms - p95 = sorted(response_times)[int(len(response_times) * 0.95)] - assert p95 < 500, ( - f"{method} {path} p95 response time {p95}ms exceeds 500ms limit" - ) + # Verify 95th percentile < 500ms + p95 = sorted(response_times)[int(len(response_times) * 0.95)] + assert p95 < 500, ( + f"{method} {path} p95 response time {p95}ms exceeds 500ms limit" + ) - print(f"\n{method} {path}:") - print(f" Mean: {statistics.mean(response_times):.2f}ms") - print(f" P95: {p95:.2f}ms") - print( - f" P99: {sorted(response_times)[int(len(response_times) * 0.99)]:.2f}ms" - ) + print(f"\n{method} {path}:") + print(f" Mean: {statistics.mean(response_times):.2f}ms") + print(f" P95: {p95:.2f}ms") + print( + f" P99: {sorted(response_times)[int(len(response_times) * 0.99)]:.2f}ms" + ) @pytest.mark.integration diff --git a/tests/integration/test_provider_management.py b/tests/integration/test_provider_management.py index 788ad768..050ae4dd 100644 --- a/tests/integration/test_provider_management.py +++ b/tests/integration/test_provider_management.py @@ -19,6 +19,13 @@ def _clear_providers_cache() -> None: _PROVIDERS_CACHE.clear() +@pytest.fixture(autouse=True) +def _enable_provider_discovery() -> None: + """Enable provider discovery for all tests in this module""" + with patch("routstr.core.settings.settings.providers_refresh_interval_seconds", 300): + yield + + @pytest.mark.integration @pytest.mark.asyncio async def test_providers_endpoint_default_response( From 7d829af681a0bcd0b150562aa0198e161e05e1f8 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Mon, 5 Jan 2026 00:06:53 +0100 Subject: [PATCH 3/3] fix types --- tests/integration/test_provider_management.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_provider_management.py b/tests/integration/test_provider_management.py index 050ae4dd..b4f2ad6b 100644 --- a/tests/integration/test_provider_management.py +++ b/tests/integration/test_provider_management.py @@ -3,7 +3,7 @@ Integration tests for provider management functionality. Tests GET /v1/providers/ endpoint for listing and managing providers. """ -from typing import Any +from typing import Any, Generator from unittest.mock import patch import pytest @@ -20,9 +20,11 @@ def _clear_providers_cache() -> None: @pytest.fixture(autouse=True) -def _enable_provider_discovery() -> None: +def _enable_provider_discovery() -> Generator[None, Any, Any]: """Enable provider discovery for all tests in this module""" - with patch("routstr.core.settings.settings.providers_refresh_interval_seconds", 300): + with patch( + "routstr.core.settings.settings.providers_refresh_interval_seconds", 300 + ): yield