Files
RuoYi-Vue3-FastAPI/ruoyi-fastapi-backend/plugins/core/runtime/task_cleanup.py
T
insistence 4bd83bc7cd feat: 支持 v2 插件、独立前端和签名制品发布 (#130)
* feat: 支持 v2 插件、原生扩展与签名发布

* fix: 修复测试

* feat: 增强宿主 SDK、运行观测与制品维护能力

* feat: 增强文件传输、配置观测与本地开发能力

* feat: 支持 SSE 实时事件流并完善开发脚手架

* feat: 完善长连接鉴权复核与关闭回收

* feat: 增强生命周期与任务关闭可靠性

* feat: 收紧健康检查契约并补齐前端与真实网络验收

* feat: 增加SDK溯源与离线更新工具并验证跨版本兼容

* feat: 增加持久化业务示例与受控 Python 交付

* feat: 增加统一运行诊断与多worker状态观测

* feat: 增加固定目标发布等待与自动验收

* fix: 修复多环境插件部署前缀与代理配置不一致

* fix: 修复测试
2026-10-09 23:49:45 +08:00

61 lines
2.1 KiB
Python

import asyncio
import math
from collections.abc import Iterable
from contextlib import suppress
from typing import Any
CANCEL_TIMEOUT_SECONDS = 5.0
_unfinished_tasks: set[asyncio.Task[Any]] = set()
def pending_plugin_tasks(tasks: Iterable[asyncio.Task[Any]] | None = None) -> frozenset[asyncio.Task[Any]]:
"""
读取取消后仍未退出的宿主任务,可限制到已知插件任务,避免推测任务归属。
:param tasks: 可选的插件所属任务集合,省略时读取当前 worker 的通用回收集合
:return: 尚未退出的任务只读快照,不包含已完成任务且不修改回收状态
"""
selected = _unfinished_tasks if tasks is None else _unfinished_tasks.intersection(tasks)
return frozenset(task for task in selected if not task.done())
def _finish_task(task: asyncio.Task[Any]) -> None:
"""
回收延迟退出的任务及其异常,避免丢失后台任务引用。
:param task: 已经结束的插件任务
:return: None
"""
_unfinished_tasks.discard(task)
with suppress(asyncio.CancelledError, Exception):
task.result()
async def cancel_plugin_tasks(
tasks: Iterable[asyncio.Task[Any]], *, timeout: float = CANCEL_TIMEOUT_SECONDS
) -> set[asyncio.Task[Any]]:
"""
并发取消并限时等待;等待者被取消时也保留未退出任务。
:param tasks: 本次需要回收的任务,不取消调用者自身
:param timeout: 整批任务允许的取消等待秒数
:return: 等待结束后仍未退出的任务
"""
if not math.isfinite(timeout) or timeout <= 0:
raise ValueError('任务取消等待时间必须大于零')
selected = set(tasks) - {asyncio.current_task()}
for task in selected:
if not task.done():
task.cancel()
try:
if selected:
await asyncio.wait(selected, timeout=timeout)
finally:
for task in selected:
if task.done():
_finish_task(task)
elif task not in _unfinished_tasks:
_unfinished_tasks.add(task)
task.add_done_callback(_finish_task)
return {task for task in selected if not task.done()}