- Update aiapp views - Update device_interaction consumers and views - Update docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.1 KiB
6.1 KiB
服务器端代码修改记录
本文档记录每次对服务器端代码的修改,方便追踪变更历史。
修改格式说明
每次修改按以下格式记录:
### [日期] 修改简述
- **文件路径**: 相对于项目根目录的文件路径
- **修改类型**: 新增 / 修改 / 删除 / 重构 / 修复Bug
- **修改内容**: 具体修改了什么
- **修改原因**: 为什么要做这个修改
修改历史
[2026-04-29] 手机端聊天记录切换服务端字幕落库(B' 方案 服务端部分)
配套手机端方案文档:LTY_App_Project_URP/docs/手机端聊天记录_切换服务端字幕落库方案.md。手机端已实施 B'(本地 ASR 实时显示 + 服务端 webhook 静默替换),服务端需要补三件事:strategy B 落库后 group_send 推回客户端、DeviceConsumer 加 handler、RTCChatHistoryAPIView 灰度期去重 + since_id 增量拉取。
修改 1:strategy B 落库成功后 group_send 转推
- 文件路径:
device_interaction/views.py - 修改类型: 新增功能
- 修改内容:
- 在
conversation_statusaction 内字幕落库分支(约 L1414ChatMessage.objects.create(...)处):- 把
create()返回值赋给变量chat_msg,落库成功 log 加上id字段 - 落库成功后追加
channel_layer.group_send调用,向device_{paradise_user_id}群组发送type='chat_message_persisted'消息,payload 含id/sender/message/timestamp/source_client - 用独立
try/except包住,转推失败仅 warning 日志,不影响主落库流程
- 把
source_client暂传'unknown'(决策点 #3 落定后改为'phone'/'device')
- 在
- 修改原因:
- 手机端 B' 方案需要服务端在字幕入库后通过 WebSocket 把"权威 LLM 原始版本"推回客户端
- 手机端按
chat_msg.id去重 + 按(sender, timestamp ±10s)匹配本地待替换队列做静默替换,达到 UI 与 DB 字符级一致 - 不影响设备端:设备端不订阅
chat_message_persisted类型即可(DeviceConsumer handler 仅向已实现处理的客户端透传)
修改 2:DeviceConsumer 加 chat_message_persisted handler
- 文件路径:
device_interaction/consumers.py - 修改类型: 新增功能
- 修改内容:
- 在
conversation_subtitlehandler 之后新增chat_message_persistedhandler - 接收 group_send 事件后通过
self.send把 JSON 推到 WebSocket 客户端 - 日志记录
id/sender/source_client用于后续排查
- 在
- 修改原因:
- Channels 协议要求 group_send 的
type字段值在 Consumer 上有同名方法处理,否则消息被丢弃且报警 - 必须与修改 1 同步部署,否则 strategy B 的 group_send 调用会失败
- Channels 协议要求 group_send 的
修改 3:RTCChatHistoryAPIView 灰度期 POST 去重 + GET since_id 支持
- 文件路径:
aiapp/views.py - 修改类型: 新增功能 + 增强
- 修改内容:
RTCChatHistoryAPIView.post()入口加去重判定:同一(user, bot, sender, message)在±2s时间窗内已存在则跳过create,返回deduplicated: trueRTCChatHistoryAPIView.get()支持since_idquery 参数:传入则返回id > since_id的消息(升序,最多 page_size 条),未传则保持原最近 page_size 条逻辑
- 修改原因:
- 灰度期双倒保护:手机端 App 发版到用户手里需要时间,老版仍走 POST 落库;strategy B webhook 此时也在落库 → 同一对话产生重复行。POST 去重让两条路径并存而不致脏库
- 重放保护:strategy B 自身被火山重试或客户端重连补提时,去重也能挡住
- WebSocket 漏推兜底:B' 方案手机端 5s 超时未收到
chat_message_persisted时调GET ?since_id=<last>增量拉取替换队列里待修正的消息
关联代码(手机端,仅记录依赖关系)
- 手机端
Assets/Scripts/Manager/WebSocketNetworking.cs已新增chat_message_persisted类型分发分支 - 手机端
Assets/Scripts/AI/ChatLogManager.cs已新增OnServerChatPersisted方法、_pendingReplaceQueue与 5s 超时兜底 - 手机端
Assets/Scripts/AI/getJson.cs已加Config.SubtitleConfig.SubtitleMode=1
部署顺序与回滚
- 部署顺序:服务端先部署(修改 1+2+3 三处一同上线)→ 验证 group_send 通道工作 → 手机端再发版
- 回滚:三处改动都用独立 try/except 包住,可独立 git revert
- 修改 1 revert:strategy B 主流程不受影响,只是不再 group_send,手机端 UI 替换路径变为 5s 超时兜底
- 修改 2 revert:与修改 1 必须同时 revert,否则 group_send 收方为空报警
- 修改 3 revert:POST 不再去重(灰度期会出现双倒,需人工清理 DB);GET 不再支持 since_id(手机端兜底拉取无效)
待跟进 TODO
- 决策点 #3:服务端区分手机端 / 设备端 RTC session(mac 标记 / task_id 命名规则)→
source_client字段填充真实值,让两端按需过滤 - 决策点 #5:服务端验证打断时是否仍 flush 部分内容;如不 flush,手机端打断分支应跳过入待替换队列以避免 5s 超时空触发
- Phase 0 步骤 1:DB 双轨验证(SQL 见
LTY_App_Project_URP/docs/手机端聊天记录_切换服务端字幕落库方案.md) - Phase 0 步骤 4:清理历史脏数据(如发现)
[2026-03-17] 修复手机号登录时 IntegrityError
- 文件路径:
userapp/views.py - 修改类型: 修复Bug
- 修改内容:
PhoneLoginView.post()中get_or_create新增defaults={'username': phone_number} - 修改原因: 新用户首次通过手机号登录时,
get_or_create未设置username字段,导致username=""与数据库中已有空 username 记录冲突,触发IntegrityError: duplicate key value violates unique constraint "userapp_paradiseuser_username_key"。改为用手机号作为默认 username,保证唯一性。