Make Stop stop: no replay, no restart, immediate feedback
Build — Windows, Linux & macOS / GDPRScanner / linux (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / macos (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / windows (push) Has been cancelled
Build — Windows, Linux & macOS / Create GitHub Release (push) Has been cancelled

Pressing Stop could look like the scan restarting, and for scheduled jobs
it really did restart the Google stage.

- Scheduler: check the abort flag between stages and never clear the
  Google abort after a Stop (that started a fresh all-users Google scan).
  A stopped job is recorded as "cancelled" and skips email/retention;
  scheduler_done carries cancelled=true.
- SSE: scan_cancelled and file_scan_done now end the current scan like
  scan_done, and sse.replay_messages() never replays a finished scan.
  Previously a stopped M365 scan (and every file scan) stayed "current",
  so each reconnect replayed it and re-showed Stop + progress.
- Frontend: scan_cancelled clears the M365 running flag and only tears
  down the UI when no Google/file scan is still running; scheduler_done /
  scheduler_error clear all running flags.
- run_scan: Stop during collection now ends the scan (checkpoint, finish,
  scan_cancelled) instead of announcing scan_start / "Scanning…".
- Stop button: switches to a disabled "Stopping…" state on click; all
  show/hide goes through _setStopBtnDisplay(), which resets it when hidden
  or when a new scan starts.

Adds tests/test_stop_scan.py (10 tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #2.
This commit is contained in:
StyxX65andClaude Opus 5.5 committed 2026-09-28 10:03:12 +02:00
1 parent 9cf23da907
commit 606d8e944b
12 files changed
+372 -64

No files matched your search

+26 -2
View File
@@ -19,6 +19,29 @@ logger = logging.getLogger(__name__)
_sse_queues: list = []
_sse_buffer: deque = deque(maxlen=500)
_current_scan_id: str = ""
# Scans that have ended (done / stopped). Their events stay in the buffer but
# are never replayed: replaying a stopped scan re-showed the Stop button and
# progress bar on every reconnect, so Stop looked like a restart.
_finished_scan_ids: deque = deque(maxlen=20)
# Events that end the scan identified by _current_scan_id.
# scan_done: M365 finished; scan_cancelled: M365 stopped; file_scan_done:
# file scan finished or stopped. (Google scans don't set _current_scan_id.)
_TERMINAL_EVENTS = frozenset({"scan_done", "scan_cancelled", "file_scan_done"})
def replay_messages() -> list[str]:
"""Buffered messages to replay to a newly connected browser.
While a scan runs, only that scan's events. Otherwise everything except
events of scans that have already ended (done or stopped).
"""
buf = list(_sse_buffer)
if _current_scan_id:
tag = f'"scan_id": "{_current_scan_id}"'
return [m for m in buf if tag in m]
finished = [f'"scan_id": "{sid}"' for sid in _finished_scan_ids]
return [m for m in buf if not any(tag in m for tag in finished)]
def broadcast(event: str, data: dict):
global _current_scan_id
@@ -31,8 +54,9 @@ def broadcast(event: str, data: dict):
q.put_nowait(msg)
except queue.Full:
pass
# Clear scan_id after scan_done so replay knows the scan is finished
if event == "scan_done" and _current_scan_id:
# Clear scan_id when the scan ends so replay knows it is finished
if event in _TERMINAL_EVENTS and _current_scan_id:
_finished_scan_ids.append(_current_scan_id)
_current_scan_id = ""
# When no browser is watching (e.g. scheduled scan), log key events
if not _sse_queues: