feat(c3): ADR-073-C C3 — WebSocket 飛輪即時推送
後端:
- stats.py 新增 @router.websocket('/flywheel/ws')
- 每 10 秒推送 flywheel_summary JSON
前端 FlywheelKPICard:
- WebSocket 優先,WS 斷線自動降級到 30s HTTP 輪詢
- onopen 時停止 HTTP polling,onclose 時恢復
2026-04-12 ogt (ADR-073-C C3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,9 +19,11 @@
|
||||
# @see feedback_lewooogo_modular_enforcement.md
|
||||
# =============================================================================
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from typing import Annotated, Any
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi import APIRouter, Depends, Query, WebSocket, WebSocketDisconnect
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
@@ -552,3 +554,35 @@ async def get_flywheel_prometheus_metrics(svc: FlywheelStatsDep) -> PlainTextRes
|
||||
content=metrics.to_prometheus_lines(),
|
||||
media_type="text/plain; version=0.0.4; charset=utf-8",
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# ADR-073-C C3: WebSocket 即時飛輪推送
|
||||
# =============================================================================
|
||||
|
||||
@router.websocket("/flywheel/ws")
|
||||
async def flywheel_websocket(websocket: WebSocket) -> None:
|
||||
"""
|
||||
WebSocket 即時飛輪健康度推送 — ADR-073-C C3
|
||||
|
||||
每 10 秒推送一次 FlywheelSummary JSON。
|
||||
前端連線路徑:ws(s)://<host>/api/v1/stats/flywheel/ws
|
||||
|
||||
Protocol:
|
||||
Server → Client: {"type": "flywheel_summary", "data": {...}, "ts": "ISO8601"}
|
||||
Client → Server: (ignored)
|
||||
"""
|
||||
svc = get_flywheel_stats_service()
|
||||
await websocket.accept()
|
||||
try:
|
||||
while True:
|
||||
metrics = await svc.compute()
|
||||
payload = json.dumps({
|
||||
"type": "flywheel_summary",
|
||||
"data": metrics.to_summary_api_dict(),
|
||||
"ts": metrics.computed_at.isoformat(),
|
||||
})
|
||||
await websocket.send_text(payload)
|
||||
await asyncio.sleep(10)
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user