"""recover_stalled_head_training_runs + recover_stalled_head_auto_apply_runs share one helper (_recover_stalled_runs, DRY pass #161). These pin BOTH wrappers so the shared source stays correct: a 'running' row with no progress past the stall threshold flips to 'error'; a fresh 'running' row is left alone.""" from datetime import UTC, datetime, timedelta import pytest from sqlalchemy import select from backend.app.models import HeadAutoApplyRun, HeadTrainingRun pytestmark = pytest.mark.integration def test_recover_stalled_head_training_runs_flips_stalled_keeps_fresh(db_sync): from backend.app.tasks.maintenance import recover_stalled_head_training_runs stale = HeadTrainingRun( params={}, status="running", last_progress_at=datetime.now(UTC) - timedelta(days=1), ) fresh = HeadTrainingRun( params={}, status="running", last_progress_at=datetime.now(UTC), ) db_sync.add_all([stale, fresh]) db_sync.commit() stale_id, fresh_id = stale.id, fresh.id assert recover_stalled_head_training_runs.apply().get() == 1 db_sync.expire_all() assert db_sync.execute( select(HeadTrainingRun.status).where(HeadTrainingRun.id == stale_id) ).scalar_one() == "error" assert db_sync.execute( select(HeadTrainingRun.status).where(HeadTrainingRun.id == fresh_id) ).scalar_one() == "running" def test_recover_stalled_head_auto_apply_runs_flips_stalled_keeps_fresh(db_sync): from backend.app.tasks.maintenance import recover_stalled_head_auto_apply_runs stale = HeadAutoApplyRun( dry_run=False, params={}, status="running", last_progress_at=datetime.now(UTC) - timedelta(days=1), ) fresh = HeadAutoApplyRun( dry_run=False, params={}, status="running", last_progress_at=datetime.now(UTC), ) db_sync.add_all([stale, fresh]) db_sync.commit() stale_id, fresh_id = stale.id, fresh.id assert recover_stalled_head_auto_apply_runs.apply().get() == 1 db_sync.expire_all() assert db_sync.execute( select(HeadAutoApplyRun.status).where(HeadAutoApplyRun.id == stale_id) ).scalar_one() == "error" assert db_sync.execute( select(HeadAutoApplyRun.status).where(HeadAutoApplyRun.id == fresh_id) ).scalar_one() == "running"