feature: Scan progress and timing features

This commit is contained in:
Keith Solomon
2026-03-08 15:40:11 -05:00
parent 12b23b43d8
commit 5a35a7158b
5 changed files with 207 additions and 15 deletions

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import json
import threading
import time
from datetime import UTC, datetime
from .db import get_conn
@@ -13,19 +14,73 @@ class ScanState:
self._lock = threading.Lock()
self.running = False
self.current_scan_id: int | None = None
self.subnet: str | None = None
self.total_hosts = 0
self.processed_hosts = 0
self.saved_hosts = 0
self.current_host: str | None = None
self.started_monotonic: float | None = None
def start(self, scan_id: int) -> bool:
def start(self, scan_id: int, subnet: str) -> bool:
with self._lock:
if self.running:
return False
self.running = True
self.current_scan_id = scan_id
self.subnet = subnet
self.total_hosts = 0
self.processed_hosts = 0
self.saved_hosts = 0
self.current_host = None
self.started_monotonic = time.monotonic()
return True
def set_total_hosts(self, total_hosts: int) -> None:
with self._lock:
self.total_hosts = max(total_hosts, 0)
def set_current_host(self, host_ip: str | None) -> None:
with self._lock:
self.current_host = host_ip
def update_progress(self, processed_hosts: int, saved_hosts: int) -> None:
with self._lock:
self.processed_hosts = max(processed_hosts, 0)
self.saved_hosts = max(saved_hosts, 0)
def finish(self) -> None:
with self._lock:
self.running = False
self.current_scan_id = None
self.current_host = None
self.started_monotonic = None
def snapshot(self) -> dict:
with self._lock:
percent = 0
if self.total_hosts > 0:
percent = int((self.processed_hosts / self.total_hosts) * 100)
elapsed_seconds = 0
eta_seconds = None
if self.running and self.started_monotonic is not None:
elapsed_seconds = int(max(time.monotonic() - self.started_monotonic, 0))
if self.processed_hosts > 0 and self.total_hosts > self.processed_hosts:
rate = self.processed_hosts / max(elapsed_seconds, 1)
remaining = self.total_hosts - self.processed_hosts
eta_seconds = int(remaining / max(rate, 1e-9))
return {
"running": self.running,
"scan_id": self.current_scan_id,
"subnet": self.subnet,
"total_hosts": self.total_hosts,
"processed_hosts": self.processed_hosts,
"saved_hosts": self.saved_hosts,
"current_host": self.current_host,
"percent": min(max(percent, 0), 100),
"elapsed_seconds": elapsed_seconds,
"eta_seconds": eta_seconds,
}
scan_state = ScanState()