aboutsummaryrefslogtreecommitdiffstats
path: root/atuin-client/src/kv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'atuin-client/src/kv.rs')
-rw-r--r--atuin-client/src/kv.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/atuin-client/src/kv.rs b/atuin-client/src/kv.rs
new file mode 100644
index 00000000..87149275
--- /dev/null
+++ b/atuin-client/src/kv.rs
@@ -0,0 +1,103 @@
+use eyre::Result;
+use serde::{Deserialize, Serialize};
+
+use crate::record::store::Store;
+use crate::settings::Settings;
+
+const KV_VERSION: &str = "v0";
+const KV_TAG: &str = "kv";
+
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
+pub struct KvRecord {
+ pub key: String,
+ pub value: String,
+}
+
+impl KvRecord {
+ pub fn serialize(&self) -> Result<Vec<u8>> {
+ let buf = rmp_serde::to_vec(self)?;
+
+ Ok(buf)
+ }
+}
+
+pub struct KvStore;
+
+impl Default for KvStore {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl KvStore {
+ // will want to init the actual kv store when that is done
+ pub fn new() -> KvStore {
+ KvStore {}
+ }
+
+ pub async fn set(
+ &self,
+ store: &mut (impl Store + Send + Sync),
+ key: &str,
+ value: &str,
+ ) -> Result<()> {
+ let host_id = Settings::host_id().expect("failed to get host_id");
+
+ let record = KvRecord {
+ key: key.to_string(),
+ value: value.to_string(),
+ };
+
+ let bytes = record.serialize()?;
+
+ let parent = store
+ .last(host_id.as_str(), KV_TAG)
+ .await?
+ .map(|entry| entry.id);
+
+ let record = atuin_common::record::Record::builder()
+ .host(host_id)
+ .version(KV_VERSION.to_string())
+ .tag(KV_TAG.to_string())
+ .parent(parent)
+ .data(bytes)
+ .build();
+
+ store.push(&record).await?;
+
+ Ok(())
+ }
+
+ // TODO: setup an actual kv store, rebuild func, and do not pass the main store in here as
+ // well.
+ pub async fn get(&self, store: &impl Store, key: &str) -> Result<Option<KvRecord>> {
+ // TODO: don't load this from disk so much
+ let host_id = Settings::host_id().expect("failed to get host_id");
+
+ // Currently, this is O(n). When we have an actual KV store, it can be better
+ // Just a poc for now!
+
+ // iterate records to find the value we want
+ // start at the end, so we get the most recent version
+ let Some(mut record) = store.last(host_id.as_str(), KV_TAG).await? else {
+ return Ok(None);
+ };
+ let kv: KvRecord = rmp_serde::from_slice(&record.data)?;
+
+ if kv.key == key {
+ return Ok(Some(kv));
+ }
+
+ while let Some(parent) = record.parent {
+ record = store.get(parent.as_str()).await?;
+ let kv: KvRecord = rmp_serde::from_slice(&record.data)?;
+
+ if kv.key == key {
+ return Ok(Some(kv));
+ }
+ }
+
+ // if we get here, then... we didn't find the record with that key :(
+ Ok(None)
+ }
+}