feat: keep global search useful during partial failures (#199)
CI / lint (pull_request) Successful in 15s
CI / build-frontend (pull_request) Successful in 4s

This commit is contained in:
timmy committed 2026-08-07 14:18:38 +00:00
1 parent 2243b9453c
commit f1448e6b58
6 files changed
+195 -29

No files matched your search

+18 -5
View File
@@ -208,7 +208,7 @@ def _normalize_global_search_item(item: Any, kind: str) -> dict | None:
}
async def global_search(query: str, limit: int = 10) -> list[dict]:
async def global_search(query: str, limit: int = 10) -> dict:
"""Search accessible issues and pulls concurrently with a bounded result set."""
async def load(item_type: str) -> Any:
response = await _get_client().get(
@@ -222,11 +222,21 @@ async def global_search(query: str, limit: int = 10) -> list[dict]:
raise ValueError("Gitea global search response was not a list")
return payload
issues_payload, pulls_payload = await asyncio.gather(load("issues"), load("pulls"))
outcomes = await asyncio.gather(
load("issues"), load("pulls"), return_exceptions=True
)
for outcome in outcomes:
if isinstance(outcome, asyncio.CancelledError):
raise outcome
if all(isinstance(outcome, BaseException) for outcome in outcomes):
raise outcomes[0]
results = []
seen: set[tuple[str, str, int]] = set()
for payload, kind in ((issues_payload, "issue"), (pulls_payload, "pull")):
for item in payload:
for outcome, kind in zip(outcomes, ("issue", "pull"), strict=True):
if isinstance(outcome, BaseException):
continue
for item in outcome:
normalized = _normalize_global_search_item(item, kind)
if normalized is not None:
identity = (kind, normalized["repository"], normalized["number"])
@@ -234,7 +244,10 @@ async def global_search(query: str, limit: int = 10) -> list[dict]:
continue
seen.add(identity)
results.append(normalized)
return results
return {
"items": results[:limit],
"partial": any(isinstance(outcome, BaseException) for outcome in outcomes),
}
async def work_preview(repository: str, kind: str, number: int) -> dict:
+2 -2
View File
@@ -481,7 +481,7 @@ async def global_search(
if len(query) < 2:
raise HTTPException(status_code=422, detail="Search query must contain at least 2 characters")
try:
items = await asyncio.wait_for(
result = await asyncio.wait_for(
gitea_proxy.global_search(query, limit),
timeout=GLOBAL_SEARCH_TIMEOUT_SECONDS,
)
@@ -491,7 +491,7 @@ async def global_search(
status_code=503,
headers={"Retry-After": "1"},
)
return JSONResponse({"query": query, "items": items})
return JSONResponse({"query": query, **result})
@app.get("/api/v1/repos/{owner}/{repo}/issues/{number}/preview")