ForcePilot/backend/package/yuxi/channel/sdk/channel_lifecycle.py
Kris b438af3ba8 feat(channel-sdk): 新增完整的渠道SDK工具链
本提交新增了全渠道SDK核心模块:
1.  异步锁、目标解析、动作调度等基础工具
2.  消息动作注册与统一调度系统
3.  测试套件与契约测试框架
4.  完整的目标解析流水线与工具函数
5.  资源依赖注入与生命周期管理
2026-05-21 10:29:12 +08:00

83 lines
2.1 KiB
Python

from __future__ import annotations
import asyncio
import logging
from collections.abc import Awaitable, Callable
from typing import Any, TypeVar
logger = logging.getLogger(__name__)
T = TypeVar("T")
async def _maybe_await(result: Any) -> None:
if isinstance(result, Awaitable):
await result
async def wait_until_abort(
abort_event: asyncio.Event | None = None,
*,
on_abort: Callable[[], Any] | None = None,
) -> None:
if abort_event is None:
if on_abort is not None:
logger.warning("wait_until_abort: on_abort provided but abort_event is None, callback ignored")
await asyncio.Event().wait()
return
await abort_event.wait()
if on_abort is not None:
await _maybe_await(on_abort())
async def run_passive_account_lifecycle(
start: Callable[[], Awaitable[T]],
*,
abort_event: asyncio.Event | None = None,
stop: Callable[[T], Awaitable[Any]] | None = None,
on_stop: Callable[[], Awaitable[Any]] | None = None,
) -> None:
handle = await start()
try:
await wait_until_abort(abort_event)
finally:
if stop is not None:
await stop(handle)
if on_stop is not None:
await on_stop()
async def keep_http_server_task_alive(
server_close_event: asyncio.Event,
*,
abort_event: asyncio.Event | None = None,
on_abort: Callable[[], Any] | None = None,
) -> None:
abort_triggered = False
async def _trigger_abort() -> None:
nonlocal abort_triggered
if abort_triggered:
return
abort_triggered = True
if on_abort is not None:
await _maybe_await(on_abort())
async def _on_abort_event() -> None:
if abort_event is not None:
await abort_event.wait()
await _trigger_abort()
abort_task = asyncio.create_task(_on_abort_event())
try:
await server_close_event.wait()
finally:
abort_task.cancel()
try:
await abort_task
except asyncio.CancelledError:
pass
await _trigger_abort()