更新后台管理消息列表;
This commit is contained in:
@@ -3,8 +3,13 @@ GLM聊天服务,包含角色配置管理
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
import os
|
||||
from typing import Optional
|
||||
from pymongo import AsyncMongoClient
|
||||
from beanie import init_beanie
|
||||
from app.models.glm_role import GLMRole
|
||||
from app.models import models
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -14,11 +19,19 @@ class GLMService:
|
||||
|
||||
def __init__(self):
|
||||
self._current_role: Optional[GLMRole] = None
|
||||
self._max_retries = 3
|
||||
self._retry_delay = 1 # 秒
|
||||
self._db_client: Optional[AsyncMongoClient] = None
|
||||
self._db_initialized = False
|
||||
|
||||
async def get_current_role(self) -> GLMRole:
|
||||
"""获取当前激活的角色配置"""
|
||||
if self._current_role is None:
|
||||
self._current_role = await self._load_or_create_role()
|
||||
logger.info("当前无缓存角色,开始加载角色配置")
|
||||
self._current_role = await self._load_or_create_role_with_retry()
|
||||
logger.info(f"角色加载完成: name='{self._current_role.name}'")
|
||||
else:
|
||||
logger.debug(f"使用缓存角色: name='{self._current_role.name}'")
|
||||
return self._current_role
|
||||
|
||||
async def update_role(self, role_data: dict) -> GLMRole:
|
||||
@@ -30,33 +43,153 @@ class GLMService:
|
||||
Returns:
|
||||
更新后的GLMRole实例
|
||||
"""
|
||||
logger.info(f"开始更新角色配置,更新字段: {list(role_data.keys())}")
|
||||
role = await self.get_current_role()
|
||||
|
||||
# 更新字段
|
||||
if "name" in role_data:
|
||||
# 记录更新前的值
|
||||
changes = []
|
||||
if "name" in role_data and role_data["name"] != role.name:
|
||||
changes.append(f"name: '{role.name}' -> '{role_data['name']}'")
|
||||
role.name = role_data["name"]
|
||||
if "description" in role_data:
|
||||
|
||||
if "description" in role_data and role_data["description"] != role.description:
|
||||
changes.append(
|
||||
f"description: {len(role.description)}字符 -> {len(role_data['description'])}字符"
|
||||
)
|
||||
role.description = role_data["description"]
|
||||
if "skills" in role_data:
|
||||
|
||||
if "skills" in role_data and role_data["skills"] != role.skills:
|
||||
old_skills_count = len(role.skills.split("\n")) if role.skills else 0
|
||||
new_skills_count = (
|
||||
len(role_data["skills"].split("\n")) if role_data["skills"] else 0
|
||||
)
|
||||
changes.append(f"skills: {old_skills_count}条 -> {new_skills_count}条")
|
||||
role.skills = role_data["skills"]
|
||||
if "restrictions" in role_data:
|
||||
|
||||
if (
|
||||
"restrictions" in role_data
|
||||
and role_data["restrictions"] != role.restrictions
|
||||
):
|
||||
old_restrictions_count = (
|
||||
len(role.restrictions.split("\n")) if role.restrictions else 0
|
||||
)
|
||||
new_restrictions_count = (
|
||||
len(role_data["restrictions"].split("\n"))
|
||||
if role_data["restrictions"]
|
||||
else 0
|
||||
)
|
||||
changes.append(
|
||||
f"restrictions: {old_restrictions_count}条 -> {new_restrictions_count}条"
|
||||
)
|
||||
role.restrictions = role_data["restrictions"]
|
||||
|
||||
role.update_timestamp()
|
||||
await role.save()
|
||||
|
||||
if changes:
|
||||
logger.info(f"角色配置变更: {', '.join(changes)}")
|
||||
else:
|
||||
logger.info("角色配置无实际变更")
|
||||
|
||||
# 使用重试机制保存
|
||||
await self._save_with_retry(role)
|
||||
|
||||
# 更新缓存
|
||||
self._current_role = role
|
||||
|
||||
logger.info(f"角色配置已更新: {role.name}")
|
||||
logger.info(f"角色配置更新完成: name='{role.name}'")
|
||||
return role
|
||||
|
||||
async def _load_or_create_role_with_retry(self) -> GLMRole:
|
||||
"""使用重试机制加载或创建默认角色"""
|
||||
for attempt in range(self._max_retries):
|
||||
try:
|
||||
return await self._load_or_create_role()
|
||||
except Exception as e:
|
||||
if attempt < self._max_retries - 1:
|
||||
logger.warning(f"加载角色配置失败,第{attempt + 1}次重试: {e}")
|
||||
await asyncio.sleep(self._retry_delay * (attempt + 1))
|
||||
else:
|
||||
logger.error(f"加载角色配置失败,已达到最大重试次数: {e}")
|
||||
raise
|
||||
|
||||
async def _ensure_db_connection(self) -> None:
|
||||
"""确保数据库连接正常,如果连接已关闭则重新连接"""
|
||||
if not self._db_initialized:
|
||||
await self._init_db_connection()
|
||||
|
||||
async def _init_db_connection(self) -> None:
|
||||
"""初始化数据库连接"""
|
||||
try:
|
||||
# 从环境变量获取数据库配置
|
||||
mongodb_url = os.getenv("MONGODB_URL", "mongodb://localhost:27017")
|
||||
database_name = os.getenv("DATABASE_NAME", "douba_chat_dev")
|
||||
|
||||
# 创建新的数据库连接
|
||||
if self._db_client:
|
||||
try:
|
||||
await self._db_client.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
self._db_client = AsyncMongoClient(mongodb_url)
|
||||
await init_beanie(
|
||||
database=self._db_client[database_name], document_models=models
|
||||
)
|
||||
self._db_initialized = True
|
||||
logger.info(f"数据库连接初始化成功: {database_name}")
|
||||
except Exception as e:
|
||||
logger.error(f"数据库连接初始化失败: {e}")
|
||||
self._db_initialized = False
|
||||
raise
|
||||
|
||||
async def _load_or_create_role(self) -> GLMRole:
|
||||
"""加载或创建默认角色"""
|
||||
try:
|
||||
# 确保数据库连接正常
|
||||
await self._ensure_db_connection()
|
||||
|
||||
# 1. 尝试获取激活的角色
|
||||
active_role = await GLMRole.find_one(GLMRole.is_active == True)
|
||||
if active_role:
|
||||
logger.info(f"加载激活角色: {active_role.name}")
|
||||
return active_role
|
||||
|
||||
# 2. 尝试获取默认角色
|
||||
default_role = await GLMRole.find_one(GLMRole.is_default == True)
|
||||
if default_role:
|
||||
default_role.is_active = True
|
||||
await default_role.save()
|
||||
logger.info(f"加载默认角色并激活: {default_role.name}")
|
||||
return default_role
|
||||
|
||||
# 3. 创建默认角色
|
||||
logger.info("创建默认角色配置")
|
||||
return await self._create_default_role()
|
||||
except Exception as e:
|
||||
logger.error(f"加载或创建角色失败: {e}")
|
||||
# 检查是否是数据库连接错误
|
||||
if (
|
||||
"Cannot use AsyncMongoClient after close" in str(e)
|
||||
or "not connected" in str(e).lower()
|
||||
):
|
||||
logger.error("数据库连接已关闭,尝试重新连接...")
|
||||
self._db_initialized = False
|
||||
# 尝试重新连接
|
||||
try:
|
||||
await self._init_db_connection()
|
||||
logger.info("数据库重新连接成功,重试操作...")
|
||||
# 重试操作
|
||||
return await self._retry_after_reconnect()
|
||||
except Exception as reconnect_error:
|
||||
logger.error(f"数据库重新连接失败: {reconnect_error}")
|
||||
raise
|
||||
|
||||
async def _retry_after_reconnect(self) -> GLMRole:
|
||||
"""重新连接后重试操作"""
|
||||
# 1. 尝试获取激活的角色
|
||||
active_role = await GLMRole.find_one(GLMRole.is_active == True)
|
||||
if active_role:
|
||||
logger.info(f"加载激活角色: {active_role.name}")
|
||||
logger.info(f"重新连接后加载激活角色: {active_role.name}")
|
||||
return active_role
|
||||
|
||||
# 2. 尝试获取默认角色
|
||||
@@ -64,11 +197,11 @@ class GLMService:
|
||||
if default_role:
|
||||
default_role.is_active = True
|
||||
await default_role.save()
|
||||
logger.info(f"加载默认角色并激活: {default_role.name}")
|
||||
logger.info(f"重新连接后加载默认角色并激活: {default_role.name}")
|
||||
return default_role
|
||||
|
||||
# 3. 创建默认角色
|
||||
logger.info("创建默认角色配置")
|
||||
logger.info("重新连接后创建默认角色配置")
|
||||
return await self._create_default_role()
|
||||
|
||||
async def _create_default_role(self) -> GLMRole:
|
||||
@@ -89,10 +222,40 @@ class GLMService:
|
||||
logger.info(f"默认角色创建成功: {role.name}")
|
||||
return role
|
||||
|
||||
async def _save_with_retry(self, role: GLMRole) -> None:
|
||||
"""使用重试机制保存角色"""
|
||||
for attempt in range(self._max_retries):
|
||||
try:
|
||||
# 确保数据库连接正常
|
||||
await self._ensure_db_connection()
|
||||
await role.save()
|
||||
return
|
||||
except Exception as e:
|
||||
if attempt < self._max_retries - 1:
|
||||
logger.warning(f"保存角色配置失败,第{attempt + 1}次重试: {e}")
|
||||
# 检查是否是数据库连接错误
|
||||
if (
|
||||
"Cannot use AsyncMongoClient after close" in str(e)
|
||||
or "not connected" in str(e).lower()
|
||||
):
|
||||
logger.warning("检测到数据库连接问题,尝试重新连接...")
|
||||
self._db_initialized = False
|
||||
try:
|
||||
await self._init_db_connection()
|
||||
logger.info("数据库重新连接成功,继续重试...")
|
||||
except Exception as reconnect_error:
|
||||
logger.error(f"数据库重新连接失败: {reconnect_error}")
|
||||
await asyncio.sleep(self._retry_delay * (attempt + 1))
|
||||
else:
|
||||
logger.error(f"保存角色配置失败,已达到最大重试次数: {e}")
|
||||
raise
|
||||
|
||||
async def ensure_default_role(self):
|
||||
"""确保存在默认角色配置(应用启动时调用)"""
|
||||
try:
|
||||
role = await self._load_or_create_role()
|
||||
# 确保数据库连接正常
|
||||
await self._ensure_db_connection()
|
||||
role = await self._load_or_create_role_with_retry()
|
||||
logger.info(f"默认角色已确保存在: {role.name}")
|
||||
return role
|
||||
except Exception as e:
|
||||
@@ -102,6 +265,13 @@ class GLMService:
|
||||
async def close(self):
|
||||
"""关闭服务,清理资源"""
|
||||
self._current_role = None
|
||||
if self._db_client:
|
||||
try:
|
||||
await self._db_client.close()
|
||||
logger.info("数据库连接已关闭")
|
||||
except Exception as e:
|
||||
logger.error(f"关闭数据库连接时出错: {e}")
|
||||
self._db_initialized = False
|
||||
logger.info("GLM服务已关闭")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user