fix: bound context fallback latency (#30)
All checks were successful
CI / lint (pull_request) Successful in 9s
CI / build-frontend (pull_request) Successful in 4s

This commit is contained in:
timmy 2026-08-05 08:02:39 +00:00
parent 426c0645f9
commit 286680c053
2 changed files with 45 additions and 5 deletions

View File

@ -1,3 +1,5 @@
import asyncio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
@ -9,6 +11,7 @@ from src.suggestion_engine import compute
from src.views import router as frontend_router
app = FastAPI(title="Stackchain Dashboard")
CONTEXT_TIMEOUT_SECONDS = 5.0
app.add_middleware(
CORSMiddleware,
@ -30,11 +33,16 @@ def health() -> dict[str, str]:
@app.get("/api/v1/context")
async def context() -> JSONResponse:
try:
user_data = await current_user()
repo_data = await repos()
issues_data = await issues()
prs_data = await pull_requests()
user_data, repo_data, issues_data, prs_data = await asyncio.wait_for(
asyncio.gather(current_user(), repos(), issues(), pull_requests()),
timeout=CONTEXT_TIMEOUT_SECONDS,
)
except Exception as e:
error_message = (
f"Gitea context request timed out after {CONTEXT_TIMEOUT_SECONDS:g}s"
if isinstance(e, TimeoutError)
else str(e)
)
return JSONResponse({
"user": {"id": None, "login": "timmy", "full_name": "Timmy Jr", "email": ""},
"repos": [],
@ -45,7 +53,7 @@ async def context() -> JSONResponse:
{"panel": "auth", "action": "connect", "target": "stackchain-dashboard backend", "priority": "high"},
{"panel": "gitea", "action": "set GITEA_URL + GITEA_TOKEN", "target": "/root/stackchain-dashboard/.env or systemd env", "priority": "high"},
],
"error": str(e),
"error": error_message,
})
user_model = User(id=user_data["id"], login=user_data["login"], full_name=user_data.get("full_name", ""), email=user_data.get("email", ""))
repo_models = [

View File

@ -0,0 +1,32 @@
import asyncio
import pytest
from src import main
@pytest.mark.anyio
async def test_context_returns_fallback_when_gitea_exceeds_deadline(monkeypatch):
cancelled = asyncio.Event()
async def hanging_current_user():
try:
await asyncio.Event().wait()
finally:
cancelled.set()
async def empty_collection():
return []
monkeypatch.setattr(main, "CONTEXT_TIMEOUT_SECONDS", 0.01)
monkeypatch.setattr(main, "current_user", hanging_current_user)
monkeypatch.setattr(main, "repos", empty_collection)
monkeypatch.setattr(main, "issues", empty_collection)
monkeypatch.setattr(main, "pull_requests", empty_collection)
response = await main.context()
assert response.status_code == 200
assert b'"repos":[]' in response.body
assert b'"error":"Gitea context request timed out after 0.01s"' in response.body
assert cancelled.is_set()