feat: non-blocking scan with progressive device discovery

Backend:
- asyncio.to_thread(_nmap_scan) — nmap no longer blocks the event loop
- Commit each discovered device immediately (previously one bulk commit at end)
- Update ScanRun.devices_found after each device so history panel shows live count
- broadcast_scan_update() pushes {type: scan_device_found} WS event per device
- Refactor broadcast_status to shared _broadcast() helper, adds type: "status" field

Frontend:
- useStatusPolling handles both WS message types (status / scan_device_found)
- canvasStore: scanEventTs + notifyScanDeviceFound() action
- PendingDevicesPanel auto-refreshes when WS scan event is received
This commit is contained in:
Pouzor
2026-03-07 16:06:44 +01:00
parent 974e782057
commit bec699ba93
5 changed files with 72 additions and 25 deletions
+5
View File
@@ -16,6 +16,7 @@ interface CanvasState {
edges: Edge<EdgeData>[]
hasUnsavedChanges: boolean
selectedNodeId: string | null
scanEventTs: number
onNodesChange: (changes: NodeChange<Node<NodeData>>[]) => void
onEdgesChange: (changes: EdgeChange<Edge<EdgeData>>[]) => void
@@ -29,6 +30,7 @@ interface CanvasState {
setProxmoxContainerMode: (proxmoxId: string, enabled: boolean) => void
markSaved: () => void
loadCanvas: (nodes: Node<NodeData>[], edges: Edge<EdgeData>[]) => void
notifyScanDeviceFound: () => void
}
export const useCanvasStore = create<CanvasState>((set) => ({
@@ -36,6 +38,7 @@ export const useCanvasStore = create<CanvasState>((set) => ({
edges: [],
hasUnsavedChanges: false,
selectedNodeId: null,
scanEventTs: 0,
onNodesChange: (changes) =>
set((state) => ({
@@ -126,6 +129,8 @@ export const useCanvasStore = create<CanvasState>((set) => ({
markSaved: () => set({ hasUnsavedChanges: false }),
notifyScanDeviceFound: () => set({ scanEventTs: Date.now() }),
loadCanvas: (nodes, edges) => {
// React Flow requires parents before children in the array
const parents = nodes.filter((n) => !n.parentId)