Add HTML5 operations SSE updates
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-17 02:35:06 +03:00
parent 816b009f47
commit de7248db9e
3 changed files with 42 additions and 10 deletions
+5 -7
View File
@@ -112,12 +112,14 @@ def render_html5_operations(jobs: Iterable[object]) -> str:
<span>jobs</span>
</div>
</section>
<section class="band">
<section class="band" hx-ext="sse" sse-connect="/html5/operations/events">
<div class="section-title">
<h2>Очередь</h2>
<a class="button" href="/html5">Проекты</a>
</div>
{render_html5_operation_summary(job_list)}
<div data-html5-operations-summary-stream sse-swap="operations-summary" hx-swap="innerHTML">
{render_html5_operation_summary(job_list)}
</div>
<div class="table-wrap">
<table data-html5-operations>
<thead>
@@ -125,8 +127,7 @@ def render_html5_operations(jobs: Iterable[object]) -> str:
</thead>
<tbody
data-html5-operations-body
hx-get="/html5/operations/jobs"
hx-trigger="every 3s"
sse-swap="operations-jobs"
hx-swap="innerHTML"
>{render_html5_operation_rows(job_list)}</tbody>
</table>
@@ -148,9 +149,6 @@ def render_html5_operation_summary(jobs: Iterable[object]) -> str:
<div
class="ops-summary"
data-html5-operations-summary
hx-get="/html5/operations/summary"
hx-trigger="every 3s"
hx-swap="outerHTML"
>
{_metric("Всего", len(job_list))}
{_metric("В работе", running)}
+24 -1
View File
@@ -1653,6 +1653,24 @@ async def html5_operation_summary() -> Response:
)
@app.get("/html5/operations/events")
async def html5_operations_events(once: bool = False) -> StreamingResponse:
def stream_operations():
while True:
jobs = _html5_operation_jobs()
yield _html5_sse_event("operations-summary", render_html5_operation_summary(jobs))
yield _html5_sse_event("operations-jobs", render_html5_operation_rows(jobs))
if once:
break
time.sleep(3)
return StreamingResponse(
stream_operations(),
media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
)
@app.get("/html5/projects/{project_id}/editor")
async def html5_project_editor(project_id: str, q: str = "") -> Response:
try:
@@ -1683,7 +1701,7 @@ async def html5_project_events(project_id: str, once: bool = False) -> Streaming
fragment = render_html5_status(project_id, snapshot)
except HTTPException as error:
fragment = f'<span>project: {project_id}</span><span>error: {error.detail}</span>'
yield f"event: status\ndata: {fragment}\n\n"
yield _html5_sse_event("status", fragment)
if once:
break
time.sleep(5)
@@ -8357,6 +8375,11 @@ def _html5_operation_jobs() -> list[OperationJob]:
return sorted(_operations.jobs.values(), key=lambda job: job.updated_at, reverse=True)[:50]
def _html5_sse_event(event: str, fragment: str) -> str:
data = "\n".join(f"data: {line}" for line in fragment.splitlines())
return f"event: {event}\n{data}\n\n"
def _project_summaries() -> list[ProjectSummaryResponse]:
project_ids = set(_project_setup.keys())
stored_snapshots = _storage.list_snapshot_refs()