`detect_meeting_processes` is called every 15 s when meeting-auto-capture is enabled. The previous `list_running_process_names` allocated a fresh `sysinfo::System` per call and walked /proc cold; on a busy host (~300 processes) that's ~50–100 ms of work, every poll, forever. Add `kon_core::process_watch::ProcessLister`, a thin wrapper around a long-lived `System` whose process table is refreshed in place. The Tauri host holds one behind a `Mutex<ProcessLister>` in a new `MeetingState` managed at app setup. The free `list_running_process_names` is kept as a convenience that constructs a fresh `ProcessLister` per call — its only remaining caller is the existing smoke test. - ProcessLister + Default in crates/core/src/process_watch.rs. - MeetingState in src-tauri/src/commands/meeting.rs; the command takes it via `tauri::State` and locks for the duration of the snapshot. - src-tauri/src/lib.rs registers MeetingState alongside the other managed states. https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
51 lines
1.4 KiB
Rust
51 lines
1.4 KiB
Rust
//! Meeting auto-capture — the single-signal variant.
|
|
//!
|
|
//! The frontend polls `detect_meeting_processes` on an interval with the
|
|
//! user's app patterns. On a positive hit it surfaces a non-modal toast
|
|
//! that reminds the user to start recording with their hotkey. We do not
|
|
//! start recording from this signal — the user decides.
|
|
|
|
use std::sync::Mutex;
|
|
|
|
use kon_core::process_watch::{self, ProcessLister};
|
|
|
|
/// Tauri-managed state for the meeting poller. Holds a long-lived
|
|
/// `ProcessLister` so each poll refreshes the existing `sysinfo::System`
|
|
/// in place instead of allocating a fresh one — the previous implementation
|
|
/// rebuilt the process table from scratch every 15 s.
|
|
pub struct MeetingState {
|
|
lister: Mutex<ProcessLister>,
|
|
}
|
|
|
|
impl MeetingState {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
lister: Mutex::new(ProcessLister::new()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MeetingState {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn detect_meeting_processes(
|
|
state: tauri::State<'_, MeetingState>,
|
|
patterns: Vec<String>,
|
|
) -> Result<Vec<String>, String> {
|
|
if patterns.is_empty() {
|
|
return Ok(Vec::new());
|
|
}
|
|
let processes = {
|
|
let mut lister = state
|
|
.lister
|
|
.lock()
|
|
.map_err(|e| format!("MeetingState lister poisoned: {e}"))?;
|
|
lister.snapshot()
|
|
};
|
|
Ok(process_watch::match_meeting_patterns(&processes, &patterns))
|
|
}
|