2.8 KiB
2.8 KiB
TODO: 语音实时分段上传的取消逻辑
背景
当前 cancelRecordingVoice() 只做了:停止录音、删除当前临时文件、重置会话状态,没有处理:
- 已入队的待上传分段(
pendingVoiceSegmentStore) - 重试任务(
pendingSegmentRetryJob) - 正在执行的
dispatchPendingVoiceSegment协程
用户取消后,已切好的分段仍可能被发送或重试。
目标
用户点击「取消」后:当前语音会话的所有分段不再上传、不再重试,并释放相关资源。
TODO 列表
1. ViewModel 增加「已取消会话」集合
- 在
CreateMemoryViewModel中增加:cancelledVoiceSessionIds: MutableSet<String> - 在开始新一轮录音时(如
startRecordingVoice()或ensureVoiceSessionStarted())清理该集合,避免无限增长(可选:只保留最近 N 个或按会话生命周期清理)
2. 完善 cancelRecordingVoice()
- 在调用
resetVoiceSessionState()之前 保存currentVoiceSessionId到局部变量sessionId - 若
sessionId != null:cancelledVoiceSessionIds.add(sessionId)pendingSegmentRetryJob?.cancel()- 列出该 session 的所有待发分段并逐个从 store 删除:
- 若 Store 无按
voiceSessionId查询:用pendingVoiceSegmentStore.listAll().filter { it.voiceSessionId == sessionId },对每个调用pendingVoiceSegmentStore.remove(segment.clientSegmentId)
- 若 Store 无按
- 再调用
resetVoiceSessionState()(保持现有逻辑)
3. dispatchPendingVoiceSegment 开头做取消判断
- 在
tryAcquirePendingDispatch之后、ensureConversationReadyForSegmentUpload()之前增加:- 若
pendingSegment.voiceSessionId in cancelledVoiceSessionIds:pendingVoiceSegmentStore.remove(pendingSegment.clientSegmentId)releasePendingDispatch(pendingSegment.clientSegmentId)return
- 若
- 确保
finally中releasePendingDispatch仍对正常路径执行(现有逻辑保持不变)
4. (可选)Store 按 session 列举
- 在
PendingVoiceSegmentStore增加listByVoiceSession(voiceSessionId: String): List<PendingVoiceSegment>(例如基于listAll().filter { it.voiceSessionId == voiceSessionId }) - 在
cancelRecordingVoice()中用listByVoiceSession(sessionId)替代listAll().filter { ... },减少全量列举
涉及文件
app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/CreateMemoryViewModel.ktapp-android/app/src/main/java/com/huaga/life_echo/feature/voice/PendingVoiceSegmentStore.kt(仅当做第 4 项时)
验收
- 长按录音并触发至少一次自动切片(如 30s)后,点击取消:本地待发分段被清除,不再上传,重试任务不执行。
- 取消后再次录音:新会话正常录音与分段上传,无旧 session 分段被发送。