| 518 | return violations |
| 519 | |
| 520 | def _reaper_loop(self) -> None: |
| 521 | while True: |
| 522 | time.sleep(60) |
| 523 | cutoff = time.time() - RESULT_RETENTION_SECONDS |
| 524 | with self._lock: |
| 525 | stale = [ |
| 526 | sid for sid, state in self.active_scans.items() |
| 527 | if state.completed_at and state.completed_at.timestamp() < cutoff |
| 528 | ] |
| 529 | for sid in stale: |
| 530 | del self.active_scans[sid] |
| 531 | if stale: |
| 532 | logger.info(f"Reaped {len(stale)} stale recon scans") |
| 533 | |
| 534 | |
| 535 | def _split_host_port(target: str, default_port: int) -> tuple[str, int]: |