diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-07 15:34:26 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-07 15:35:20 +0300 |
| commit | b425260f9d86bb7e0bbea1d1e557ee75ba22443e (patch) | |
| tree | d67a0896bdfa5ce027fc85982d547ed995936265 /src/app/session.rs | |
| parent | b017d212905b4de04770100ad993cb5c0b7855ca (diff) | |
perf: move session autosaves off main loop
Diffstat (limited to 'src/app/session.rs')
| -rw-r--r-- | src/app/session.rs | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/src/app/session.rs b/src/app/session.rs index 5e174507..60d49d52 100644 --- a/src/app/session.rs +++ b/src/app/session.rs @@ -1,7 +1,15 @@ -use std::time::Instant; +use std::time::{Duration, Instant}; use super::{App, SESSION_SAVE_DEBOUNCE}; +enum SessionSaveJob { + Clear, + Save { + snapshot: crate::persist::SessionSnapshot, + history: Option<crate::persist::SessionHistorySnapshot>, + }, +} + impl App { pub(super) fn schedule_session_save(&mut self) { if !self.no_session { @@ -16,16 +24,23 @@ impl App { } } - pub(crate) fn save_session_now(&mut self) { - if self.no_session { - self.session_save_deadline = None; - return; + fn reap_finished_session_save(&mut self) { + if self + .session_save_thread + .as_ref() + .is_some_and(std::thread::JoinHandle::is_finished) + { + if let Some(thread) = self.session_save_thread.take() { + let _ = thread.join(); + } } + } + fn capture_session_save_job(&self) -> SessionSaveJob { if self.state.workspaces.is_empty() { - crate::persist::clear(); + SessionSaveJob::Clear } else { - let snap = crate::persist::capture( + let snapshot = crate::persist::capture( &self.state.workspaces, &self.state.terminals, &self.terminal_runtimes, @@ -38,9 +53,56 @@ impl App { let history = self.persist_pane_history.then(|| { crate::persist::capture_history(&self.state.workspaces, &self.terminal_runtimes) }); - crate::persist::save(&snap, history.as_ref()); + SessionSaveJob::Save { snapshot, history } + } + } + + pub(crate) fn start_background_session_save(&mut self) { + if self.no_session { + self.session_save_deadline = None; + return; + } + + self.reap_finished_session_save(); + if self.session_save_thread.is_some() { + self.session_save_deadline = Some(Instant::now() + Duration::from_millis(250)); + return; } + let job = self.capture_session_save_job(); self.session_save_deadline = None; + match std::thread::Builder::new() + .name("herdr-session-save".into()) + .spawn(move || run_session_save_job(job)) + { + Ok(thread) => self.session_save_thread = Some(thread), + Err(err) => { + tracing::warn!(err = %err, "failed to spawn session save thread; saving inline"); + run_session_save_job(self.capture_session_save_job()); + } + } + } + + pub(crate) fn save_session_now(&mut self) { + if let Some(thread) = self.session_save_thread.take() { + let _ = thread.join(); + } + + if self.no_session { + self.session_save_deadline = None; + return; + } + + run_session_save_job(self.capture_session_save_job()); + self.session_save_deadline = None; + } +} + +fn run_session_save_job(job: SessionSaveJob) { + match job { + SessionSaveJob::Clear => crate::persist::clear(), + SessionSaveJob::Save { snapshot, history } => { + crate::persist::save(&snapshot, history.as_ref()); + } } } |
