新增大量渠道适配器相关的协议、策略、工具类与基础设施代码,包括: 1. 多协议定义:认证、消息、配置、网关等核心接口 2. 策略模块:上下文、群聊、去重、防抖等业务策略 3. 工具集:重试、去重、文本分块、消息格式化等SDK工具 4. 基础设施:外部进程管理、事件广播、熔断机制等 5. 账户与管道系统:账户管理、消息处理管道实现 6. 运行时服务:状态收集、维护任务、日志等后台服务
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Awaitable, Callable
|
|
from typing import Any
|
|
|
|
from yuxi.channels.pipeline.context import PipelineContext
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
PipelineStage = Callable[
|
|
["BaseInboundPipeline", PipelineContext],
|
|
Awaitable[PipelineContext | None],
|
|
]
|
|
|
|
|
|
class BaseInboundPipeline:
|
|
def __init__(self, adapter: Any):
|
|
self._adapter = adapter
|
|
self._stages: list[PipelineStage] = []
|
|
|
|
async def initialize(self) -> None:
|
|
self._stages = await self._build_stages()
|
|
logger.info(
|
|
f"[Pipeline] {self.__class__.__name__} initialized with "
|
|
f"{len(self._stages)} stages: "
|
|
f"{[getattr(s, '__name__', s.__class__.__name__) for s in self._stages]}"
|
|
)
|
|
|
|
async def _build_stages(self) -> list[PipelineStage]:
|
|
return []
|
|
|
|
async def process(
|
|
self,
|
|
event_type: str,
|
|
event_data: dict[str, Any],
|
|
) -> PipelineContext | None:
|
|
ctx = self._build_context(event_type, event_data)
|
|
|
|
for idx, stage in enumerate(self._stages, start=1):
|
|
stage_name = self._resolve_stage_name(stage, idx)
|
|
|
|
try:
|
|
result = await stage(self, ctx)
|
|
except Exception as e:
|
|
logger.error(
|
|
f"[Pipeline::{self.__class__.__name__}] Stage [{idx}] '{stage_name}' raised exception: {e}",
|
|
exc_info=True,
|
|
)
|
|
return None
|
|
|
|
if result is None:
|
|
reason = ctx._stop_reason or f"stage_{idx}:{stage_name}"
|
|
logger.debug(
|
|
f"[Pipeline] Message dropped at [{idx}] '{stage_name}': {reason} | ctx={ctx.debug_summary()}"
|
|
)
|
|
return None
|
|
|
|
ctx = result
|
|
|
|
if ctx.stopped:
|
|
logger.debug(f"[Pipeline] Message stopped at [{idx}] '{stage_name}': {ctx._stop_reason}")
|
|
return None
|
|
|
|
return ctx
|
|
|
|
def _build_context(self, event_type: str, event_data: dict[str, Any]) -> PipelineContext:
|
|
return PipelineContext(event_type=event_type, event_data=event_data)
|
|
|
|
@staticmethod
|
|
def _resolve_stage_name(stage: PipelineStage, idx: int) -> str:
|
|
name = getattr(stage, "__name__", "")
|
|
if name and not name.startswith("_"):
|
|
return name
|
|
if hasattr(stage, "__self__"):
|
|
return type(stage.__self__).__name__
|
|
return f"stage_{idx}"
|
|
|
|
@property
|
|
def adapter(self) -> Any:
|
|
return self._adapter
|