mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 03:10:46 +08:00
Stream topology discovery progress and mark missing links stale.
SSE updates the UI per NE; edges not seen in a successful scan turn red and can be cleared. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
bfc10ee8cf
commit
bf82a01a03
11 changed files with 748 additions and 67 deletions
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import json
|
||||
from typing import Any, Iterator
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi.responses import StreamingResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .db import get_db
|
||||
|
|
@ -19,6 +21,7 @@ from .topology_service import (
|
|||
delete_map,
|
||||
discover_neighbors,
|
||||
get_graph,
|
||||
iter_discover_neighbors,
|
||||
list_maps,
|
||||
put_graph,
|
||||
update_map,
|
||||
|
|
@ -27,6 +30,11 @@ from .topology_service import (
|
|||
router = APIRouter(prefix="/v1/topology", tags=["topology"])
|
||||
|
||||
|
||||
def _sse_pack(event: dict[str, Any]) -> str:
|
||||
etype = str(event.get("type") or "message")
|
||||
return f"event: {etype}\ndata: {json.dumps(event, ensure_ascii=False, default=str)}\n\n"
|
||||
|
||||
|
||||
@router.get("/maps")
|
||||
def api_list_maps(db: Session = Depends(get_db)) -> dict[str, Any]:
|
||||
return list_maps(db)
|
||||
|
|
@ -69,3 +77,30 @@ def api_discover(
|
|||
) -> dict[str, Any]:
|
||||
req = body or TopologyDiscoverRequest()
|
||||
return discover_neighbors(db, map_id, req).model_dump()
|
||||
|
||||
|
||||
@router.post("/maps/{map_id}/discover/stream")
|
||||
def api_discover_stream(
|
||||
map_id: str,
|
||||
body: TopologyDiscoverRequest | None = None,
|
||||
db: Session = Depends(get_db),
|
||||
) -> StreamingResponse:
|
||||
"""SSE stream: start → ne_start/ne_result (per NE) → done."""
|
||||
req = body or TopologyDiscoverRequest()
|
||||
|
||||
def generate() -> Iterator[str]:
|
||||
try:
|
||||
for event in iter_discover_neighbors(db, map_id, req):
|
||||
yield _sse_pack(event)
|
||||
except Exception as exc: # noqa: BLE001 — surface to client then end stream
|
||||
yield _sse_pack({"type": "error", "detail": str(exc)[:800]})
|
||||
|
||||
return StreamingResponse(
|
||||
generate(),
|
||||
media_type="text/event-stream",
|
||||
headers={
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"X-Accel-Buffering": "no",
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue