mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-07 00:16:57 +08:00
refactor: unify protected task completion
This commit is contained in:
Vendored
+2
-8
@@ -45,6 +45,7 @@ from app.adapters.system.plugin.manifest import (
|
||||
from app.runtime.log import logger
|
||||
from app.runtime.observability import observe_compat_facade
|
||||
from app.runtime.execution import (
|
||||
await_task_to_terminal,
|
||||
run_in_threadpool_to_completion as _await_thread_operation,
|
||||
)
|
||||
from app.runtime.tasks import get_task_registry
|
||||
@@ -1499,15 +1500,8 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
await asyncio.to_thread(created_file.unlink, missing_ok=True)
|
||||
|
||||
cleanup_task = asyncio.create_task(cleanup_created_file())
|
||||
while not cleanup_task.done():
|
||||
try:
|
||||
await asyncio.shield(cleanup_task)
|
||||
except asyncio.CancelledError:
|
||||
continue
|
||||
except Exception:
|
||||
break
|
||||
try:
|
||||
await cleanup_task
|
||||
await await_task_to_terminal(cleanup_task)
|
||||
except Exception as err:
|
||||
logger.warning(f"[UV] 取消后清理运行环境约束文件失败:{err}")
|
||||
raise
|
||||
|
||||
@@ -9,6 +9,7 @@ from typing import Any, ContextManager, Optional
|
||||
|
||||
from app.schemas.exception import PersistenceUnavailableError
|
||||
from app.application.plugin.lifecycle import plugin_lifecycle
|
||||
from app.runtime.execution import await_task_to_terminal
|
||||
from app.runtime.log import logger
|
||||
from app.schemas.exception import PluginMutationRejectedError
|
||||
|
||||
@@ -29,17 +30,6 @@ PluginRegistrationRefresher = Callable[[str], Awaitable[object]]
|
||||
PluginMutationAdmission = Callable[[str], ContextManager[None]]
|
||||
PluginPackageWriteGuard = Callable[[str], ContextManager[None]]
|
||||
|
||||
|
||||
async def _await_task_to_terminal(task: asyncio.Task[Any]) -> Any:
|
||||
"""忽略调用方的重复取消,直到受保护子任务进入真实终态。"""
|
||||
while not task.done():
|
||||
try:
|
||||
return await asyncio.shield(task)
|
||||
except asyncio.CancelledError:
|
||||
continue
|
||||
return task.result()
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PluginInstallRollback:
|
||||
"""描述失败安装中各类可补偿副作用的恢复结果。"""
|
||||
@@ -193,7 +183,7 @@ class PluginInstallCommand:
|
||||
state.checkpoint = checkpoint
|
||||
except asyncio.CancelledError:
|
||||
try:
|
||||
state.checkpoint = await _await_task_to_terminal(checkpoint_task)
|
||||
state.checkpoint = await await_task_to_terminal(checkpoint_task)
|
||||
except BaseException:
|
||||
pass
|
||||
raise
|
||||
@@ -369,7 +359,7 @@ class PluginInstallCommand:
|
||||
)
|
||||
)
|
||||
try:
|
||||
result = await _await_task_to_terminal(rollback_task)
|
||||
result = await await_task_to_terminal(rollback_task)
|
||||
except BaseException as err:
|
||||
logger.error(f"插件 {plugin_id} 取消后的补偿失败:{err}")
|
||||
return
|
||||
@@ -410,12 +400,7 @@ class PluginInstallCommand:
|
||||
cleanup_task = asyncio.create_task(
|
||||
self._restore_refreshed_runtime(plugin_id)
|
||||
)
|
||||
while not cleanup_task.done():
|
||||
try:
|
||||
await asyncio.shield(cleanup_task)
|
||||
except asyncio.CancelledError:
|
||||
continue
|
||||
rollback = await cleanup_task
|
||||
rollback = await await_task_to_terminal(cleanup_task)
|
||||
state.refresh_compensated = True
|
||||
if rollback.errors:
|
||||
logger.error(
|
||||
|
||||
@@ -3,12 +3,29 @@ import inspect
|
||||
import time
|
||||
from contextvars import copy_context
|
||||
from functools import partial, wraps
|
||||
from typing import Any, Callable
|
||||
from typing import Any, Callable, TypeVar
|
||||
|
||||
from app.schemas.exception import ImmediateException
|
||||
from anyio.to_thread import run_sync
|
||||
|
||||
|
||||
TaskResult = TypeVar("TaskResult")
|
||||
|
||||
|
||||
async def await_task_to_terminal(
|
||||
task: asyncio.Future[TaskResult],
|
||||
) -> TaskResult:
|
||||
"""忽略当前调用方的重复取消,直到受保护任务进入真实终态。"""
|
||||
while not task.done():
|
||||
try:
|
||||
await asyncio.shield(task)
|
||||
except asyncio.CancelledError:
|
||||
continue
|
||||
except BaseException:
|
||||
break
|
||||
return task.result()
|
||||
|
||||
|
||||
async def run_in_threadpool(
|
||||
func: Callable[..., Any],
|
||||
*args: Any,
|
||||
|
||||
Reference in New Issue
Block a user