♻️ 大幅重构,拆分模块,增加一些MCP相关限制
Some checks failed
Pyright Lint / Pyright Lint (push) Has been cancelled
Ruff Lint / Ruff Lint (push) Has been cancelled

This commit is contained in:
FuQuan233 2026-07-29 17:00:22 +08:00
parent 41e6aeacb9
commit 0d6771eca6
17 changed files with 1142 additions and 912 deletions

View file

@ -0,0 +1,66 @@
import asyncio
from collections.abc import Awaitable, Callable
from typing import Any
from nonebot import logger
from .state import ChatState
EventProcessor = Callable[[int, bool, ChatState, Any], Awaitable[None]]
class MessageDispatcher:
"""每个会话只运行一个worker并可靠接管竞态窗口中新入队的消息。"""
def __init__(self, processor: EventProcessor):
self._processor = processor
self._tasks: set[asyncio.Task[None]] = set()
self._closing = False
async def enqueue(self, context_id: int, is_group: bool, state: ChatState, event: Any) -> None:
if self._closing:
return
await state.queue.put(event)
async with state.worker_lock:
if state.worker_task is None or state.worker_task.done():
self._start_worker(context_id, is_group, state)
def _start_worker(self, context_id: int, is_group: bool, state: ChatState) -> None:
task = asyncio.create_task(
self._run_worker(context_id, is_group, state),
name=f"llmchat:{'group' if is_group else 'private'}:{context_id}",
)
state.worker_task = task
self._tasks.add(task)
task.add_done_callback(self._tasks.discard)
async def _run_worker(self, context_id: int, is_group: bool, state: ChatState) -> None:
current_task = asyncio.current_task()
try:
while True:
try:
event = state.queue.get_nowait()
except asyncio.QueueEmpty:
break
try:
await self._processor(context_id, is_group, state, event)
except asyncio.CancelledError:
raise
except Exception:
logger.exception(f"处理会话 {context_id} 的消息失败")
finally:
state.queue.task_done()
finally:
async with state.worker_lock:
if state.worker_task is current_task:
state.worker_task = None
if not self._closing and not state.queue.empty():
self._start_worker(context_id, is_group, state)
async def shutdown(self) -> None:
self._closing = True
tasks = list(self._tasks)
for task in tasks:
task.cancel()
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)