fix(plugin): make installation lifecycle cancellable

This commit is contained in:
InfinityPacer
2026-08-23 14:26:42 +08:00
parent b1ad309fc7
commit 0378eabb8f
10 changed files with 932 additions and 82 deletions
+14 -2
View File
@@ -364,5 +364,17 @@ class PluginDependencyInstaller:
return await asyncio.to_thread(self.find_missing)
async def async_install(self, dependencies: list[str]) -> tuple[bool, str]:
"""在线程池中安装依赖,复用同步包安装策略"""
return await asyncio.to_thread(self.install, dependencies)
"""异步安装依赖,使用可取消的包安装子进程"""
if not dependencies:
return False, "没有传入需要安装的依赖项"
try:
manifest_paths = [manifest.path for manifest in self._plugin_manifests()]
if not manifest_paths:
return False, "没有找到已安装插件的依赖清单"
return await self._helper.async_install_packages_with_fallback(
manifest_paths,
self._wheels_dirs(),
)
except Exception as err:
logger.error(f"安装依赖项时发生错误:{err}")
return False, f"安装依赖项时发生错误:{err}"
+16 -3
View File
@@ -19,6 +19,19 @@ from app.runtime.settings import RuntimeSettingsCompat
settings = RuntimeSettingsCompat()
async def _await_thread_operation(func, *args, **kwargs):
"""取消请求到达时先等待文件操作收口,避免后台线程继续写运行目录。"""
task = asyncio.create_task(asyncio.to_thread(func, *args, **kwargs))
try:
return await asyncio.shield(task)
except asyncio.CancelledError:
try:
await asyncio.shield(task)
except BaseException:
pass
raise
@dataclass(frozen=True, slots=True)
class PluginPackageCheckpoint:
"""记录一次插件包变更前可用于补偿恢复的文件快照。"""
@@ -74,7 +87,7 @@ class PluginPackageManager:
async def async_checkpoint(self, plugin_id: str) -> PluginPackageCheckpoint:
"""在线程池中创建插件包文件快照。"""
return await asyncio.to_thread(self.checkpoint, plugin_id)
return await _await_thread_operation(self.checkpoint, plugin_id)
@staticmethod
def commit(checkpoint: PluginPackageCheckpoint) -> None:
@@ -83,7 +96,7 @@ class PluginPackageManager:
async def async_commit(self, checkpoint: PluginPackageCheckpoint) -> None:
"""在线程池中清理已提交的插件包快照。"""
await asyncio.to_thread(self.commit, checkpoint)
await _await_thread_operation(self.commit, checkpoint)
@staticmethod
def rollback(checkpoint: PluginPackageCheckpoint) -> None:
@@ -101,7 +114,7 @@ class PluginPackageManager:
async def async_rollback(self, checkpoint: PluginPackageCheckpoint) -> None:
"""在线程池中恢复插件包文件快照。"""
await asyncio.to_thread(self.rollback, checkpoint)
await _await_thread_operation(self.rollback, checkpoint)
def install(
self,