Skip to content

Commit

Permalink
feat(index): Add support for raw index metadata and expose index func…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
zkat committed Feb 19, 2023
1 parent 70b3d5e commit 9991f56
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
31 changes: 27 additions & 4 deletions src/index.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Raw access to the cache index. Use with caution!
use std::collections::HashSet;
use std::fs::{self, OpenOptions};
use std::hash::{Hash, Hasher};
Expand Down Expand Up @@ -34,6 +36,8 @@ pub struct Metadata {
pub size: usize,
/// Arbitrary JSON associated with this entry.
pub metadata: Value,
/// Raw metadata in binary form. Can be different from JSON metadata.
pub raw_metadata: Option<Vec<u8>>,
}

#[derive(Deserialize, Serialize, Debug)]
Expand All @@ -43,6 +47,7 @@ struct SerializableMetadata {
time: u128,
size: usize,
metadata: Value,
raw_metadata: Option<Vec<u8>>,
}

impl PartialEq for SerializableMetadata {
Expand All @@ -59,6 +64,7 @@ impl Hash for SerializableMetadata {
}
}

/// Raw insertion into the cache index.
pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result<Integrity> {
let bucket = bucket_path(cache, key);
fs::create_dir_all(bucket.parent().unwrap()).with_context(|| {
Expand All @@ -73,6 +79,7 @@ pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result<Integrity> {
time: opts.time.unwrap_or_else(now),
size: opts.size.unwrap_or(0),
metadata: opts.metadata.unwrap_or(serde_json::Value::Null),
raw_metadata: opts.raw_metadata,
})
.with_context(|| format!("Failed to serialize entry with key `{key}`"))?;

Expand All @@ -93,6 +100,7 @@ pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result<Integrity> {
.unwrap())
}

/// Asynchronous raw insertion into the cache index.
pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) -> Result<Integrity> {
let bucket = bucket_path(cache, key);
crate::async_lib::create_dir_all(bucket.parent().unwrap())
Expand All @@ -109,6 +117,7 @@ pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) ->
time: opts.time.unwrap_or_else(now),
size: opts.size.unwrap_or(0),
metadata: opts.metadata.unwrap_or(serde_json::Value::Null),
raw_metadata: opts.raw_metadata,
})
.with_context(|| format!("Failed to serialize entry with key `{key}`"))?;

Expand All @@ -132,6 +141,7 @@ pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) ->
.unwrap())
}

/// Raw index Metadata access.
pub fn find(cache: &Path, key: &str) -> Result<Option<Metadata>> {
let bucket = bucket_path(cache, key);
Ok(bucket_entries(&bucket)
Expand All @@ -150,6 +160,7 @@ pub fn find(cache: &Path, key: &str) -> Result<Option<Metadata>> {
size: entry.size,
time: entry.time,
metadata: entry.metadata,
raw_metadata: entry.raw_metadata,
})
} else {
None
Expand All @@ -160,6 +171,7 @@ pub fn find(cache: &Path, key: &str) -> Result<Option<Metadata>> {
}))
}

/// Asynchronous raw index Metadata access.
pub async fn find_async(cache: &Path, key: &str) -> Result<Option<Metadata>> {
let bucket = bucket_path(cache, key);
Ok(bucket_entries_async(&bucket)
Expand All @@ -179,6 +191,7 @@ pub async fn find_async(cache: &Path, key: &str) -> Result<Option<Metadata>> {
size: entry.size,
time: entry.time,
metadata: entry.metadata,
raw_metadata: entry.raw_metadata,
})
} else {
None
Expand All @@ -189,6 +202,7 @@ pub async fn find_async(cache: &Path, key: &str) -> Result<Option<Metadata>> {
}))
}

/// Deletes an index entry, without deleting the actual cache data entry.
pub fn delete(cache: &Path, key: &str) -> Result<()> {
insert(
cache,
Expand All @@ -199,11 +213,14 @@ pub fn delete(cache: &Path, key: &str) -> Result<()> {
sri: None,
time: None,
metadata: None,
raw_metadata: None,
},
)
.map(|_| ())
}

