MeiliSearch/file-store/src/lib.rs

98 lines
2.5 KiB
Rust
Raw Normal View History

use std::fs::File as StdFile;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use tempfile::NamedTempFile;
use uuid::Uuid;
const UPDATE_FILES_PATH: &str = "updates/updates_files";
#[derive(Debug, thiserror::Error)]
2022-09-13 15:54:35 +02:00
pub enum Error {
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error(transparent)]
PersistError(#[from] tempfile::PersistError),
}
2022-09-13 15:54:35 +02:00
pub type Result<T> = std::result::Result<T, Error>;
impl Deref for File {
type Target = NamedTempFile;
fn deref(&self) -> &Self::Target {
&self.file
}
}
impl DerefMut for File {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.file
}
}
2022-09-13 15:54:35 +02:00
// #[cfg_attr(test, faux::create)]
#[derive(Clone, Debug)]
pub struct FileStore {
2022-09-13 15:54:35 +02:00
path: PathBuf,
}
2022-09-13 15:54:35 +02:00
// #[cfg_attr(test, faux::methods)]
impl FileStore {
pub fn new(path: impl AsRef<Path>) -> Result<FileStore> {
2022-09-13 15:54:35 +02:00
let path = path.as_ref().join(UPDATE_FILES_PATH);
std::fs::create_dir_all(&path)?;
Ok(FileStore { path })
}
2022-09-13 15:54:35 +02:00
/// Creates a new temporary update file.
/// A call to `persist` is needed to persist the file in the database.
pub fn new_update(&self) -> Result<(Uuid, File)> {
2022-09-13 15:54:35 +02:00
let file = NamedTempFile::new_in(&self.path)?;
let uuid = Uuid::new_v4();
let path = self.path.join(uuid.to_string());
let update_file = File { file, path };
2022-09-13 15:54:35 +02:00
Ok((uuid, update_file))
}
2022-09-13 15:54:35 +02:00
/// Returns the file corresponding to the requested uuid.
pub fn get_update(&self, uuid: Uuid) -> Result<StdFile> {
2022-09-13 15:54:35 +02:00
let path = self.path.join(uuid.to_string());
let file = StdFile::open(path)?;
2022-09-13 15:54:35 +02:00
Ok(file)
}
2022-09-13 15:54:35 +02:00
/// Copies the content of the update file pointed to by `uuid` to the `dst` directory.
pub fn snapshot(&self, uuid: Uuid, dst: impl AsRef<Path>) -> Result<()> {
let src = self.path.join(uuid.to_string());
let mut dst = dst.as_ref().join(UPDATE_FILES_PATH);
std::fs::create_dir_all(&dst)?;
dst.push(uuid.to_string());
std::fs::copy(src, dst)?;
Ok(())
}
2022-09-13 15:54:35 +02:00
pub fn get_size(&self, uuid: Uuid) -> Result<u64> {
Ok(self.get_update(uuid)?.metadata()?.len())
}
2022-09-13 15:54:35 +02:00
pub fn delete(&self, uuid: Uuid) -> Result<()> {
let path = self.path.join(uuid.to_string());
std::fs::remove_file(path)?;
Ok(())
}
2022-09-13 15:54:35 +02:00
}
pub struct File {
2022-09-13 15:54:35 +02:00
path: PathBuf,
file: NamedTempFile,
}
impl File {
2022-09-13 15:54:35 +02:00
pub fn persist(self) -> Result<()> {
self.file.persist(&self.path)?;
Ok(())
}
}