aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-client/src
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2024-05-08 12:09:04 +0100
committerGitHub <noreply@github.com>2024-05-08 12:09:04 +0100
commitbce0faa1c2dc221b0ff77d2cd647bfb2a48ffa7e (patch)
tree4d66bd95b151d3bab4cabf8799805c739f608bc4 /crates/atuin-client/src
parentfix(config): add quotes for strategy value in comment (#1993) (diff)
downloadatuin-bce0faa1c2dc221b0ff77d2cd647bfb2a48ffa7e.zip
feat: add background daemon (#2006)
* init daemon crate * wip * minimal functioning daemon, needs cleanup for sure * better errors * add signal cleanup * logging * things * add sync worker * move daemon crate * 30s -> 5mins * make clippy happy * fix stuff maybe? * fmt * trim packages * rate limit fix * more protoc huh * this makes no sense, why linux why * can it install literally just curl * windows in ci is slow, and all the newer things will not work there. disable the daemon feature and it will build * add daemon feature * maybe this * ok wut where is protoc * try setting protoc * hm * try copying protoc * remove optional * add cross config * idk nix * does nix want this? * some random pkg I found does this * uh oh * hack, be gone! * update contributing
Diffstat (limited to '')
-rw-r--r--crates/atuin-client/src/database.rs1
-rw-r--r--crates/atuin-client/src/history.rs42
-rw-r--r--crates/atuin-client/src/history/builder.rs33
-rw-r--r--crates/atuin-client/src/settings.rs31
4 files changed, 107 insertions, 0 deletions
diff --git a/crates/atuin-client/src/database.rs b/crates/atuin-client/src/database.rs
index 7faa3802..33156077 100644
--- a/crates/atuin-client/src/database.rs
+++ b/crates/atuin-client/src/database.rs
@@ -120,6 +120,7 @@ pub trait Database: Send + Sync + 'static {
// Intended for use on a developer machine and not a sync server.
// TODO: implement IntoIterator
+#[derive(Debug)]
pub struct Sqlite {
pub pool: SqlitePool,
}
diff --git a/crates/atuin-client/src/history.rs b/crates/atuin-client/src/history.rs
index 1b590e88..0503b43d 100644
--- a/crates/atuin-client/src/history.rs
+++ b/crates/atuin-client/src/history.rs
@@ -303,6 +303,48 @@ impl History {
builder::HistoryCaptured::builder()
}
+ /// Builder for a history entry that is captured via hook, and sent to the daemon.
+ ///
+ /// This builder is used only at the `start` step of the hook,
+ /// so it doesn't have any fields which are known only after
+ /// the command is finished, such as `exit` or `duration`.
+ ///
+ /// It does, however, include information that can usually be inferred.
+ ///
+ /// This is because the daemon we are sending a request to lacks the context of the command
+ ///
+ /// ## Examples
+ /// ```rust
+ /// use atuin_client::history::History;
+ ///
+ /// let history: History = History::daemon()
+ /// .timestamp(time::OffsetDateTime::now_utc())
+ /// .command("ls -la")
+ /// .cwd("/home/user")
+ /// .session("018deb6e8287781f9973ef40e0fde76b")
+ /// .hostname("computer:ellie")
+ /// .build()
+ /// .into();
+ /// ```
+ ///
+ /// Command without any required info cannot be captured, which is forced at compile time:
+ ///
+ /// ```compile_fail
+ /// use atuin_client::history::History;
+ ///
+ /// // this will not compile because `hostname` is missing
+ /// let history: History = History::daemon()
+ /// .timestamp(time::OffsetDateTime::now_utc())
+ /// .command("ls -la")
+ /// .cwd("/home/user")
+ /// .session("018deb6e8287781f9973ef40e0fde76b")
+ /// .build()
+ /// .into();
+ /// ```
+ pub fn daemon() -> builder::HistoryDaemonCaptureBuilder {
+ builder::HistoryDaemonCapture::builder()
+ }
+
/// Builder for a history entry that is imported from the database.
///
/// All fields are required, as they are all present in the database.
diff --git a/crates/atuin-client/src/history/builder.rs b/crates/atuin-client/src/history/builder.rs
index 4e69cf66..2b28339f 100644
--- a/crates/atuin-client/src/history/builder.rs
+++ b/crates/atuin-client/src/history/builder.rs
@@ -97,3 +97,36 @@ impl From<HistoryFromDb> for History {
}
}
}
+
+/// Builder for a history entry that is captured via hook and sent to the daemon
+///
+/// This builder is similar to Capture, but we just require more information up front.
+/// For the old setup, we could just rely on History::new to read some of the missing
+/// data. This is no longer the case.
+#[derive(Debug, Clone, TypedBuilder)]
+pub struct HistoryDaemonCapture {
+ timestamp: time::OffsetDateTime,
+ #[builder(setter(into))]
+ command: String,
+ #[builder(setter(into))]
+ cwd: String,
+ #[builder(setter(into))]
+ session: String,
+ #[builder(setter(into))]
+ hostname: String,
+}
+
+impl From<HistoryDaemonCapture> for History {
+ fn from(captured: HistoryDaemonCapture) -> Self {
+ History::new(
+ captured.timestamp,
+ captured.command,
+ captured.cwd,
+ -1,
+ -1,
+ Some(captured.session),
+ Some(captured.hostname),
+ None,
+ )
+ }
+}
diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs
index 675fb307..ad7f95fc 100644
--- a/crates/atuin-client/src/settings.rs
+++ b/crates/atuin-client/src/settings.rs
@@ -342,6 +342,19 @@ pub struct Preview {
pub strategy: PreviewStrategy,
}
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct Daemon {
+ /// Use the daemon to sync
+ /// If enabled, requires a running daemon with `atuin daemon`
+ pub enabled: bool,
+
+ /// The daemon will handle sync on an interval. How often to sync, in seconds.
+ pub sync_frequency: u64,
+
+ /// The path to the unix socket used by the daemon
+ pub socket_path: String,
+}
+
impl Default for Preview {
fn default() -> Self {
Self {
@@ -350,6 +363,16 @@ impl Default for Preview {
}
}
+impl Default for Daemon {
+ fn default() -> Self {
+ Self {
+ enabled: false,
+ sync_frequency: 300,
+ socket_path: "".to_string(),
+ }
+ }
+}
+
// The preview height strategy also takes max_preview_height into account.
#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)]
pub enum PreviewStrategy {
@@ -428,6 +451,9 @@ pub struct Settings {
#[serde(default)]
pub dotfiles: dotfiles::Settings,
+ #[serde(default)]
+ pub daemon: Daemon,
+
// This is automatically loaded when settings is created. Do not set in
// config! Keep secrets and settings apart.
#[serde(skip)]
@@ -622,6 +648,7 @@ impl Settings {
let data_dir = atuin_common::utils::data_dir();
let db_path = data_dir.join("history.db");
let record_store_path = data_dir.join("records.db");
+ let socket_path = data_dir.join("atuin.sock");
let key_path = data_dir.join("key");
let session_path = data_dir.join("session");
@@ -643,6 +670,7 @@ impl Settings {
.set_default("style", "auto")?
.set_default("inline_height", 0)?
.set_default("show_preview", true)?
+ .set_default("preview.strategy", "auto")?
.set_default("max_preview_height", 4)?
.set_default("show_help", true)?
.set_default("show_tabs", true)?
@@ -675,6 +703,9 @@ impl Settings {
.set_default("keymap_cursor", HashMap::<String, String>::new())?
.set_default("smart_sort", false)?
.set_default("store_failed", true)?
+ .set_default("daemon.sync_frequency", 300)?
+ .set_default("daemon.enabled", false)?
+ .set_default("daemon.socket_path", socket_path.to_str())?
.set_default(
"prefers_reduced_motion",
std::env::var("NO_MOTION")