Merge branch 'dev' of https://github.com/MoFox-Studio/MoFox-Core into dev
This commit is contained in:
@@ -12,9 +12,7 @@ from functools import lru_cache
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
from sqlalchemy import delete, func, select, update
|
||||
from sqlalchemy.engine import CursorResult, Result
|
||||
|
||||
from src.common.database.core.models import Base
|
||||
from src.common.database.core.session import get_db_session
|
||||
from src.common.database.optimization import (
|
||||
BatchOperation,
|
||||
|
||||
@@ -15,7 +15,6 @@ from sqlalchemy import and_, asc, desc, func, or_, select
|
||||
|
||||
# 导入 CRUD 辅助函数以避免重复定义
|
||||
from src.common.database.api.crud import _dict_to_model, _model_to_dict
|
||||
from src.common.database.core.models import Base
|
||||
from src.common.database.core.session import get_db_session
|
||||
from src.common.database.optimization import get_cache, record_preload_access
|
||||
from src.common.logger import get_logger
|
||||
|
||||
@@ -91,7 +91,7 @@ async def store_action_info(
|
||||
)
|
||||
|
||||
# 使用get_or_create保存记录
|
||||
saved_record, created = await _action_records_crud.get_or_create(
|
||||
saved_record, _created = await _action_records_crud.get_or_create(
|
||||
defaults=record_data,
|
||||
action_id=action_id,
|
||||
)
|
||||
@@ -438,7 +438,7 @@ async def update_relationship_affinity(
|
||||
"""
|
||||
try:
|
||||
# 获取或创建关系
|
||||
relationship, created = await _user_relationships_crud.get_or_create(
|
||||
relationship, _created = await _user_relationships_crud.get_or_create(
|
||||
defaults={"affinity": 0.0, "interaction_count": 0},
|
||||
platform=platform,
|
||||
user_id=user_id,
|
||||
|
||||
@@ -300,7 +300,7 @@ async def db_save(
|
||||
crud = CRUDBase(model_class)
|
||||
|
||||
# 使用get_or_create (返回tuple[T, bool])
|
||||
instance, created = await crud.get_or_create(
|
||||
instance, _created = await crud.get_or_create(
|
||||
defaults=data,
|
||||
**{key_field: key_value},
|
||||
)
|
||||
|
||||
@@ -100,14 +100,14 @@ async def check_and_migrate_database(existing_engine=None):
|
||||
|
||||
def add_columns_sync(conn):
|
||||
dialect = conn.dialect
|
||||
|
||||
|
||||
for column_name in missing_columns:
|
||||
column = table.c[column_name]
|
||||
|
||||
|
||||
# 获取列类型的 SQL 表示
|
||||
# 直接使用 compile 方法,它会自动选择正确的方言
|
||||
column_type_sql = column.type.compile(dialect=dialect)
|
||||
|
||||
|
||||
# 构建 ALTER TABLE 语句
|
||||
sql = f"ALTER TABLE {table.name} ADD COLUMN {column.name} {column_type_sql}"
|
||||
|
||||
@@ -285,7 +285,7 @@ def _normalize_pg_type(type_name: str) -> str:
|
||||
|
||||
async def _check_and_fix_column_types(connection, inspector, table_name, table, db_columns_info):
|
||||
"""检查并修复列类型不匹配的问题(仅 PostgreSQL)
|
||||
|
||||
|
||||
Args:
|
||||
connection: 数据库连接
|
||||
inspector: SQLAlchemy inspector
|
||||
@@ -296,41 +296,41 @@ async def _check_and_fix_column_types(connection, inspector, table_name, table,
|
||||
# 获取数据库方言
|
||||
def get_dialect_name(conn):
|
||||
return conn.dialect.name
|
||||
|
||||
|
||||
dialect_name = await connection.run_sync(get_dialect_name)
|
||||
|
||||
|
||||
# 目前只处理 PostgreSQL
|
||||
if dialect_name != "postgresql":
|
||||
return
|
||||
|
||||
|
||||
for (fix_table, fix_column), (expected_type_category, using_clause) in _COLUMN_TYPE_FIXES.items():
|
||||
if fix_table != table_name:
|
||||
continue
|
||||
|
||||
|
||||
if fix_column not in db_columns_info:
|
||||
continue
|
||||
|
||||
|
||||
col_info = db_columns_info[fix_column]
|
||||
current_type = _normalize_pg_type(str(col_info.get("type", "")))
|
||||
expected_type = _get_expected_pg_type(expected_type_category)
|
||||
|
||||
|
||||
# 如果类型已经正确,跳过
|
||||
if current_type == expected_type:
|
||||
continue
|
||||
|
||||
|
||||
# 检查是否需要修复:如果当前是 numeric 但期望是 boolean
|
||||
if current_type == "numeric" and expected_type == "boolean":
|
||||
logger.warning(
|
||||
f"发现列类型不匹配: {table_name}.{fix_column} "
|
||||
f"(当前: {current_type}, 期望: {expected_type})"
|
||||
)
|
||||
|
||||
|
||||
# PostgreSQL 需要先删除默认值,再修改类型,最后重新设置默认值
|
||||
using_sql = using_clause.format(column=fix_column)
|
||||
drop_default_sql = f"ALTER TABLE {table_name} ALTER COLUMN {fix_column} DROP DEFAULT"
|
||||
alter_type_sql = f"ALTER TABLE {table_name} ALTER COLUMN {fix_column} TYPE BOOLEAN {using_sql}"
|
||||
set_default_sql = f"ALTER TABLE {table_name} ALTER COLUMN {fix_column} SET DEFAULT FALSE"
|
||||
|
||||
|
||||
try:
|
||||
def execute_alter(conn):
|
||||
# 步骤 1: 删除默认值
|
||||
@@ -342,7 +342,7 @@ async def _check_and_fix_column_types(connection, inspector, table_name, table,
|
||||
conn.execute(text(alter_type_sql))
|
||||
# 步骤 3: 重新设置默认值
|
||||
conn.execute(text(set_default_sql))
|
||||
|
||||
|
||||
await connection.run_sync(execute_alter)
|
||||
await connection.commit()
|
||||
logger.info(f"成功修复列类型: {table_name}.{fix_column} -> BOOLEAN")
|
||||
|
||||
@@ -651,7 +651,7 @@ class UserPermissions(Base):
|
||||
|
||||
class UserRelationships(Base):
|
||||
"""用户关系模型 - 存储用户与bot的关系数据
|
||||
|
||||
|
||||
核心字段:
|
||||
- relationship_text: 当前印象描述(用于兼容旧系统,逐步迁移到 impression_text)
|
||||
- impression_text: 长期印象(新字段,自然叙事风格)
|
||||
@@ -667,19 +667,19 @@ class UserRelationships(Base):
|
||||
user_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, unique=True, index=True)
|
||||
user_name: Mapped[str | None] = mapped_column(get_string_field(100), nullable=True)
|
||||
user_aliases: Mapped[str | None] = mapped_column(Text, nullable=True) # 用户别名,逗号分隔
|
||||
|
||||
|
||||
# 印象相关(新旧兼容)
|
||||
relationship_text: Mapped[str | None] = mapped_column(Text, nullable=True) # 旧字段,保持兼容
|
||||
impression_text: Mapped[str | None] = mapped_column(Text, nullable=True) # 新字段:长期印象(自然叙事)
|
||||
|
||||
|
||||
# 用户信息
|
||||
preference_keywords: Mapped[str | None] = mapped_column(Text, nullable=True) # 用户偏好关键词,逗号分隔
|
||||
key_facts: Mapped[str | None] = mapped_column(Text, nullable=True) # 关键信息JSON(生日、职业等)
|
||||
|
||||
|
||||
# 关系状态
|
||||
relationship_score: Mapped[float] = mapped_column(Float, nullable=False, default=0.3) # 好感度(0-1)
|
||||
relationship_stage: Mapped[str | None] = mapped_column(get_string_field(50), nullable=True, default="stranger") # 关系阶段
|
||||
|
||||
|
||||
# 时间记录
|
||||
first_met_time: Mapped[float | None] = mapped_column(Float, nullable=True) # 首次认识时间戳
|
||||
last_impression_update: Mapped[float | None] = mapped_column(Float, nullable=True) # 上次更新印象时间
|
||||
|
||||
@@ -378,7 +378,7 @@ class AdaptiveBatchScheduler:
|
||||
# 过滤掉 id 为 None 的键,让数据库自动生成主键
|
||||
filtered_data = {k: v for k, v in op.data.items() if not (k == "id" and v is None)}
|
||||
all_data.append(filtered_data)
|
||||
|
||||
|
||||
if not all_data:
|
||||
return
|
||||
|
||||
|
||||
@@ -440,8 +440,8 @@ class MultiLevelCache:
|
||||
|
||||
# 计算共享键和独占键
|
||||
shared_keys = l1_keys & l2_keys
|
||||
l1_only_keys = l1_keys - l2_keys
|
||||
l2_only_keys = l2_keys - l1_keys
|
||||
l1_keys - l2_keys
|
||||
l2_keys - l1_keys
|
||||
|
||||
# 🔧 修复:并行计算内存使用,避免锁嵌套
|
||||
l1_size_task = asyncio.create_task(self._calculate_memory_usage_safe(self.l1_cache, l1_keys))
|
||||
|
||||
@@ -10,7 +10,7 @@ import asyncio
|
||||
import functools
|
||||
import hashlib
|
||||
import time
|
||||
from collections.abc import Awaitable, Callable, Coroutine
|
||||
from collections.abc import Callable, Coroutine
|
||||
from typing import Any, ParamSpec, TypeVar
|
||||
|
||||
from sqlalchemy.exc import DBAPIError, OperationalError
|
||||
|
||||
Reference in New Issue
Block a user