本提交新增了全渠道SDK核心模块: 1. 异步锁、目标解析、动作调度等基础工具 2. 消息动作注册与统一调度系统 3. 测试套件与契约测试框架 4. 完整的目标解析流水线与工具函数 5. 资源依赖注入与生命周期管理
67 lines
1.6 KiB
Python
67 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import logging
|
|
from collections.abc import Callable, Coroutine
|
|
from typing import Protocol, TypeVar
|
|
|
|
T = TypeVar("T")
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class KeyedAsyncQueueHooks(Protocol):
|
|
def on_enqueue(self) -> None: ...
|
|
def on_settle(self) -> None: ...
|
|
|
|
|
|
def enqueue_keyed_task(
|
|
tails: dict[str, asyncio.Future],
|
|
key: str,
|
|
task: Callable[[], Coroutine[None, None, T]],
|
|
*,
|
|
hooks: KeyedAsyncQueueHooks | None = None,
|
|
) -> Coroutine[None, None, T]:
|
|
async def _run() -> T:
|
|
if hooks:
|
|
hooks.on_enqueue()
|
|
|
|
prev = tails.get(key)
|
|
if prev is not None and not prev.done():
|
|
try:
|
|
await prev
|
|
except Exception:
|
|
_logger.debug("Keyed task predecessor failed for key=%s", key, exc_info=True)
|
|
|
|
loop = asyncio.get_running_loop()
|
|
tail: asyncio.Future = loop.create_future()
|
|
tails[key] = tail
|
|
|
|
try:
|
|
return await task()
|
|
finally:
|
|
if hooks:
|
|
hooks.on_settle()
|
|
tail.set_result(None)
|
|
if tails.get(key) is tail:
|
|
tails.pop(key, None)
|
|
|
|
return _run()
|
|
|
|
|
|
class KeyedAsyncQueue:
|
|
|
|
def __init__(self) -> None:
|
|
self._tails: dict[str, asyncio.Future] = {}
|
|
|
|
def get_tails(self) -> dict[str, asyncio.Future]:
|
|
return self._tails
|
|
|
|
async def enqueue(
|
|
self,
|
|
key: str,
|
|
task: Callable[[], Coroutine[None, None, T]],
|
|
*,
|
|
hooks: KeyedAsyncQueueHooks | None = None,
|
|
) -> T:
|
|
return await enqueue_keyed_task(self._tails, key, task, hooks=hooks) |