use crate::io::FileIO;
use crate::spec::Snapshot;
const TAG_DIR: &str = "tag";
const TAG_PREFIX: &str = "tag-";
#[derive(Debug, Clone)]
pub struct TagManager {
file_io: FileIO,
table_path: String,
}
impl TagManager {
pub fn new(file_io: FileIO, table_path: String) -> Self {
Self {
file_io,
table_path,
}
}
pub fn tag_directory(&self) -> String {
format!("{}/{}", self.table_path, TAG_DIR)
}
pub fn tag_path(&self, tag_name: &str) -> String {
format!("{}/{}{}", self.tag_directory(), TAG_PREFIX, tag_name)
}
pub async fn tag_exists(&self, tag_name: &str) -> crate::Result<bool> {
let path = self.tag_path(tag_name);
let input = self.file_io.new_input(&path)?;
input.exists().await
}
pub async fn get(&self, tag_name: &str) -> crate::Result<Option<Snapshot>> {
let path = self.tag_path(tag_name);
let input = self.file_io.new_input(&path)?;
let bytes = match input.read().await {
Ok(b) => b,
Err(crate::Error::IoUnexpected { ref source, .. })
if source.kind() == opendal::ErrorKind::NotFound =>
{
return Ok(None);
}
Err(e) => return Err(e),
};
let snapshot: Snapshot =
serde_json::from_slice(&bytes).map_err(|e| crate::Error::DataInvalid {
message: format!("tag '{tag_name}' JSON invalid: {e}"),
source: Some(Box::new(e)),
})?;
Ok(Some(snapshot))
}
}