Skip to content

perf(coordinator): 可选热键 supervisor 注册成功即退出,消除稳态轮询 - #671

Merged
appergb merged 1 commit into
betafrom
fix/470-hotkey-supervisor-exit
Jun 16, 2026
Merged

perf(coordinator): 可选热键 supervisor 注册成功即退出,消除稳态轮询#671
appergb merged 1 commit into
betafrom
fix/470-hotkey-supervisor-exit

Conversation

@appergb

@appergbappergb commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

User description

源自 #470 Cloud 性能审查 #2。combo/translation/action 三类可选热键 supervisor 原本注册成功后不退出,稳态每 5s 醒来读 prefs,多线程常驻空转。

改动:对齐主 hotkey_supervisor_loop 的 exit-on-success 模式——到达「已安装」或「已主动停用」稳态即 return 退出,零稳态轮询。仅改控制流(sleep+continuereturn),无新增锁。

安全前提(已逐函数确认):用户启用/改/停这些热键时 set_*_hotkey 命令与 persist_settings diff 都会调 update_*_hotkey_binding,其覆盖「monitor 为 None → 从零 start+spawn」安装路径 → 退出后启停改键无需重启即时生效;ComboHotkeyMonitor 注册后驻留、无运行中自注销 → monitor 不会自己死,无需守护。有界路径(失败重试 3s / recv_timeout 5s / app未就绪 1s)全部保留。

验证:macOS cargo check 通过 + 对抗式复审 pass。Windows/Linux cfg 分支靠 CI(控制流三端等价,无 cfg 分歧)。


PR Type

Enhancement


Description

  • 消除 combo/translation/action 可选热键 supervisor 的稳态轮询

  • 对齐主 supervisor 的 exit-on-success 模式:注册成功即 return 退出

  • 依赖 update_*_hotkey_binding 主动路径确保启停即时生效,无需守护


Diagram Walkthrough

flowchart LR
Before("之前") --> Loop("loop {}") --> Check1["检查 prefs"] --> Decision1{"已安装/已禁用?"}
Decision1 -->|是| Uninstall["卸载热键"] --> Sleep["sleep 5s"] --> Loop
Decision1 -->|否| Decision2{"Monitor 已存在?"}
Decision2 -->|是| Sleep
Decision2 -->|否| Install["安装热键"] --> ReturnBefore["保持 loop"]
After("之后") --> Loop2["loop {}"] --> Check2["检查 prefs"] --> Decision3{"已安装/已禁用?"}
Decision3 -->|是| Uninstall2["卸载热键"] --> ReturnAfter1["return"]
Decision3 -->|否| Decision4{"Monitor 已存在?"}
Decision4 -->|是| ReturnAfter2["return"]
Decision4 -->|否| Install2["安装热键"] --> ReturnAfter3["return"]
Loading

File Walkthrough

Relevant files
Enhancement
coordinator.rs
supervisor loop exit-on-success

openless-all/app/src-tauri/src/coordinator.rs

  • 在 combo_hotkey_supervisor_loop 中将三个稳定状态分支从 sleep+continue 改为 return
  • 在 translation_hotkey_supervisor_loop 中将两个稳定状态分支改为 return
  • 在 action_hotkey_supervisor_loop 中将三个稳定状态分支改为 return
  • 添加注释说明对齐主 supervisor 的 exit-on-success 模式,依赖 update_*_hotkey_binding
    主动路径
+18/-18

issue #470:combo/translation/action 三类可选热键 supervisor 原本注册成功后不退出,稳态
每 5s 醒来读 prefs,多线程常驻空转。改为对齐主 hotkey_supervisor_loop 的 exit-on-success
模式——到达「已安装」或「已主动停用」稳态即 return 退出,零轮询。
安全前提(已逐函数确认):用户启用/改/停这些热键时,set_*_hotkey 命令与 persist_settings
diff 都会调 update_*_hotkey_binding,其覆盖「monitor 为 None → 从零 start+spawn」安装路径,
故退出后启停改键无需重启即时生效;ComboHotkeyMonitor 注册后驻留、无运行中自注销,monitor
不会自己死,无需 supervisor 守护。失败重试 sleep(3s)/recv_timeout(5s)/app未就绪 sleep(1s)
等有界路径全部保留。
@github-actions

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

2 - Partially compliant

Compliant requirements:

(empty)

Non-compliant requirements:

  • Add hold-to-talk hotkey mode alongside existing toggle mode
  • Emit .pressed/.released events in OpenLessHotkey
  • Update DictationCoordinator to interpret events per HotkeyMode
  • Add settings UI segmented picker for recording mode
  • Bump build version to 1.0.01/A1003

Requires further human verification:

(empty)

470 - Partially compliant

Compliant requirements:

(empty)

