feat: Async scan with polling — no more timeout issues
Fundamental fix: scans now run asynchronously with progress polling.
Backend:
- POST /scan starts background task, returns scan_id immediately
- GET /scan/{scan_id} returns status + progress + result when done
- 7 progress steps shown: Website scan, DSI discovery, DSE analysis,
SOLL/IST comparison, corrections, report, email
- In-memory job store (dict with scan_id → status/result)
- No timeout limits on scan duration
Frontend:
- POST starts scan, receives scan_id
- Polls GET every 5 seconds (max 120 attempts = 10 min)
- Shows live progress message during scan
- Displays result when completed, error when failed
Proxy:
- POST timeout reduced to 30s (just starts the job)
- GET timeout 10s (just status check)
- No more 504/connection-dropped errors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,13 +40,42 @@ export default function AgentPage() {
|
||||
setScanError(null)
|
||||
setScanData(null)
|
||||
try {
|
||||
const res = await fetch('/api/sdk/v1/agent/scan', {
|
||||
// Step 1: Start async scan
|
||||
const startRes = await fetch('/api/sdk/v1/agent/scan', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url: url.trim(), mode }),
|
||||
})
|
||||
if (!res.ok) throw new Error(`Scan fehlgeschlagen: ${res.status}`)
|
||||
setScanData(await res.json())
|
||||
if (!startRes.ok) throw new Error(`Scan konnte nicht gestartet werden: ${startRes.status}`)
|
||||
const { scan_id } = await startRes.json()
|
||||
if (!scan_id) throw new Error('Keine Scan-ID erhalten')
|
||||
|
||||
// Step 2: Poll for results
|
||||
let attempts = 0
|
||||
const maxAttempts = 120 // 10 min at 5s intervals
|
||||
while (attempts < maxAttempts) {
|
||||
await new Promise(r => setTimeout(r, 5000))
|
||||
const pollRes = await fetch(`/api/sdk/v1/agent/scan?scan_id=${scan_id}`)
|
||||
if (!pollRes.ok) { attempts++; continue }
|
||||
const status = await pollRes.json()
|
||||
|
||||
// Update progress message
|
||||
if (status.progress) {
|
||||
setScanError(null)
|
||||
// Show progress as temporary "error" (will be cleared when done)
|
||||
setScanData({ _progress: status.progress } as any)
|
||||
}
|
||||
|
||||
if (status.status === 'completed' && status.result) {
|
||||
setScanData(status.result)
|
||||
break
|
||||
}
|
||||
if (status.status === 'failed') {
|
||||
throw new Error(status.error || 'Scan fehlgeschlagen')
|
||||
}
|
||||
attempts++
|
||||
}
|
||||
if (attempts >= maxAttempts) throw new Error('Scan-Timeout (10 Minuten)')
|
||||
} catch (e) {
|
||||
setScanError(e instanceof Error ? e.message : 'Unbekannter Fehler')
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user