From 879c54cbda4d5a823ec16894c4e0f5317cee147d Mon Sep 17 00:00:00 2001 From: mwiegand Date: Fri, 8 May 2026 15:45:34 +0200 Subject: [PATCH] refactor(l4d2-web): drop refresh_global_overlays from scheduler GLOBAL_OPERATIONS becomes {"install", "refresh_workshop_items"}. Removes refresh_global_overlays_running from SchedulerState and the _run_refresh_global_overlays dispatch. Drops dead test cases and pins GLOBAL_OPERATIONS contents. Co-Authored-By: Claude Opus 4.7 (1M context) --- l4d2web/services/job_worker.py | 43 ++--------------------- l4d2web/tests/test_job_logs.py | 2 +- l4d2web/tests/test_job_worker.py | 59 ++++++++++++-------------------- l4d2web/tests/test_pages.py | 6 ++-- 4 files changed, 28 insertions(+), 82 deletions(-) diff --git a/l4d2web/services/job_worker.py b/l4d2web/services/job_worker.py index e5a4ee4..3f810a0 100644 --- a/l4d2web/services/job_worker.py +++ b/l4d2web/services/job_worker.py @@ -27,7 +27,7 @@ TERMINAL_JOB_STATES = {"succeeded", "failed", "cancelled"} ACTIVE_JOB_STATES = {"running", "cancelling"} SERVER_OPERATIONS = {"initialize", "start", "stop", "delete"} OVERLAY_OPERATIONS = {"build_overlay"} -GLOBAL_OPERATIONS = {"install", "refresh_workshop_items", "refresh_global_overlays"} +GLOBAL_OPERATIONS = {"install", "refresh_workshop_items"} WORKSHOP_REFRESH_DOWNLOAD_WORKERS = 1 _claim_lock = threading.Lock() @@ -40,7 +40,6 @@ _workers_started = False class SchedulerState: install_running: bool = False refresh_running: bool = False - refresh_global_overlays_running: bool = False running_servers: set[int] = field(default_factory=set) running_overlays: set[int] = field(default_factory=set) blocked_servers_by_overlay: set[int] = field(default_factory=set) @@ -63,7 +62,6 @@ def can_start(job, state: SchedulerState) -> bool: return ( not state.install_running and not state.refresh_running - and not state.refresh_global_overlays_running and len(state.running_servers) == 0 and len(state.running_overlays) == 0 ) @@ -71,26 +69,17 @@ def can_start(job, state: SchedulerState) -> bool: return ( not state.install_running and not state.refresh_running - and not state.refresh_global_overlays_running - and len(state.running_servers) == 0 - and len(state.running_overlays) == 0 - ) - if job.operation == "refresh_global_overlays": - return ( - not state.install_running - and not state.refresh_running - and not state.refresh_global_overlays_running and len(state.running_servers) == 0 and len(state.running_overlays) == 0 ) if job.operation == "build_overlay": - if state.install_running or state.refresh_running or state.refresh_global_overlays_running: + if state.install_running or state.refresh_running: return False if job.overlay_id is None: return False return job.overlay_id not in state.running_overlays # Server operations from here on. - if state.install_running or state.refresh_running or state.refresh_global_overlays_running: + if state.install_running or state.refresh_running: return False if job.server_id is None: return False @@ -109,8 +98,6 @@ def build_scheduler_state(session: Session) -> SchedulerState: state.install_running = True elif job.operation == "refresh_workshop_items": state.refresh_running = True - elif job.operation == "refresh_global_overlays": - state.refresh_global_overlays_running = True elif job.operation == "build_overlay" and job.overlay_id is not None: state.running_overlays.add(job.overlay_id) elif job.server_id is not None: @@ -260,15 +247,6 @@ def run_job(job_id: int) -> None: on_stderr=on_stderr, should_cancel=should_cancel, ) - elif operation == "refresh_global_overlays": - _run_with_boundaries( - "refresh", - "global overlays", - _run_refresh_global_overlays, - on_stdout=on_stdout, - on_stderr=on_stderr, - should_cancel=should_cancel, - ) elif operation == "build_overlay": if overlay_id_for_job is None: raise ValueError("build_overlay job has no overlay_id") @@ -390,21 +368,6 @@ def _run_build_overlay( ) -def _run_refresh_global_overlays( - *, - on_stdout: Callable[[str], None], - on_stderr: Callable[[str], None], - should_cancel: Callable[[], bool], -) -> list[str]: - from l4d2web.services.global_overlay_refresh import refresh_global_overlays - - return refresh_global_overlays( - on_stdout=on_stdout, - on_stderr=on_stderr, - should_cancel=should_cancel, - ) - - def _run_refresh_workshop_items( *, on_stdout: Callable[[str], None], diff --git a/l4d2web/tests/test_job_logs.py b/l4d2web/tests/test_job_logs.py index 0168a8a..6d2842c 100644 --- a/l4d2web/tests/test_job_logs.py +++ b/l4d2web/tests/test_job_logs.py @@ -117,7 +117,7 @@ def test_system_job_logs_persist(tmp_path, monkeypatch): job = Job( user_id=None, server_id=None, - operation="refresh_global_overlays", + operation="refresh_workshop_items", state="queued", ) db.add(job) diff --git a/l4d2web/tests/test_job_worker.py b/l4d2web/tests/test_job_worker.py index 79a9726..d71020a 100644 --- a/l4d2web/tests/test_job_worker.py +++ b/l4d2web/tests/test_job_worker.py @@ -752,46 +752,29 @@ def test_refresh_job_enqueues_build_overlay_without_locking_its_final_log( assert "enqueued build_overlay for 1 overlay(s)" in lines -def test_refresh_global_overlays_blocks_install_build_refresh_and_servers() -> None: - from l4d2web.services.job_worker import SchedulerState, can_start +def test_global_operations_set() -> None: + from l4d2web.services.job_worker import GLOBAL_OPERATIONS - state = SchedulerState(refresh_global_overlays_running=True) - assert can_start(DummyJob(operation="install"), state) is False - assert can_start(DummyJob(operation="refresh_workshop_items"), state) is False - assert can_start(DummyJob(operation="build_overlay", overlay_id=1), state) is False - assert can_start(DummyJob(operation="start", server_id=1), state) is False + assert GLOBAL_OPERATIONS == {"install", "refresh_workshop_items"} -def test_refresh_global_overlays_waits_for_active_work() -> None: - from l4d2web.services.job_worker import SchedulerState, can_start +def test_build_overlay_script_type_blocks_per_overlay(overlay_seeded_worker) -> None: + """Mechanically identical to workshop builds, but pinned for script type.""" + app, ids = overlay_seeded_worker + with session_scope() as s: + overlay = s.query(Overlay).filter_by(id=ids.overlay).one() + overlay.type = "script" + overlay.script = "echo hi" + + add_job(ids.user, "build_overlay", server_id=None, state="running", overlay_id=ids.overlay) - assert can_start(DummyJob(operation="refresh_global_overlays"), SchedulerState(install_running=True)) is False - assert can_start(DummyJob(operation="refresh_global_overlays"), SchedulerState(refresh_running=True)) is False state = SchedulerState() - state.running_overlays.add(1) - assert can_start(DummyJob(operation="refresh_global_overlays"), state) is False - state = SchedulerState() - state.running_servers.add(1) - assert can_start(DummyJob(operation="refresh_global_overlays"), state) is False - - -def test_run_worker_once_dispatches_refresh_global_overlays(seeded_worker, monkeypatch): - from l4d2web.services import job_worker - from l4d2web.models import Job - from l4d2web.db import session_scope - - called = [] - - def fake_refresh(*, on_stdout, on_stderr, should_cancel): - called.append("refresh") - on_stdout("global refresh complete") - return ["l4d2center-maps"] - - monkeypatch.setattr(job_worker, "_run_refresh_global_overlays", fake_refresh) - with session_scope() as db: - job = Job(user_id=None, server_id=None, operation="refresh_global_overlays", state="queued") - db.add(job) - - app, ids = seeded_worker - assert job_worker.run_worker_once() is True - assert called == ["refresh"] + state.running_overlays.add(ids.overlay) + assert ( + can_start(DummyJob(operation="build_overlay", overlay_id=ids.overlay), state) + is False + ) + assert ( + can_start(DummyJob(operation="build_overlay", overlay_id=ids.overlay + 1), state) + is True + ) diff --git a/l4d2web/tests/test_pages.py b/l4d2web/tests/test_pages.py index a5c7047..f487608 100644 --- a/l4d2web/tests/test_pages.py +++ b/l4d2web/tests/test_pages.py @@ -476,13 +476,13 @@ def test_admin_jobs_page_renders_system_job(tmp_path, monkeypatch) -> None: sess["user_id"] = admin_id with session_scope() as db: - db.add(Job(user_id=None, server_id=None, operation="refresh_global_overlays", state="queued")) + db.add(Job(user_id=None, server_id=None, operation="refresh_workshop_items", state="queued")) response = admin_client.get("/admin/jobs") text = response.get_data(as_text=True) assert response.status_code == 200 - assert "refresh_global_overlays" in text + assert "refresh_workshop_items" in text assert "system" in text @@ -503,7 +503,7 @@ def test_non_admin_cannot_view_system_job(tmp_path, monkeypatch) -> None: sess["user_id"] = user_id with session_scope() as db: - job = Job(user_id=None, server_id=None, operation="refresh_global_overlays", state="queued") + job = Job(user_id=None, server_id=None, operation="refresh_workshop_items", state="queued") db.add(job) db.flush() job_id = job.id