round45: Sammel-Scan bearbeitet jetzt bis zu 10 Geraete gleichzeitig statt nacheinander (behebt sehr lange Gesamtdauer bei vielen Geraeten)

This commit is contained in:
2026-07-25 13:17:44 +02:00
parent 59bb4a30b8
commit 6792f5b7ea

View File

@@ -203,33 +203,49 @@ export async function scanRoutes(app: FastifyInstance): Promise<void> {
let cancelled = false; let cancelled = false;
try { try {
for (const device of devices) { // Mehrere Geräte GLEICHZEITIG scannen statt strikt nacheinander -
// bei z. B. 118 Geräten und je 10-30 Sekunden pro vollständigem
// Portscan hätte ein rein sequenzieller Durchlauf zusammen leicht
// 30+ Minuten gedauert. Batch-Größe bewusst moderat (nicht alle
// Geräte auf einmal): jeder einzelne Geräte-Scan öffnet intern schon
// bis zu 1000 gleichzeitige Verbindungen (siehe ports.ts) - zu viele
// Geräte gleichzeitig könnte das eigene Netz/den Docker-Host
// überlasten.
const CONCURRENT_DEVICES = 10;
for (let i = 0; i < devices.length; i += CONCURRENT_DEVICES) {
if (isCancelRequested("devices")) { if (isCancelRequested("devices")) {
cancelled = true; cancelled = true;
break; break;
} }
updateJobProgress("devices", scannedCount, device.hostname); const batch = devices.slice(i, i + CONCURRENT_DEVICES);
if (!tryLockDevice(device.id)) { updateJobProgress("devices", scannedCount, batch.map((d) => d.hostname).join(", "));
// Für dieses eine Gerät läuft bereits ein separater Scan (z. B.
// über den "Jetzt scannen"-Button auf der Geräte-Seite) - await Promise.all(
// überspringen statt zu überlappen, sonst könnten beide batch.map(async (device) => {
// gleichzeitig denselben neuen Dienst anlegen wollen. if (!tryLockDevice(device.id)) {
scannedCount++; // Für dieses eine Gerät läuft bereits ein separater Scan
continue; // (z. B. über den "Jetzt scannen"-Button auf der
} // Geräte-Seite) - überspringen statt zu überlappen, sonst
try { // könnten beide gleichzeitig denselben neuen Dienst anlegen
const result = await performDeviceScan(device, true); // wollen.
created += result.created; return;
updated += result.updated; }
allStale.push(...result.staleServices); try {
allNameChanges.push(...result.nameChanges); const result = await performDeviceScan(device, true);
allNew.push(...result.newServices); created += result.created;
} catch { updated += result.updated;
// einzelnes fehlgeschlagenes Gerät soll den Rest nicht abbrechen allStale.push(...result.staleServices);
} finally { allNameChanges.push(...result.nameChanges);
unlockDevice(device.id); allNew.push(...result.newServices);
} } catch {
scannedCount++; // einzelnes fehlgeschlagenes Gerät soll den Rest nicht abbrechen
} finally {
unlockDevice(device.id);
}
})
);
scannedCount += batch.length;
updateJobProgress("devices", scannedCount, null);
} }
finishJob("devices", { finishJob("devices", {