from __future__ import annotations from datetime import datetime, timedelta import json def test_reference_bundle_running_task_remains_running_after_elapsed_time(tmp_path, monkeypatch): from apps.web.vue3 import main monkeypatch.setattr(main, "WORKSPACE_ROOT", tmp_path / "workspace") task = { "id": "task_ref_timeout", "task_id": "task_ref_timeout", "stage": "reference_bundle_download", "job_id": "job_ref_timeout", "status": "running", "message": "正在后台下载参考物种注释包", "created_at": (datetime.now() - timedelta(seconds=500)).isoformat(), "start_time": (datetime.now() - timedelta(seconds=500)).isoformat(), "timeout_sec": 300, "payload": {"job_id": "job_ref_timeout", "timeout_sec": 300}, } main._apply_reference_bundle_stale_watchdog(task) assert task["status"] == "running" assert task["pending_seconds"] >= 500 assert task["progress"]["phase"] == "running" assert task["progress"]["indeterminate"] is True assert "action_required" not in task assert "retryable" not in task assert "result" not in task status_path = ( tmp_path / "workspace" / "job_ref_timeout" / "final" / "reference_bundle_tasks" / "task_ref_timeout.json" ) assert status_path.exists() persisted = json.loads(status_path.read_text(encoding="utf-8")) assert persisted["status"] == "running" assert persisted["progress"]["phase"] == "running" def test_reference_bundle_task_can_be_recovered_from_persisted_status(tmp_path, monkeypatch): from apps.web.vue3 import main monkeypatch.setattr(main, "WORKSPACE_ROOT", tmp_path / "workspace") status_dir = tmp_path / "workspace" / "job_ref_recover" / "final" / "reference_bundle_tasks" status_dir.mkdir(parents=True) status_path = status_dir / "task_ref_recover.json" status_path.write_text( json.dumps( { "id": "task_ref_recover", "task_id": "task_ref_recover", "stage": "reference_bundle_download", "job_id": "job_ref_recover", "status": "failed", "message": "download failed", }, ensure_ascii=False, ), encoding="utf-8", ) recovered = main._load_reference_bundle_task("task_ref_recover") assert recovered is not None assert recovered["job_id"] == "job_ref_recover" assert recovered["status"] == "failed"