feat: Fallback context endpoint timeout #32
18
src/main.py
18
src/main.py
|
|
@ -1,3 +1,5 @@
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
|
@ -9,6 +11,7 @@ from src.suggestion_engine import compute
|
||||||
from src.views import router as frontend_router
|
from src.views import router as frontend_router
|
||||||
|
|
||||||
app = FastAPI(title="Stackchain Dashboard")
|
app = FastAPI(title="Stackchain Dashboard")
|
||||||
|
CONTEXT_TIMEOUT_SECONDS = 5.0
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
|
|
@ -30,11 +33,16 @@ def health() -> dict[str, str]:
|
||||||
@app.get("/api/v1/context")
|
@app.get("/api/v1/context")
|
||||||
async def context() -> JSONResponse:
|
async def context() -> JSONResponse:
|
||||||
try:
|
try:
|
||||||
user_data = await current_user()
|
user_data, repo_data, issues_data, prs_data = await asyncio.wait_for(
|
||||||
repo_data = await repos()
|
asyncio.gather(current_user(), repos(), issues(), pull_requests()),
|
||||||
issues_data = await issues()
|
timeout=CONTEXT_TIMEOUT_SECONDS,
|
||||||
prs_data = await pull_requests()
|
)
|
||||||
except Exception as e:
|
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({
|
return JSONResponse({
|
||||||
"user": {"id": None, "login": "timmy", "full_name": "Timmy Jr", "email": ""},
|
"user": {"id": None, "login": "timmy", "full_name": "Timmy Jr", "email": ""},
|
||||||
"repos": [],
|
"repos": [],
|
||||||
|
|
@ -45,7 +53,7 @@ async def context() -> JSONResponse:
|
||||||
{"panel": "auth", "action": "connect", "target": "stackchain-dashboard backend", "priority": "high"},
|
{"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"},
|
{"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", ""))
|
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 = [
|
repo_models = [
|
||||||
|
|
|
||||||
32
tests/test_context_timeout.py
Normal file
32
tests/test_context_timeout.py
Normal 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()
|
||||||
Loading…
Reference in New Issue
Block a user