Skip to content

Commit 1a88581

Browse files
committed
perf(notes): 清偿TD-A——会话转笔记三命令迁spawn_blocking
1 parent 0336b51 commit 1a88581

1 file changed

Lines changed: 62 additions & 39 deletions

File tree

‎app/src-tauri/src/commands_session_note.rs‎

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -157,26 +157,35 @@ fn convert_to_note(
157157
}
158158

159159
/// 会话 → 笔记:转写段 + OCR 块经 note_filter 净化管线,一键落库(REQ-010 闭环)。
160+
///
161+
/// @ai-context: TD-2026-08-20-A 清偿:主体迁 spawn_blocking——v0.7.6 起管线叠加
162+
/// analyze_session_opt 全量分析(章节/术语/重点等),千段长会话
163+
/// 可达秒级,不得占用异步运行时线程(review_text_filter 先例)。
160164
#[tauri::command]
161165
pub async fn session_to_note(
162166
state: State<'_, AppState>,
163167
id: i64,
164168
title: Option<String>,
165169
ai_decisions: Option<Vec<TextFilterDecision>>,
166170
) -> Result<Note, String> {
167-
convert_to_note(
168-
&state.db,
169-
&state.ui_junk,
170-
&PurifyEnv {
171-
config: state.purify.clone(),
172-
symbol: state.symbol_normalize.clone(),
173-
corrections: state.ocr_corrections.clone(),
174-
},
175-
&state.data_dir,
176-
id,
177-
title,
178-
ai_decisions,
179-
)
171+
let state: AppState = (*state).clone();
172+
tauri::async_runtime::spawn_blocking(move || {
173+
convert_to_note(
174+
&state.db,
175+
&state.ui_junk,
176+
&PurifyEnv {
177+
config: state.purify.clone(),
178+
symbol: state.symbol_normalize.clone(),
179+
corrections: state.ocr_corrections.clone(),
180+
},
181+
&state.data_dir,
182+
id,
183+
title,
184+
ai_decisions,
185+
)
186+
})
187+
.await
188+
.map_err(|e| format!("转笔记任务失败: {}", e))?
180189
}
181190

182191
/// 批量转笔记核心编排(v0.7.1:部分成功语义——单条失败不阻塞其他)。
@@ -238,22 +247,29 @@ pub fn run_batch_conversion(
238247
}
239248

240249
/// 批量转笔记(v0.7.1 会话体验:列表勾选批量转化)。
250+
/// @ai-context: TD-2026-08-20-A 清偿:迁 spawn_blocking(≤50 条 × 全量分析,
251+
/// 长会话批量可达数十秒——不得阻塞异步运行时线程)。
241252
#[tauri::command]
242253
pub async fn batch_session_to_note(
243254
state: State<'_, AppState>,
244255
ids: Vec<i64>,
245256
) -> Result<BatchNoteResult, String> {
246-
run_batch_conversion(
247-
&state.db,
248-
&state.ui_junk,
249-
&PurifyEnv {
250-
config: state.purify.clone(),
251-
symbol: state.symbol_normalize.clone(),
252-
corrections: state.ocr_corrections.clone(),
253-
},
254-
&state.data_dir,
255-
ids,
256-
)
257+
let state: AppState = (*state).clone();
258+
tauri::async_runtime::spawn_blocking(move || {
259+
run_batch_conversion(
260+
&state.db,
261+
&state.ui_junk,
262+
&PurifyEnv {
263+
config: state.purify.clone(),
264+
symbol: state.symbol_normalize.clone(),
265+
corrections: state.ocr_corrections.clone(),
266+
},
267+
&state.data_dir,
268+
ids,
269+
)
270+
})
271+
.await
272+
.map_err(|e| format!("批量转笔记任务失败: {}", e))?
257273
}
258274

259275
/// 会话笔记预览(REQ-081):过滤后只读预览——不落库、不改库。
@@ -270,19 +286,26 @@ pub async fn preview_session_note(
270286
state: State<'_, AppState>,
271287
id: i64,
272288
) -> Result<NoteFilterResult, String> {
273-
let (session, segments, ocr_blocks) = load_note_material(&state.db, id)?;
274-
let env = PurifyEnv {
275-
config: state.purify.clone(),
276-
symbol: state.symbol_normalize.clone(),
277-
corrections: state.ocr_corrections.clone(),
278-
};
279-
let mut result = filter_note(&session.title, &segments, &ocr_blocks, &state.ui_junk, &env);
280-
let images_dir = state.data_dir.join("session-images").join(id.to_string());
281-
crate::screens::attach_images(&mut result.ocr_screens, &images_dir);
282-
// v0.7.5(REQ-170):预览与落库同口径——异常会话预览即带警示行
283-
crate::note_filter::apply_session_warning(&mut result, &session.status);
284-
crate::note_filter::refresh_screen_points(&mut result);
285-
// v0.7.6(REQ-177/178):结构渲染(与 convert_to_note 同函数同口径)
286-
apply_note_structure(&mut result, &state.db, &session, &segments, &ocr_blocks, &env);
287-
Ok(result)
289+
// TD-2026-08-20-A 清偿:迁 spawn_blocking(预览与落库同口径——全量分析
290+
// 同样耗时;数据所有权移入闭包,消除 segments/ocr_blocks 二次拷贝——观察 1)
291+
let state: AppState = (*state).clone();
292+
tauri::async_runtime::spawn_blocking(move || {
293+
let (session, segments, ocr_blocks) = load_note_material(&state.db, id)?;
294+
let env = PurifyEnv {
295+
config: state.purify.clone(),
296+
symbol: state.symbol_normalize.clone(),
297+
corrections: state.ocr_corrections.clone(),
298+
};
299+
let mut result = filter_note(&session.title, &segments, &ocr_blocks, &state.ui_junk, &env);
300+
let images_dir = state.data_dir.join("session-images").join(id.to_string());
301+
crate::screens::attach_images(&mut result.ocr_screens, &images_dir);
302+
// v0.7.5(REQ-170):预览与落库同口径——异常会话预览即带警示行
303+
crate::note_filter::apply_session_warning(&mut result, &session.status);
304+
crate::note_filter::refresh_screen_points(&mut result);
305+
// v0.7.6(REQ-177/178):结构渲染(与 convert_to_note 同函数同口径)
306+
apply_note_structure(&mut result, &state.db, &session, &segments, &ocr_blocks, &env);
307+
Ok(result)
308+
})
309+
.await
310+
.map_err(|e| format!("笔记预览任务失败: {}", e))?
288311
}

0 commit comments

Comments
 (0)