Files
life-echo/docs/todo/voice-segment-cancel-logic.md
2026-03-10 15:47:25 +08:00

2.8 KiB
Raw Blame History

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)
  • 再调用 resetVoiceSessionState()(保持现有逻辑)

3. dispatchPendingVoiceSegment 开头做取消判断

  • tryAcquirePendingDispatch 之后、ensureConversationReadyForSegmentUpload() 之前增加:
    • pendingSegment.voiceSessionId in cancelledVoiceSessionIds
      • pendingVoiceSegmentStore.remove(pendingSegment.clientSegmentId)
      • releasePendingDispatch(pendingSegment.clientSegmentId)
      • return
  • 确保 finallyreleasePendingDispatch 仍对正常路径执行(现有逻辑保持不变)

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.kt
  • app-android/app/src/main/java/com/huaga/life_echo/feature/voice/PendingVoiceSegmentStore.kt(仅当做第 4 项时)

验收

  • 长按录音并触发至少一次自动切片(如 30s点击取消本地待发分段被清除不再上传重试任务不执行。
  • 取消后再次录音:新会话正常录音与分段上传,无旧 session 分段被发送。