aboutsummaryrefslogtreecommitdiff
path: root/src/app/session.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-07 15:34:26 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-07 15:35:20 +0300
commitb425260f9d86bb7e0bbea1d1e557ee75ba22443e (patch)
treed67a0896bdfa5ce027fc85982d547ed995936265 /src/app/session.rs
parentb017d212905b4de04770100ad993cb5c0b7855ca (diff)
perf: move session autosaves off main loop
Diffstat (limited to 'src/app/session.rs')
-rw-r--r--src/app/session.rs78
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());
+ }
}
}