feat: keep global search useful during partial failures (#199)
This commit is contained in:
1 parent
2243b9453c
commit
f1448e6b58
6 files changed
+195
-29
No files matched your search
+18
-5
@@ -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
@@ -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")
|
||||
|
||||
Reference in new issue
Block a user