From 2bc5d9550c6315883a4569da572b4e86d1929462 Mon Sep 17 00:00:00 2001 From: Dicken Date: Sun, 26 Jul 2026 11:29:21 +0200 Subject: [PATCH] round52: Fehler im Sammel-Scan werden jetzt in der UI angezeigt und persistent geloggt statt verschluckt --- apps/backend/src/routes/scan.ts | 31 +++++++++++++++++-- .../frontend/src/routes/admin/ScannerPage.tsx | 14 +++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/apps/backend/src/routes/scan.ts b/apps/backend/src/routes/scan.ts index 5e78441..37fba91 100644 --- a/apps/backend/src/routes/scan.ts +++ b/apps/backend/src/routes/scan.ts @@ -370,8 +370,20 @@ export async function scanRoutes(app: FastifyInstance): Promise { allStale.push(...result.staleServices); allNameChanges.push(...result.nameChanges); allNew.push(...result.newServices); - } catch { - // einzelnes fehlgeschlagenes Gerät soll den Rest nicht abbrechen + } catch (err) { + // Einzelnes fehlgeschlagenes Gerät soll den Rest nicht + // abbrechen - ABER trotzdem persistent loggen, statt + // stillschweigend zu überspringen. Vorher war das ein + // stummer catch-Block: scheiterte ausgerechnet immer + // dasselbe Gerät (z. B. wegen eines kaputten Hostnamens), + // gab es dafür nie einen sichtbaren Hinweis. + const detail = err instanceof Error ? err.message : String(err); + logRepo.logScan({ + type: "device", + targetId: device.id, + level: "error", + message: `${device.hostname} (${device.ip}): Scan im Sammel-Lauf fehlgeschlagen – ${detail}`, + }); } finally { unlockDevice(device.id); } @@ -392,7 +404,20 @@ export async function scanRoutes(app: FastifyInstance): Promise { newServices: allNew, }); } catch (err) { - failJob("devices", err instanceof Error ? err.message : "Unbekannter Fehler"); + // WICHTIG: Vorher wurde ein Abbruch des GESAMTEN Sammel-Scans nur im + // In-Memory-Jobstatus (lastError) vermerkt, nie in der persistenten + // scan_logs-Tabelle - Admin -> Logs blieb dadurch leer, obwohl der + // Scan sichtbar fehlgeschlagen war (Badge in der Seitenleiste + // verschwindet, weil running=false wird, aber ohne jede Erklärung + // warum). Jetzt zusätzlich persistent geloggt. + const detail = err instanceof Error ? err.message : String(err); + logRepo.logScan({ + type: "device", + targetId: null, + level: "error", + message: `Sammel-Scan abgebrochen – ${detail}`, + }); + failJob("devices", detail); } })(); diff --git a/apps/frontend/src/routes/admin/ScannerPage.tsx b/apps/frontend/src/routes/admin/ScannerPage.tsx index 83329cb..3d1cbf3 100644 --- a/apps/frontend/src/routes/admin/ScannerPage.tsx +++ b/apps/frontend/src/routes/admin/ScannerPage.tsx @@ -632,6 +632,20 @@ export function ScannerPage() { queryClient.invalidateQueries({ queryKey: ["devices"] }); queryClient.invalidateQueries({ queryKey: ["services"] }); queryClient.invalidateQueries({ queryKey: ["logs"] }); + } else if ( + status.lastError && + status.startedAt !== getHandledResultId("scanner:bulkLastHandledAt") + ) { + // WICHTIG: Bisher wurde status.lastError hier NIE geprüft - schlug + // der Sammel-Scan fehl (z. B. eine Ausnahme im Hintergrund-Job), + // blieb der zuletzt gesetzte Text ("Scan gestartet…"/"Scanne + // masscan läuft…") einfach stehen, obwohl der Scan längst beendet + // war (running wird false, das Badge in der Seitenleiste + // verschwindet) - der Fehler selbst blieb dabei komplett + // unsichtbar. Analog zum API- und FritzBox-Scanner jetzt auch hier + // angezeigt. + setHandledResultId("scanner:bulkLastHandledAt", status.startedAt); + setBulkStatus(`Fehlgeschlagen: ${status.lastError}`); } } catch { // Netzwerk-Hänger beim Poll soll nicht die Seite stören - nächster