mirror of
https://github.com/atuinsh/atuin.git
synced 2024-12-26 08:59:21 +01:00
Allow reading tail across hosts
This commit is contained in:
parent
1a6e012295
commit
7b0c72e7e0
@ -101,7 +101,10 @@ impl KvStore {
|
|||||||
|
|
||||||
let bytes = record.serialize()?;
|
let bytes = record.serialize()?;
|
||||||
|
|
||||||
let parent = store.tail(host_id, KV_TAG).await?.map(|entry| entry.id);
|
let parent = store
|
||||||
|
.tail(Some(host_id), KV_TAG)
|
||||||
|
.await?
|
||||||
|
.map(|entry| entry.id);
|
||||||
|
|
||||||
let record = atuin_common::record::Record::builder()
|
let record = atuin_common::record::Record::builder()
|
||||||
.host(host_id)
|
.host(host_id)
|
||||||
@ -127,15 +130,12 @@ impl KvStore {
|
|||||||
namespace: &str,
|
namespace: &str,
|
||||||
key: &str,
|
key: &str,
|
||||||
) -> Result<Option<KvRecord>> {
|
) -> 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
|
// Currently, this is O(n). When we have an actual KV store, it can be better
|
||||||
// Just a poc for now!
|
// Just a poc for now!
|
||||||
|
|
||||||
// iterate records to find the value we want
|
// iterate records to find the value we want
|
||||||
// start at the end, so we get the most recent version
|
// start at the end, so we get the most recent version
|
||||||
let Some(mut record) = store.tail(host_id, KV_TAG).await? else {
|
let Some(mut record) = store.tail(None, KV_TAG).await? else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,15 +171,28 @@ impl Store for SqliteStore {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn tail(&self, host: Uuid, tag: &str) -> Result<Option<Record<EncryptedData>>> {
|
// Get the tail for a given tag
|
||||||
let res = sqlx::query(
|
// If a host is provided, get the tail for a tag for that host
|
||||||
|
// Otherwise, the latest record across hosts
|
||||||
|
async fn tail(&self, host: Option<Uuid>, tag: &str) -> Result<Option<Record<EncryptedData>>> {
|
||||||
|
let res = if let Some(host) = host {
|
||||||
|
sqlx::query(
|
||||||
"select * from records rp where tag=?1 and host=?2 and (select count(1) from records where parent=rp.id) = 0;",
|
"select * from records rp where tag=?1 and host=?2 and (select count(1) from records where parent=rp.id) = 0;",
|
||||||
)
|
)
|
||||||
.bind(tag)
|
.bind(tag)
|
||||||
.bind(host.as_simple().to_string())
|
.bind(host.as_simple().to_string())
|
||||||
.map(Self::query_row)
|
.map(Self::query_row)
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
.await?;
|
.await?
|
||||||
|
} else {
|
||||||
|
sqlx::query(
|
||||||
|
"select * from records rp where tag=?1 and (select count(1) from records where parent=rp.id) = 0;",
|
||||||
|
)
|
||||||
|
.bind(tag)
|
||||||
|
.map(Self::query_row)
|
||||||
|
.fetch_optional(&self.pool)
|
||||||
|
.await?
|
||||||
|
};
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ pub trait Store {
|
|||||||
/// Get the first record for a given host and tag
|
/// Get the first record for a given host and tag
|
||||||
async fn head(&self, host: Uuid, tag: &str) -> Result<Option<Record<EncryptedData>>>;
|
async fn head(&self, host: Uuid, tag: &str) -> Result<Option<Record<EncryptedData>>>;
|
||||||
/// Get the last record for a given host and tag
|
/// Get the last record for a given host and tag
|
||||||
async fn tail(&self, host: Uuid, tag: &str) -> Result<Option<Record<EncryptedData>>>;
|
async fn tail(&self, host: Option<Uuid>, tag: &str) -> Result<Option<Record<EncryptedData>>>;
|
||||||
|
|
||||||
async fn tail_records(&self) -> Result<Vec<(Uuid, String, Uuid)>>;
|
async fn tail_records(&self) -> Result<Vec<(Uuid, String, Uuid)>>;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ pub async fn operations(diff: Diff, store: &impl Store) -> Result<Vec<Operation>
|
|||||||
// if local has the ID, then we should find the actual tail of this
|
// if local has the ID, then we should find the actual tail of this
|
||||||
// store, so we know what we need to update the remote to.
|
// store, so we know what we need to update the remote to.
|
||||||
let tail = store
|
let tail = store
|
||||||
.tail(host, tag.as_str())
|
.tail(Some(host), tag.as_str())
|
||||||
.await?
|
.await?
|
||||||
.expect("failed to fetch last record, expected tag/host to exist");
|
.expect("failed to fetch last record, expected tag/host to exist");
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ async fn sync_download(
|
|||||||
let remote_tail = remote_index
|
let remote_tail = remote_index
|
||||||
.get(op.0, op.1.clone())
|
.get(op.0, op.1.clone())
|
||||||
.expect("remote index does not contain expected tail during download");
|
.expect("remote index does not contain expected tail during download");
|
||||||
let local_tail = store.tail(op.0, op.1.as_str()).await?;
|
let local_tail = store.tail(Some(op.0), op.1.as_str()).await?;
|
||||||
//
|
//
|
||||||
// We expect that the operations diff will represent the desired state
|
// We expect that the operations diff will represent the desired state
|
||||||
// In this case, that contains the remote tail.
|
// In this case, that contains the remote tail.
|
||||||
|
Loading…
Reference in New Issue
Block a user