From a9a9f380d608929187805688197f2d5afa19190e Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Sat, 20 Sep 2025 22:21:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor(person=5Finfo):=20=E5=BC=95=E5=85=A5?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=96=B9=E6=B3=95=20get=5Fvalue=20=E5=B9=B6?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=97=A7=E7=9A=84=20get=5Fvalue=5Fsync(?= =?UTF-8?q?=E5=9B=A0=E4=B8=BA=E6=A0=B9=E6=9C=AC=E5=B0=B1=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E8=BF=99=E4=B8=AA=E6=96=B9=E6=B3=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为了解决在不同异步上下文中同步调用数据库可能引发的运行时错误,实现了一个新的、更健壮的同步方法 `PersonInfoManager.get_value`。 - 新方法能够正确处理已在运行的 asyncio 事件循环,提高了在混合代码环境中调用的稳定性。 - 全面替换了原有的 `get_value_sync` 方法调用,统一了同步获取用户信息的接口。 --- src/chat/utils/chat_message_builder.py | 4 +-- src/chat/utils/prompt.py | 2 +- src/chat/utils/utils.py | 2 +- src/person_info/person_info.py | 40 ++++++++++++++++++++++++- src/person_info/relationship_builder.py | 8 ++--- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index e49c218c4..b5fe33373 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -46,8 +46,8 @@ def replace_user_references_sync( if replace_bot_name and user_id == global_config.bot.qq_account: return f"{global_config.bot.nickname}(你)" person_id = PersonInfoManager.get_person_id(platform, user_id) - return person_info_manager.get_value_sync(person_id, "person_name") or user_id # type: ignore - + return person_info_manager.get_value(person_id, "person_name") or user_id # type: ignore + name_resolver = default_resolver # 处理回复格式 diff --git a/src/chat/utils/prompt.py b/src/chat/utils/prompt.py index 2f115aa98..db31acfa5 100644 --- a/src/chat/utils/prompt.py +++ b/src/chat/utils/prompt.py @@ -965,7 +965,7 @@ class Prompt: person_info_manager = get_person_info_manager() person_id = person_info_manager.get_person_id_by_person_name(sender) if person_id: - user_id = person_info_manager.get_value_sync(person_id, "user_id") + user_id = person_info_manager.get_value(person_id, "user_id") return str(user_id) if user_id else "" return "" diff --git a/src/chat/utils/utils.py b/src/chat/utils/utils.py index 99647e36c..5eb4cc991 100644 --- a/src/chat/utils/utils.py +++ b/src/chat/utils/utils.py @@ -663,7 +663,7 @@ def get_chat_type_and_target_info(chat_id: str) -> Tuple[bool, Optional[Dict]]: if person_id: # get_value is async, so await it directly person_info_manager = get_person_info_manager() - person_name = person_info_manager.get_value_sync(person_id, "person_name") + person_name = person_info_manager.get_value(person_id, "person_name") target_info["person_id"] = person_id target_info["person_name"] = person_name diff --git a/src/person_info/person_info.py b/src/person_info/person_info.py index 3a036d029..f5bf8a515 100644 --- a/src/person_info/person_info.py +++ b/src/person_info/person_info.py @@ -512,6 +512,45 @@ class PersonInfoManager: logger.debug(f"删除失败:未找到 person_id={person_id} 或删除未影响行") + @staticmethod + def get_value(person_id: str, field_name: str) -> Any: + """获取单个字段值(同步版本)""" + if not person_id: + logger.debug("get_value获取失败:person_id不能为空") + return None + + import asyncio + + async def _get_record_sync(): + async with get_db_session() as session: + return (await session.execute(select(PersonInfo).where(PersonInfo.person_id == person_id))).scalar() + + try: + record = asyncio.run(_get_record_sync()) + except RuntimeError: + # 如果当前线程已经有事件循环在运行,则使用现有的循环 + loop = asyncio.get_running_loop() + record = loop.run_until_complete(_get_record_sync()) + + model_fields = [column.name for column in PersonInfo.__table__.columns] + + if field_name not in model_fields: + if field_name in person_info_default: + logger.debug(f"字段'{field_name}'不在SQLAlchemy模型中,使用默认配置值。") + return copy.deepcopy(person_info_default[field_name]) + else: + logger.debug(f"get_value查询失败:字段'{field_name}'未在SQLAlchemy模型和默认配置中定义。") + return None + + if record: + value = getattr(record, field_name) + if value is not None: + return value + else: + return copy.deepcopy(person_info_default.get(field_name)) + else: + return copy.deepcopy(person_info_default.get(field_name)) + @staticmethod async def get_values(person_id: str, field_names: list) -> dict: """获取指定person_id文档的多个字段值,若不存在该字段,则返回该字段的全局默认值""" @@ -550,7 +589,6 @@ class PersonInfoManager: result[field_name] = copy.deepcopy(person_info_default.get(field_name)) return result - @staticmethod async def get_specific_value_list( field_name: str, diff --git a/src/person_info/relationship_builder.py b/src/person_info/relationship_builder.py index 1ff90a99d..35ac76d7d 100644 --- a/src/person_info/relationship_builder.py +++ b/src/person_info/relationship_builder.py @@ -138,7 +138,7 @@ class RelationshipBuilder: "message_count": await self._count_messages_in_timerange(potential_start_time, message_time), } segments.append(new_segment) - person_name = get_person_info_manager().get_value_sync(person_id, "person_name") or person_id + person_name = get_person_info_manager().get_value(person_id, "person_name") or person_id logger.debug( f"{self.log_prefix} 眼熟用户 {person_name} 在 {time.strftime('%H:%M:%S', time.localtime(potential_start_time))} - {time.strftime('%H:%M:%S', time.localtime(message_time))} 之间有 {new_segment['message_count']} 条消息" ) @@ -178,7 +178,7 @@ class RelationshipBuilder: } segments.append(new_segment) person_info_manager = get_person_info_manager() - person_name = person_info_manager.get_value_sync(person_id, "person_name") or person_id + person_name = person_info_manager.get_value(person_id, "person_name") or person_id logger.debug( f"{self.log_prefix} 重新眼熟用户 {person_name} 创建新消息段(超过10条消息间隔): {new_segment}" ) @@ -368,8 +368,8 @@ class RelationshipBuilder: users_to_build_relationship = [] for person_id, segments in self.person_engaged_cache.items(): total_message_count = self._get_total_message_count(person_id) - person_name = get_person_info_manager().get_value_sync(person_id, "person_name") or person_id - + person_name = get_person_info_manager().get_value(person_id, "person_name") or person_id + if total_message_count >= max_build_threshold or ( total_message_count >= 5 and (immediate_build == person_id or immediate_build == "all") ):