/// Asynchronously deletes an index entry, without deleting the actual cache
/// data entry.
pub async fn delete_async(cache: &Path, key: &str) -> Result<()> {
insert(
cache,
Expand All @@ -214,11 +231,13 @@ pub async fn delete_async(cache: &Path, key: &str) -> Result<()> {
sri: None,
time: None,
metadata: None,
raw_metadata: None,
},
)
.map(|_| ())
}

/// Lists raw index Metadata entries.
pub fn ls(cache: &Path) -> impl Iterator<Item = Result<Metadata>> {
let cache_path = cache.join(format!("index-v{INDEX_VERSION}"));
let cloned = cache_path.clone();
Expand Down Expand Up @@ -258,6 +277,7 @@ pub fn ls(cache: &Path) -> impl Iterator<Item = Result<Metadata>> {
time: se.time,
size: se.size,
metadata: se.metadata,
raw_metadata: se.raw_metadata,
})
} else {
None
Expand Down Expand Up @@ -363,7 +383,7 @@ mod tests {
#[cfg(feature = "tokio")]
use tokio::test as async_test;

const MOCK_ENTRY: &str = "\n251d18a2b33264ea8655695fd23c88bd874cdea2c3dc9d8f9b7596717ad30fec\t{\"key\":\"hello\",\"integrity\":\"sha1-deadbeef\",\"time\":1234567,\"size\":0,\"metadata\":null}";
const MOCK_ENTRY: &str = "\n9cbbfe2553e7c7e1773f53f0f643fdd72008faa38da53ebcb055e5e20321ae47\t{\"key\":\"hello\",\"integrity\":\"sha1-deadbeef\",\"time\":1234567,\"size\":0,\"metadata\":null,\"raw_metadata\":null}";

fn ls_entries(dir: &Path) -> Vec<String> {
let mut entries = ls(dir)
Expand Down Expand Up @@ -417,7 +437,8 @@ mod tests {
integrity: sri,
time,
size: 0,
metadata: json!(null)
metadata: json!(null),
raw_metadata: None,
}
);
}
Expand Down Expand Up @@ -471,7 +492,8 @@ mod tests {
integrity: sri,
time,
size: 0,
metadata: json!(null)
metadata: json!(null),
raw_metadata: None,
}
);
}
Expand All @@ -496,7 +518,8 @@ mod tests {
integrity: sri,
time,
size: 0,
metadata: json!(null)
metadata: json!(null),
raw_metadata: None,
}
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
//! Ok(())
//! }
//! ```
#![warn(missing_docs, rustdoc::missing_doc_code_examples)]
#![warn(missing_docs)]

#[cfg(not(any(feature = "async-std", feature = "tokio-runtime")))]
compile_error!("Either feature \"async-std\" or \"tokio-runtime\" must be enabled for this crate.");
Expand All @@ -136,7 +136,7 @@ mod async_lib;

mod content;
mod errors;
mod index;
pub mod index;

mod get;
mod ls;
Expand Down
7 changes: 7 additions & 0 deletions src/put.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ pub struct WriteOpts {
pub(crate) size: Option<usize>,
pub(crate) time: Option<u128>,
pub(crate) metadata: Option<Value>,
pub(crate) raw_metadata: Option<Vec<u8>>,
}

impl WriteOpts {
Expand Down Expand Up @@ -354,6 +355,12 @@ impl WriteOpts {
self
}

/// Sets arbitrary additional binary metadata to associate with the index entry.
pub fn raw_metadata(mut self, metadata: Vec<u8>) -> Self {
self.raw_metadata = Some(metadata);
self
}

/// Sets the specific time in unix milliseconds to associate with this
/// entry. This is usually automatically set to the write time, but can be
/// useful to change for tests and such.
Expand Down

0 comments on commit 9991f56

Please sign in to comment.