Fix
This commit is contained in:
153
backend/tests/test_historical_runner_maintenance.py
Normal file
153
backend/tests/test_historical_runner_maintenance.py
Normal file
@@ -0,0 +1,153 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import os
|
||||
import unittest
|
||||
from contextlib import nullcontext, redirect_stdout
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import patch
|
||||
|
||||
import app.historical_runner as historical_runner
|
||||
from app.historical_runner import _maybe_run_database_maintenance, _run_refresh_with_retries
|
||||
|
||||
|
||||
class HistoricalRunnerMaintenanceTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
historical_runner._LAST_DATABASE_MAINTENANCE_RUN_AT = None
|
||||
|
||||
def tearDown(self) -> None:
|
||||
historical_runner._LAST_DATABASE_MAINTENANCE_RUN_AT = None
|
||||
|
||||
def test_scheduler_disabled_does_not_call_cleanup(self) -> None:
|
||||
with (
|
||||
patch.dict(os.environ, {"HLL_DB_MAINTENANCE_ENABLED": "false"}, clear=False),
|
||||
patch("app.historical_runner.run_database_maintenance_cleanup") as cleanup,
|
||||
):
|
||||
result = _maybe_run_database_maintenance(
|
||||
now=datetime(2026, 6, 20, 12, tzinfo=timezone.utc)
|
||||
)
|
||||
|
||||
cleanup.assert_not_called()
|
||||
self.assertEqual(result["status"], "skipped")
|
||||
self.assertEqual(result["reason"], "disabled")
|
||||
|
||||
def test_scheduler_enabled_but_not_due_does_not_call_cleanup(self) -> None:
|
||||
with (
|
||||
patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"HLL_DB_MAINTENANCE_ENABLED": "true",
|
||||
"HLL_DB_MAINTENANCE_INTERVAL_SECONDS": "43200",
|
||||
},
|
||||
clear=False,
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.run_database_maintenance_cleanup",
|
||||
return_value={"status": "ok"},
|
||||
) as cleanup,
|
||||
):
|
||||
first = _maybe_run_database_maintenance(
|
||||
now=datetime(2026, 6, 20, 0, tzinfo=timezone.utc)
|
||||
)
|
||||
second = _maybe_run_database_maintenance(
|
||||
now=datetime(2026, 6, 20, 1, tzinfo=timezone.utc)
|
||||
)
|
||||
|
||||
self.assertEqual(first["status"], "ok")
|
||||
self.assertEqual(second["status"], "skipped")
|
||||
self.assertEqual(second["reason"], "not-due")
|
||||
cleanup.assert_called_once()
|
||||
|
||||
def test_scheduler_enabled_and_due_calls_cleanup(self) -> None:
|
||||
with (
|
||||
patch.dict(os.environ, {"HLL_DB_MAINTENANCE_ENABLED": "true"}, clear=False),
|
||||
patch(
|
||||
"app.historical_runner.run_database_maintenance_cleanup",
|
||||
return_value={"status": "ok"},
|
||||
) as cleanup,
|
||||
):
|
||||
result = _maybe_run_database_maintenance(
|
||||
now=datetime(2026, 6, 20, 12, tzinfo=timezone.utc)
|
||||
)
|
||||
|
||||
cleanup.assert_called_once()
|
||||
self.assertEqual(result["status"], "ok")
|
||||
|
||||
def test_cleanup_exception_is_logged_and_runner_continues(self) -> None:
|
||||
stream = io.StringIO()
|
||||
with (
|
||||
patch.dict(os.environ, {"HLL_DB_MAINTENANCE_ENABLED": "true"}, clear=False),
|
||||
patch("app.historical_runner.backend_writer_lock", return_value=nullcontext()),
|
||||
patch(
|
||||
"app.historical_runner._run_primary_rcon_capture",
|
||||
return_value={"status": "ok", "targets": []},
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.run_incremental_refresh",
|
||||
return_value={"status": "ok"},
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.generate_historical_snapshots",
|
||||
return_value={"status": "ok"},
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.rebuild_elo_mmr_models",
|
||||
return_value={"status": "ok"},
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.run_database_maintenance_cleanup",
|
||||
side_effect=RuntimeError("maintenance failed"),
|
||||
),
|
||||
redirect_stdout(stream),
|
||||
):
|
||||
result = _run_refresh_with_retries(
|
||||
max_retries=0,
|
||||
retry_delay_seconds=0,
|
||||
server_slug="comunidad-hispana-01",
|
||||
max_pages=None,
|
||||
page_size=None,
|
||||
run_number=1,
|
||||
)
|
||||
|
||||
self.assertEqual(result["status"], "ok")
|
||||
self.assertEqual(result["database_maintenance_result"]["status"], "error")
|
||||
self.assertIn("database-maintenance-scheduler-failed", stream.getvalue())
|
||||
|
||||
def test_interval_parsing_handles_invalid_values_safely(self) -> None:
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"HLL_DB_MAINTENANCE_ENABLED": "true",
|
||||
"HLL_DB_MAINTENANCE_INTERVAL_SECONDS": "bad",
|
||||
},
|
||||
clear=False,
|
||||
):
|
||||
interval_seconds, source = historical_runner._resolve_db_maintenance_interval_seconds()
|
||||
|
||||
self.assertEqual(interval_seconds, 43200)
|
||||
self.assertEqual(source, "default-invalid-env-fallback")
|
||||
|
||||
def test_maintenance_state_is_tracked_in_process(self) -> None:
|
||||
with (
|
||||
patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"HLL_DB_MAINTENANCE_ENABLED": "true",
|
||||
"HLL_DB_MAINTENANCE_INTERVAL_SECONDS": "3600",
|
||||
},
|
||||
clear=False,
|
||||
),
|
||||
patch(
|
||||
"app.historical_runner.run_database_maintenance_cleanup",
|
||||
return_value={"status": "ok"},
|
||||
),
|
||||
):
|
||||
_maybe_run_database_maintenance(now=datetime(2026, 6, 20, 12, tzinfo=timezone.utc))
|
||||
self.assertEqual(
|
||||
historical_runner._LAST_DATABASE_MAINTENANCE_RUN_AT,
|
||||
datetime(2026, 6, 20, 12, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user