From 4930f050c56660c245e5976979babb66aea7bfd5 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Mon, 20 Jul 2026 23:44:15 +0200 Subject: chore: Last big refactoring --- crates/daemon/src/aclient/history/mod.rs | 36 ----- crates/daemon/src/aclient/history/store.rs | 207 +++++------------------------ 2 files changed, 31 insertions(+), 212 deletions(-) (limited to 'crates/daemon/src/aclient/history') diff --git a/crates/daemon/src/aclient/history/mod.rs b/crates/daemon/src/aclient/history/mod.rs index f9afa5e9..ae7654a6 100644 --- a/crates/daemon/src/aclient/history/mod.rs +++ b/crates/daemon/src/aclient/history/mod.rs @@ -1,4 +1,3 @@ -use regex::RegexSet; use rmp::decode::DecodeStringError; use rmp::decode::ValueReadError; use rmp::{Marker, decode::Bytes}; @@ -18,28 +17,6 @@ const HISTORY_RECORD_VERSION_V0: u16 = 0; const HISTORY_RECORD_VERSION_V1: u16 = 1; const HISTORY_VERSION: &str = HISTORY_VERSION_V1; const HISTORY_TAG: &str = "history"; -const HISTORY_AUTHOR_ENV: &str = "ATUIN_HISTORY_AUTHOR"; -const HISTORY_INTENT_ENV: &str = "ATUIN_HISTORY_INTENT"; - -#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)] -pub(crate) struct HistoryStats { - /// The command that was ran after this one in the session - pub(crate) next: Option, - - /// The command that was ran before this one in the session - pub(crate) previous: Option, - - /// How many times has this command been ran? - pub(crate) total: u64, - - pub(crate) average_duration: u64, - - pub(crate) exits: Vec<(i64, i64)>, - - pub(crate) day_of_week: Vec<(String, i64)>, - - pub(crate) duration_over_time: Vec<(String, i64)>, -} trait HistoryExt: Sized { fn serialize(&self) -> Result; @@ -47,7 +24,6 @@ trait HistoryExt: Sized { fn deserialize_v0(bytes: &[u8]) -> Result; fn deserialize_v1(bytes: &[u8]) -> Result; fn deserialize(bytes: &[u8], version: &str) -> Result; - fn success(&self) -> bool; } impl HistoryExt for History { @@ -248,18 +224,6 @@ impl HistoryExt for History { _ => bail!("unknown version {version:?}"), } } - - #[expect(unused)] - fn success(&self) -> bool { - self.exit == 0 || self.duration == -1 - } -} - -#[derive(Debug, Copy, Clone)] -struct SettingsFilter<'a> { - pub history: &'a RegexSet, - pub cwd: &'a RegexSet, - pub secrets: bool, } #[cfg(test)] diff --git a/crates/daemon/src/aclient/history/store.rs b/crates/daemon/src/aclient/history/store.rs index 244725eb..952f2070 100644 --- a/crates/daemon/src/aclient/history/store.rs +++ b/crates/daemon/src/aclient/history/store.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use eyre::{Result, bail, eyre}; use rmp::decode::Bytes; use turtle::history::{History, HistoryId}; @@ -143,58 +141,6 @@ impl HistoryStore { Ok((id, idx)) } - async fn push_batch(&self, records: impl Iterator) -> Result<()> { - let mut ret = Vec::new(); - - let idx = self - .store - .last(self.host_id, HISTORY_TAG) - .await? - .map_or(0, |p| p.idx + 1); - - // Could probably _also_ do this as an iterator, but let's see how this is for now. - // optimizing for minimal sqlite transactions, this code can be optimised later - for (n, record) in records.enumerate() { - let bytes = record.serialize()?; - - let record = Record::builder() - .host(Host::new(self.host_id)) - .version(HISTORY_VERSION.to_string()) - .tag(HISTORY_TAG.to_string()) - .idx(idx + n as u64) - .data(bytes) - .build(); - - let record = record.encrypt::(&self.encryption_key); - - ret.push(record); - } - - self.store.push_batch(ret.iter()).await?; - - Ok(()) - } - - async fn delete(&self, id: HistoryId) -> Result<(RecordId, RecordIdx)> { - let record = HistoryRecord::Delete(id); - - self.push_record(record).await - } - - /// Delete a batch of history entries via the record store. - /// Returns the record IDs so the caller can run `incremental_build` when ready. - async fn delete_entries( - &self, - entries: impl IntoIterator, - ) -> Result> { - let mut record_ids = Vec::new(); - for entry in entries { - let (id, _) = self.delete(entry.id).await?; - record_ids.push(id); - } - Ok(record_ids) - } - pub(crate) async fn push(&self, history: History) -> Result<(RecordId, RecordIdx)> { // TODO(ellie): move the history store to its own file // it's tiny rn so fine as is @@ -203,60 +149,37 @@ impl HistoryStore { self.push_record(record).await } - async fn history(&self) -> Result> { - // Atm this loads all history into memory - // Not ideal as that is potentially quite a lot, although history will be small. - let records = self.store.all_tagged(HISTORY_TAG).await?; - let mut ret = Vec::with_capacity(records.len()); - - for record in records { - let hist = match record.version.as_str() { - HISTORY_VERSION_V0 | HISTORY_VERSION => { - let version = record.version.clone(); - let decrypted = record.decrypt::(&self.encryption_key)?; - - HistoryRecord::deserialize(&decrypted.data, version.as_str()) - } - version => bail!("unknown history version {version:?}"), - }?; - - ret.push(hist); - } - - Ok(ret) - } - - async fn build(&self, database: &ClientSqlite) -> Result<()> { - // I'd like to change how we rebuild and not couple this with the database, but need to - // consider the structure more deeply. This will be easy to change. - - // TODO(ellie): page or iterate this - let history = self.history().await?; - - // In theory we could flatten this here - // The current issue is that the database may have history in it already, from the old sync - // This didn't actually delete old history - // If we're sure we have a DB only maintained by the new store, we can flatten - // create/delete before we even get to sqlite - let mut creates = Vec::new(); - let mut deletes = Vec::new(); - - for i in history { - match i { - HistoryRecord::Create(h) => { - creates.push(h); - } - HistoryRecord::Delete(id) => { - deletes.push(id); - } - } - } - - database.save_bulk(&creates).await?; - database.delete_rows(&deletes).await?; - - Ok(()) - } + // async fn build(&self, database: &ClientSqlite) -> Result<()> { + // // I'd like to change how we rebuild and not couple this with the database, but need to + // // consider the structure more deeply. This will be easy to change. + // + // // TODO(ellie): page or iterate this + // let history = self.history().await?; + // + // // In theory we could flatten this here + // // The current issue is that the database may have history in it already, from the old sync + // // This didn't actually delete old history + // // If we're sure we have a DB only maintained by the new store, we can flatten + // // create/delete before we even get to sqlite + // let mut creates = Vec::new(); + // let mut deletes = Vec::new(); + // + // for i in history { + // match i { + // HistoryRecord::Create(h) => { + // creates.push(h); + // } + // HistoryRecord::Delete(id) => { + // deletes.push(id); + // } + // } + // } + // + // database.save_bulk(&creates).await?; + // database.delete_rows(&deletes).await?; + // + // Ok(()) + // } pub(crate) async fn incremental_build( &self, @@ -294,74 +217,6 @@ impl HistoryStore { Ok(()) } - - /// Get a list of history IDs that exist in the store - /// Note: This currently involves loading all history into memory. This is not going to be a - /// large amount in absolute terms, but do not all it in a hot loop. - async fn history_ids(&self) -> Result> { - let history = self.history().await?; - - let ret = history - .iter() - .map(|h| match h { - HistoryRecord::Create(h) => h.id.clone(), - HistoryRecord::Delete(id) => id.clone(), - }) - .collect::>(); - - Ok(ret) - } - - async fn init_store(&self, db: &ClientSqlite) -> Result<()> { - todo!(); - - // let pb = ProgressBar::new_spinner(); - // pb.set_style( - // ProgressStyle::with_template("{spinner:.blue} {msg}") - // .unwrap() - // .with_key("eta", |state: &ProgressState, w: &mut dyn Write| { - // write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap(); - // }) - // .progress_chars("#>-"), - // ); - // pb.enable_steady_tick(Duration::from_millis(500)); - // - // pb.set_message("Fetching history from old database"); - // - // let context = current_context().await?; - // let history = db.list(&[], &context, None, false, true).await?; - // - // pb.set_message("Fetching history already in store"); - // let store_ids = self.history_ids().await?; - // - // pb.set_message("Converting old history to new store"); - // let mut records = Vec::new(); - // - // for i in history { - // debug!("loaded {}", i.id); - // - // if store_ids.contains(&i.id) { - // debug!("skipping {} - already exists", i.id); - // continue; - // } - // - // if i.deleted_at.is_some() { - // records.push(HistoryRecord::Delete(i.id)); - // } else { - // records.push(HistoryRecord::Create(i)); - // } - // } - // - // pb.set_message("Writing to db"); - // - // if !records.is_empty() { - // self.push_batch(records.into_iter()).await?; - // } - // - // pb.finish_with_message("Import complete"); - - Ok(()) - } } #[cfg(test)] -- cgit v1.3.1