feat(stream): 添加流循环启动锁以防止并发启动同一流的多个循环任务
This commit is contained in:
@@ -48,6 +48,9 @@ class StreamLoopManager:
|
|||||||
# 每个流的上一次间隔值(用于日志去重)
|
# 每个流的上一次间隔值(用于日志去重)
|
||||||
self._last_intervals: dict[str, float] = {}
|
self._last_intervals: dict[str, float] = {}
|
||||||
|
|
||||||
|
# 流循环启动锁:防止并发启动同一个流的多个循环任务
|
||||||
|
self._stream_start_locks: dict[str, asyncio.Lock] = {}
|
||||||
|
|
||||||
logger.info(f"流循环管理器初始化完成 (最大并发流数: {self.max_concurrent_streams})")
|
logger.info(f"流循环管理器初始化完成 (最大并发流数: {self.max_concurrent_streams})")
|
||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
@@ -105,6 +108,14 @@ class StreamLoopManager:
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 是否成功启动
|
bool: 是否成功启动
|
||||||
"""
|
"""
|
||||||
|
# 获取或创建该流的启动锁
|
||||||
|
if stream_id not in self._stream_start_locks:
|
||||||
|
self._stream_start_locks[stream_id] = asyncio.Lock()
|
||||||
|
|
||||||
|
lock = self._stream_start_locks[stream_id]
|
||||||
|
|
||||||
|
# 使用锁防止并发启动同一个流的多个循环任务
|
||||||
|
async with lock:
|
||||||
# 获取流上下文
|
# 获取流上下文
|
||||||
context = await self._get_stream_context(stream_id)
|
context = await self._get_stream_context(stream_id)
|
||||||
if not context:
|
if not context:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
当定时任务触发时,负责搜集信息、调用LLM决策、并根据决策生成回复
|
当定时任务触发时,负责搜集信息、调用LLM决策、并根据决策生成回复
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
|
|
||||||
@@ -484,6 +485,9 @@ _planner = ProactiveThinkingPlanner()
|
|||||||
# 统计数据
|
# 统计数据
|
||||||
_statistics: dict[str, dict[str, Any]] = {}
|
_statistics: dict[str, dict[str, Any]] = {}
|
||||||
|
|
||||||
|
# 全局执行锁字典:防止同一聊天流的主动思考被并发执行
|
||||||
|
_execution_locks: dict[str, asyncio.Lock] = {}
|
||||||
|
|
||||||
|
|
||||||
def _update_statistics(stream_id: str, action: str):
|
def _update_statistics(stream_id: str, action: str):
|
||||||
"""更新统计数据
|
"""更新统计数据
|
||||||
@@ -538,10 +542,34 @@ async def execute_proactive_thinking(stream_id: str):
|
|||||||
logger.debug(f"主动思考功能已关闭,跳过执行 {stream_id}")
|
logger.debug(f"主动思考功能已关闭,跳过执行 {stream_id}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 获取或创建该聊天流的执行锁
|
||||||
|
if stream_id not in _execution_locks:
|
||||||
|
_execution_locks[stream_id] = asyncio.Lock()
|
||||||
|
|
||||||
|
lock = _execution_locks[stream_id]
|
||||||
|
|
||||||
|
# 尝试获取锁,如果已被占用则跳过本次执行(防止重复)
|
||||||
|
if lock.locked():
|
||||||
|
logger.warning(f"⚠️ 主动思考跳过:聊天流 {stream_id} 已有正在执行的主动思考任务")
|
||||||
|
return
|
||||||
|
|
||||||
|
async with lock:
|
||||||
logger.debug(f"🤔 开始主动思考 {stream_id}")
|
logger.debug(f"🤔 开始主动思考 {stream_id}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 0. 前置检查
|
# 0. 前置检查
|
||||||
|
# 0.0 检查聊天流是否正在处理消息(双重保护)
|
||||||
|
try:
|
||||||
|
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||||
|
chat_manager = get_chat_manager()
|
||||||
|
chat_stream = await chat_manager.get_stream(stream_id)
|
||||||
|
|
||||||
|
if chat_stream and chat_stream.context_manager.context.is_chatter_processing:
|
||||||
|
logger.warning(f"⚠️ 主动思考跳过:聊天流 {stream_id} 的 chatter 正在处理消息")
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"检查 chatter 处理状态时出错: {e},继续执行")
|
||||||
|
|
||||||
# 0.1 检查白名单/黑名单
|
# 0.1 检查白名单/黑名单
|
||||||
# 从 stream_id 获取 stream_config 字符串进行验证
|
# 从 stream_id 获取 stream_config 字符串进行验证
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user