refactor: 第二轮架构缺陷修复 (1/2/3/4/9/10)

1. 内存泄漏修复:RealtimeChatManager 添加会话自动清理机制
   - 每10次操作检查超时会话(1小时无活动自动清理)
   - 最大活跃会话数限制500,超限清理最旧会话

2. 数据库索引补全:
   - Conversation: session_id, work_order_id 添加索引
   - WorkOrder: status 添加索引
   - ChatSession: user_id 添加索引
   - KnowledgeEntry: category, is_active, is_verified 添加索引

3. ServiceManager 线程安全:
   - 添加 threading.Lock 双重检查锁
   - 防止多线程并发初始化同一服务

4. API 响应格式统一:
   - 新增 api_response() 标准响应函数
   - 统一格式: {success, message, data} / {success, error}

9. asyncio 误用修复:
   - knowledge.py 文件上传改用安全的 asyncio 调用方式
   - 兼容已有事件循环和无事件循环两种场景

10. 请求限流:
    - 新增 rate_limit 装饰器(按 IP 限流)
    - chat/message 限制 20次/分钟
    - workorder/ai-suggestion 限制 5次/分钟
This commit is contained in:
2026-04-02 22:37:44 +08:00
parent 587933f668
commit 7151070c99
11 changed files with 138 additions and 38 deletions

View File

@@ -49,7 +49,7 @@ class WorkOrder(Base):
description = Column(Text, nullable=False)
category = Column(String(100), nullable=False)
priority = Column(String(20), nullable=False)
status = Column(String(20), nullable=False)
status = Column(String(20), nullable=False, index=True)
created_at = Column(DateTime, default=datetime.now)
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
resolution = Column(Text)
@@ -97,8 +97,8 @@ class ChatSession(Base):
id = Column(Integer, primary_key=True)
tenant_id = Column(String(50), nullable=False, default=DEFAULT_TENANT, index=True)
session_id = Column(String(100), unique=True, nullable=False) # 唯一会话标识
user_id = Column(String(100), nullable=True) # 用户标识
session_id = Column(String(100), unique=True, nullable=False)
user_id = Column(String(100), nullable=True, index=True)
work_order_id = Column(Integer, ForeignKey("work_orders.id"), nullable=True)
title = Column(String(200), nullable=True) # 会话标题(取首条消息摘要)
status = Column(String(20), default="active") # active, ended
@@ -135,8 +135,8 @@ class Conversation(Base):
id = Column(Integer, primary_key=True)
tenant_id = Column(String(50), nullable=False, default=DEFAULT_TENANT, index=True)
session_id = Column(String(100), ForeignKey("chat_sessions.session_id"), nullable=True) # 关联会话
work_order_id = Column(Integer, ForeignKey("work_orders.id"))
session_id = Column(String(100), ForeignKey("chat_sessions.session_id"), nullable=True, index=True)
work_order_id = Column(Integer, ForeignKey("work_orders.id"), index=True)
user_message = Column(Text, nullable=False)
assistant_response = Column(Text, nullable=False)
timestamp = Column(DateTime, default=datetime.now)
@@ -162,13 +162,13 @@ class KnowledgeEntry(Base):
tenant_id = Column(String(50), nullable=False, default=DEFAULT_TENANT, index=True)
question = Column(Text, nullable=False)
answer = Column(Text, nullable=False)
category = Column(String(100), nullable=False)
category = Column(String(100), nullable=False, index=True)
confidence_score = Column(Float, default=0.0)
usage_count = Column(Integer, default=0)
created_at = Column(DateTime, default=datetime.now)
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
is_active = Column(Boolean, default=True)
is_verified = Column(Boolean, default=False) # 是否已验证
is_active = Column(Boolean, default=True, index=True)
is_verified = Column(Boolean, default=False, index=True)
verified_by = Column(String(100)) # 验证人
verified_at = Column(DateTime) # 验证时间
vector_embedding = Column(Text) # 向量嵌入的JSON字符串