Non-compliant requirements:

  • Fix missing recording capsule (录音胶囊) on Windows when voice input is active
  • Ensure visual UI hint appears on desktop
  • Fix basic bug on Windows platform (P1)

Requires further human verification:

(empty)

⏱️ Estimated effort to review: 1 🔵⚪⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ No major issues detected

@appergb

Copy link
Copy Markdown
CollaboratorAuthor

@claude 请审查本 PR(#470#2:可选热键 supervisor 改 exit-on-success)。这是并发核心,重点核查:改成 return 的每处是否确为稳态(已安装/已停用)而非有界重试路径;退出后用户启用未配置热键时 update_*_binding 是否真从零安装 monitor(否则启用需重启的回归);有无引入竞态。

@claude

claudeBot commented Jun 15, 2026

Copy link
Copy Markdown

Claude finished @appergb's task in 2m 53s —— View job


PR #671 审查:可选热键 supervisor exit-on-success

  • 读取 coordinator.rs 相关代码
  • 核查每处 return 是否确为稳态而非有界重试路径
  • 核查 update_*_hotkey_binding 是否真从零安装 monitor
  • 检查竞态条件

结论:逻辑正确,可合并

三个核心问题全部通过。详细分析如下。


1. return 处是否确为稳态(非有界重试路径)✅

逐函数确认,所有 return 都在已完成动作的稳态分支,有界重试路径(recv_timeout 超时、init_result Err)一律保留为 sleep+continue

combo_hotkey_supervisor_loop(L2136–2218)

分支条件处理是稳态?
legacy_modifier_trigger is Some非 Custom 绑定take_combo_hotkeyreturn✅ 已卸载,主动路径管理
is_unconfigured_shortcut无有效主键take_combo_hotkeyreturn✅ 已卸载
combo_hotkey.lock().is_some()monitor 已装return✅ 已安装稳态
recv_timeout Err主线程未回执sleep 3s; continue✅ 保留重试
init_result Err注册失败sleep 3s; continue✅ 保留重试
app.lock().is_none()app 未就绪sleep 1s; continue✅ 保留重试

translation_hotkey_supervisor_loopaction_hotkey_supervisor_loop 同样模式,所有有界路径未改动。


2. update_*_binding 从零安装 monitor ✅

用户启用未配置热键时,update_*_binding 的 None 路径覆盖完整:

update_combo_hotkey_binding(L767–816)

// 在 run_on_main_thread 内:ifletSome(monitor) = inner_clone.combo_hotkey.lock().as_ref(){
monitor.update_binding(...);// 已有:换绑return;}// None 路径:ComboHotkeyMonitor::start(binding, tx)// 从零安装*inner_clone.combo_hotkey.lock() = Some(monitor);spawn(combo_hotkey_bridge_loop)// 连同 bridge 一并起

update_translation_hotkey_on_main_thread(L2314 附近):同样模式,None 时从零 ComboHotkeyMonitor::start + spawn bridge。

update_action_hotkey_binding(L933–972):同样模式,None 时从零 ComboHotkeyMonitor::start + spawn bridge。

三者均无遗漏。用户启用 → set_*_hotkeyupdate_*_binding → monitor None → 从零安装 → 立即生效,无需重启


3. 竞态检查 ✅(无新增)

supervisor 与 update_*_binding 并发安装(TOCTOU):

理论路径:supervisor 检查 combo_hotkey.lock().is_none() 后、调用 run_on_main_thread 之前,update_combo_hotkey_bindingrun_on_main_thread 先执行完装上 monitor_A;supervisor 的闭包随后在主线程执行,装上 monitor_B 覆盖 monitor_A,bridge_A 的 channel sender 被 drop,bridge_A 会在下一次 rx.recv() 收到 Err干净退出

此竞态在 PR 前同样存在(run_on_main_thread 是顺序队列,两次调用的闭包仍可交错注册),本次改动不引入新窗口,也不改变结果:最后写入者胜出,孤立 bridge 干净退出。

monitor 生命期take_combo_hotkey_on_main_thread 在主线程 drop monitor → tx 被 drop → bridge rx.recv() 返回 Err → bridge 退出,无泄漏。

exit-on-success 后的重装链:supervisor 退出 → 用户改键 → update_combo_hotkey_binding take + reinstall,全程无需 supervisor 守护,链路完整。


细节观察(非阻塞)

translation_hotkey_supervisor_loop 的 builtin/modifier 分支在退出前直接调用:

monitor.update_modifier_shortcuts(qa_trigger, translation_trigger);

try_update_translation_hotkey_bindingself.update_modifier_shortcut_bindings(),两者语义等价,无差异。


总结

改动纯控制流,稳态识别准确,从零安装路径完整,无新增竞态,有界重试路径全部保留。

@appergb
appergb merged commit 2d783ce into betaJun 16, 2026
5 checks passed
@appergb
appergb deleted the fix/470-hotkey-supervisor-exit branch June 16, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@appergb