Show Git ingestion job status
This commit is contained in:
+55
-8
@@ -1,8 +1,11 @@
|
||||
"""WebUI FastAPI application."""
|
||||
import asyncio
|
||||
import html
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from fastapi import FastAPI, File, Form, Request, UploadFile
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
||||
@@ -23,6 +26,8 @@ templates.env.globals["escapeHtml"] = lambda value: html.escape(str(value or "")
|
||||
app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "static")), name="static")
|
||||
|
||||
_client: Optional[DocsAPIClient] = None
|
||||
_sync_jobs: Dict[str, Dict[str, Any]] = {}
|
||||
_sync_tasks: set[asyncio.Task] = set()
|
||||
|
||||
|
||||
def get_client() -> DocsAPIClient:
|
||||
@@ -35,6 +40,25 @@ def get_client() -> DocsAPIClient:
|
||||
return _client
|
||||
|
||||
|
||||
def utc_now() -> str:
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
|
||||
async def run_sync_job(job_id: str, override: bool) -> None:
|
||||
job = _sync_jobs[job_id]
|
||||
job["status"] = "running"
|
||||
job["started_at"] = utc_now()
|
||||
try:
|
||||
result = await get_client().post("/sources/sync", json={"override": override})
|
||||
job["result"] = result
|
||||
job["status"] = "succeeded" if result.get("success") else "failed"
|
||||
except Exception as exc:
|
||||
job["status"] = "failed"
|
||||
job["error"] = str(exc)
|
||||
finally:
|
||||
job["finished_at"] = utc_now()
|
||||
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown() -> None:
|
||||
if _client is not None:
|
||||
@@ -300,10 +324,33 @@ async def add_source(
|
||||
|
||||
@app.post("/sources/sync")
|
||||
async def sync_sources(override: bool = Form(False)):
|
||||
client = get_client()
|
||||
try:
|
||||
result = await client.post("/sources/sync", json={"override": override})
|
||||
body = f"<h1>Git Sync Complete</h1><pre>{html.escape(str(result))}</pre><a href='/sources'>Back</a>"
|
||||
except Exception as e:
|
||||
body = f"<h1>Git Sync Failed</h1><pre>{html.escape(str(e))}</pre><a href='/sources'>Back</a>"
|
||||
return page("Git Sync", body)
|
||||
job_id = uuid.uuid4().hex
|
||||
_sync_jobs[job_id] = {
|
||||
"id": job_id,
|
||||
"status": "queued",
|
||||
"created_at": utc_now(),
|
||||
"started_at": None,
|
||||
"finished_at": None,
|
||||
"result": None,
|
||||
"error": None,
|
||||
}
|
||||
task = asyncio.create_task(run_sync_job(job_id, override))
|
||||
_sync_tasks.add(task)
|
||||
task.add_done_callback(_sync_tasks.discard)
|
||||
return RedirectResponse(url=f"/sources/jobs/{job_id}", status_code=303)
|
||||
|
||||
|
||||
@app.get("/sources/jobs/{job_id}")
|
||||
async def sync_job_page(request: Request, job_id: str):
|
||||
job = _sync_jobs.get(job_id)
|
||||
if job is None:
|
||||
return page("Git Sync Not Found", "<h1>Git Sync Not Found</h1><a href='/sources'>Back</a>")
|
||||
return templates.TemplateResponse("sync_job.html", {"request": request, "job": job})
|
||||
|
||||
|
||||
@app.get("/sources/jobs/{job_id}/status")
|
||||
async def sync_job_status(job_id: str):
|
||||
job = _sync_jobs.get(job_id)
|
||||
if job is None:
|
||||
return JSONResponse(status_code=404, content={"error": "Sync job not found"})
|
||||
return job
|
||||
|
||||
Reference in New Issue
Block a user