fix(qa): 加 QA recorder runtime error monitor (closes #168)

QA 录音中麦克风设备消失 / cpal 内部 panic 时,QA 流程之前**没有**对应
runtime error 监听器(recorder_errors 用 _ 弃用),导致:
- QA 浮窗一直显示"录音中"
- 用户按 Option 第二次没反应
- 必须按 Esc 才能脱困

修:
- 新增 spawn_qa_recorder_error_monitor,镜像 dictation 现有 spawn_recorder_error_monitor
- begin_qa_session Recorder::start 成功后启动监听器
- 用 qa_state.session_id 守卫 stale 事件
- 收到 error → finish_qa_with_error("录音设备异常: ..") → emit 错误胶囊 + 浮窗错误状态

测试:
- cargo check ✅
This commit is contained in:
baiqing committed 2026-05-02 10:46:03 +08:00
1 parent ca7b68053b
commit 65d4b5243b
1 file changed
+31 -1
+31 -1
View File
@@ -1039,6 +1039,33 @@ fn spawn_recorder_error_monitor(inner: &Arc<Inner>, rx: mpsc::Receiver<RecorderE
.ok();
}
/// QA 录音 runtime error 监听器。镜像 `spawn_recorder_error_monitor` 的语义但走 QA
/// 收尾路径(`finish_qa_with_error` 替代 `abort_recording_with_error`)。
/// 用 qa_state.session_id 守卫 stale 事件。详见 issue #168。
fn spawn_qa_recorder_error_monitor(inner: &Arc<Inner>, rx: mpsc::Receiver<RecorderError>) {
let captured_session_id = inner.qa_state.lock().session_id;
let inner = Arc::clone(inner);
std::thread::Builder::new()
.name("openless-qa-recorder-error-monitor".into())
.spawn(move || {
if let Ok(err) = rx.recv() {
let current_session_id = inner.qa_state.lock().session_id;
if captured_session_id != current_session_id {
log::warn!(
"[coord] QA recorder error from stale session {} dropped (current={}, err={})",
captured_session_id,
current_session_id,
err
);
return;
}
log::error!("[coord] QA recorder runtime error: {err}");
finish_qa_with_error(&inner, format!("录音设备异常: {err}"));
}
})
.ok();
}
fn abort_recording_with_error(inner: &Arc<Inner>, message: String) {
let elapsed = {
let mut state = inner.state.lock();
@@ -1754,8 +1781,11 @@ async fn begin_qa_session(inner: &Arc<Inner>) -> Result<(), String> {
});
match Recorder::start(consumer, level_handler) {
Ok((rec, _runtime_errors)) => {
Ok((rec, runtime_errors)) => {
*inner.qa_recorder.lock() = Some(rec);
// QA 也跟主听写一样监听 cpal runtime error。设备中途消失 / panic 时
// 不能让 QA 永远卡在 Recording 没反馈。详见 issue #168。
spawn_qa_recorder_error_monitor(inner, runtime_errors);
}
Err(e) => {
log::error!("[coord] QA recorder start failed: {e}");