refactor(db): 修复异步连接池无界增长,并完成 SQLAlchemy 2.0 迁移与分层归位 (#6320)

This commit is contained in:
Aqr-K
2026-08-15 06:58:38 +08:00
committed by GitHub
parent e28de9cfe1
commit 8a11214a43
252 changed files with 11405 additions and 2889 deletions
+32 -33
View File
@@ -1,8 +1,8 @@
from typing import Optional
from typing import Any, Optional
from sqlalchemy import Column, Integer, String, JSON, Index, select
from sqlalchemy import Integer, String, JSON, Index, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session
from sqlalchemy.orm import Mapped, Session, mapped_column
from app.db import Base, async_db_query, db_query, get_id_column
@@ -14,33 +14,33 @@ class AgentChat(Base):
id = get_id_column()
# Agent 内部会话 ID,用于恢复 LangGraph 对话上下文
session_id = Column(String, nullable=False)
session_id: Mapped[str] = mapped_column(String, nullable=False)
# 前端或渠道侧传入的原始会话标识
client_session_id = Column(String)
client_session_id: Mapped[Optional[str]] = mapped_column(String)
# 用户 ID
user_id = Column(String)
user_id: Mapped[Optional[str]] = mapped_column(String)
# 用户名称
username = Column(String)
username: Mapped[Optional[str]] = mapped_column(String)
# 消息渠道
channel = Column(String)
channel: Mapped[Optional[str]] = mapped_column(String)
# 渠道来源配置名
source = Column(String)
source: Mapped[Optional[str]] = mapped_column(String)
# 原聊天 ID,用于区分群聊、频道或私聊
original_chat_id = Column(String)
original_chat_id: Mapped[Optional[str]] = mapped_column(String)
# 会话标题
title = Column(String)
title: Mapped[Optional[str]] = mapped_column(String)
# 会话预览文本
preview = Column(String)
preview: Mapped[Optional[str]] = mapped_column(String)
# 原始 LangChain messages,用于继续会话
agent_messages = Column(JSON)
agent_messages: Mapped[Optional[Any]] = mapped_column(JSON)
# 展示给用户的消息记录,包含文字、工具提示、附件与选择卡片
display_messages = Column(JSON)
display_messages: Mapped[Optional[Any]] = mapped_column(JSON)
# 展示消息数量
message_count = Column(Integer, default=0)
message_count: Mapped[Optional[int]] = mapped_column(Integer, default=0)
# 创建时间
created_at = Column(String)
created_at: Mapped[Optional[str]] = mapped_column(String)
# 更新时间
updated_at = Column(String)
updated_at: Mapped[Optional[str]] = mapped_column(String)
__table_args__ = (
Index("ix_agentchat_session_user", "session_id", "user_id"),
@@ -56,10 +56,10 @@ class AgentChat(Base):
"""
根据会话 ID 获取 Agent 会话。
"""
query = db.query(cls).filter(cls.session_id == session_id)
statement = select(cls).where(cls.session_id == session_id)
if user_id is not None:
query = query.filter(cls.user_id == user_id)
return query.order_by(cls.id.desc()).first()
statement = statement.where(cls.user_id == user_id)
return db.execute(statement.order_by(cls.id.desc())).scalars().first()
@classmethod
@async_db_query
@@ -80,35 +80,34 @@ class AgentChat(Base):
def list_by_page(
cls,
db: Session,
page: Optional[int] = 1,
count: Optional[int] = 30,
page: int = 1,
count: int = 30,
user_id: Optional[str] = None,
username: Optional[str] = None,
) -> list["AgentChat"]:
"""
分页获取 Agent 会话历史。
"""
query = db.query(cls)
statement = select(cls)
if user_id is not None and username is not None:
query = query.filter((cls.user_id == user_id) | (cls.username == username))
statement = statement.where((cls.user_id == user_id) | (cls.username == username))
elif user_id is not None:
query = query.filter(cls.user_id == user_id)
statement = statement.where(cls.user_id == user_id)
elif username is not None:
query = query.filter(cls.username == username)
return (
query.order_by(cls.updated_at.desc(), cls.id.desc())
statement = statement.where(cls.username == username)
return list(db.execute(
statement.order_by(cls.updated_at.desc(), cls.id.desc())
.offset((page - 1) * count)
.limit(count)
.all()
)
).scalars().all())
@classmethod
@async_db_query
async def async_list_by_page(
cls,
db: AsyncSession,
page: Optional[int] = 1,
count: Optional[int] = 30,
page: int = 1,
count: int = 30,
user_id: Optional[str] = None,
username: Optional[str] = None,
) -> list["AgentChat"]:
@@ -127,4 +126,4 @@ class AgentChat(Base):
.offset((page - 1) * count)
.limit(count)
)
return result.scalars().all()
return list(result.scalars().all())