From 1e7fb6397b09d6cd49e862c7c4414a1ec3bdc337 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 5 Sep 2026 19:45:03 +0800 Subject: [PATCH] fix(update): clear stale resource ready state --- app/adapters/system/update.py | 9 +++++ tests/test_system_update_manager.py | 51 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/app/adapters/system/update.py b/app/adapters/system/update.py index f816f7938..792cc4c71 100644 --- a/app/adapters/system/update.py +++ b/app/adapters/system/update.py @@ -286,6 +286,15 @@ class SystemUpdateManager(metaclass=SingletonClass): elif item.get("state") == "installing" and self._is_install_applied(item, target): self._reset_item_after_install(item) changed = True + elif ( + target == _RESOURCES + and item.get("state") == "ready" + and self._is_install_applied(item, target) + ): + # 容器替换或手工安装可能先让运行资源达到目标版本,需丢弃残留待安装包。 + self._discard_prepared_target(target) + self._reset_item_after_install(item) + changed = True resources_changed = ( previous_auth_version != auth_version or previous_indexer_version != indexer_version diff --git a/tests/test_system_update_manager.py b/tests/test_system_update_manager.py index d11593783..e621a6154 100644 --- a/tests/test_system_update_manager.py +++ b/tests/test_system_update_manager.py @@ -102,6 +102,57 @@ def test_interrupted_download_becomes_retryable_failure(monkeypatch, tmp_path): assert "中断" in status.error +def test_ready_resource_update_clears_after_loaded_version_reaches_target( + monkeypatch, + tmp_path, +): + """运行资源已达到目标版本时应清除残留提示,并保留另一类待安装制品。""" + versions = ["3.0.1", "3.0.9"] + monkeypatch.setattr( + update_module, + "get_resource_versions", + lambda: tuple(versions), + ) + manager = _manager(monkeypatch, tmp_path) + manager._merge_prepared_manifest( + { + "version": "v3.1.0", + "backend_archive": "/tmp/backend.zip", + "resource_package_version": "10", + "resource_files": [{"name": "user.sites.v3.bin"}], + } + ) + manager._write_item( + "resources", + state="ready", + version="10", + current_auth_version="3.0.1", + current_indexer_version="3.0.9", + indexer_version="3.0.10", + can_update=False, + can_install=True, + ) + + pending = manager.get_status() + pending_resource = next(item for item in pending.updates if item.type == "resources") + assert pending_resource.state == "ready" + + versions[1] = "3.0.10" + current = manager.get_status() + current_resource = next(item for item in current.updates if item.type == "resources") + prepared = json.loads((manager._root / "prepared.json").read_text(encoding="utf-8")) + + assert current_resource.state == "idle" + assert current_resource.current_indexer_version == "3.0.10" + assert current_resource.indexer_version is None + assert current_resource.version is None + assert current_resource.can_install is False + assert prepared["version"] == "v3.1.0" + assert prepared["backend_archive"] == "/tmp/backend.zip" + assert "resource_package_version" not in prepared + assert "resource_files" not in prepared + + def test_download_prepares_matching_backend_and_frontend_archives(monkeypatch, tmp_path): manager = _manager(monkeypatch, tmp_path) backend_fixture = tmp_path / "source-backend.zip"