feat: create httpx.AsyncClient in lifespan for federation

This commit is contained in:
Brian Krabach
2026-04-01 10:43:31 -07:00
parent f09068c1f1
commit c03c85c76a
2 changed files with 34 additions and 0 deletions
+5
View File
@@ -20,6 +20,7 @@ import sys
import time import time
from typing import Literal from typing import Literal
import httpx
import websockets import websockets
import websockets.exceptions import websockets.exceptions
from websockets.typing import Subprotocol from websockets.typing import Subprotocol
@@ -175,8 +176,12 @@ async def lifespan(app: FastAPI):
except Exception: except Exception:
pass # tmux not running at startup is OK; hook will be set on first poll pass # tmux not running at startup is OK; hook will be set on first poll
app.state.federation_client = httpx.AsyncClient(timeout=5.0, follow_redirects=False)
yield yield
await app.state.federation_client.aclose()
# Shutdown: cancel the poll loop task and wait for it to finish. # Shutdown: cancel the poll loop task and wait for it to finish.
if _poll_task is not None: if _poll_task is not None:
_poll_task.cancel() _poll_task.cancel()
+29
View File
@@ -1435,3 +1435,32 @@ def test_federation_bearer_auth_accepted(monkeypatch):
) )
assert response.status_code == 200 assert response.status_code == 200
# ---------------------------------------------------------------------------
# httpx.AsyncClient federation client on app.state (task-7)
# ---------------------------------------------------------------------------
def test_federation_client_exists_on_app_state(monkeypatch):
"""app.state.federation_client is set during lifespan and is not None.
Verifies that the lifespan creates an httpx.AsyncClient and attaches it to
app.state.federation_client before the application begins serving requests.
"""
import httpx
monkeypatch.setenv("MUXPLEX_PASSWORD", "test-password")
with TestClient(app) as c:
# Inside the context manager the lifespan has completed startup,
# so app.state.federation_client must be set.
assert hasattr(app.state, "federation_client"), (
"app.state.federation_client must be set during lifespan startup"
)
assert app.state.federation_client is not None, (
"app.state.federation_client must not be None"
)
assert isinstance(app.state.federation_client, httpx.AsyncClient), (
"app.state.federation_client must be an httpx.AsyncClient instance"
)