pub mod local;
use async_trait::async_trait;
use std::path::PathBuf;
pub use local::LocalStorage;
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
#[error("io: {0}")]
Io(#[from] std::io::Error),
}
/// Where in the backend a file lives. For local storage, this is the path
/// relative to STORAGE_ROOT — workers and the file server can resolve it
/// against their own root.
#[derive(Debug, Clone)]
pub struct StoredObject {
pub relative_path: String,
pub size_bytes: u64,
pub sha256_hex: String,
}
/// Where `put_derived_as` will place an artifact. Kept next to the trait so
/// readers can work out a derived path without going through storage — the
/// categorizers need the poster's path before anything has written it.
pub fn derived_relative(original_relative: &str, suffix: &str, extension: &str) -> String {
let original = std::path::Path::new(original_relative);
let stem = original
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("derived");
let parent = original.parent().unwrap_or_else(|| std::path::Path::new(""));
parent
.join(format!("{stem}.{suffix}.{extension}"))
.to_string_lossy()
.into_owned()
}
#[async_trait]
pub trait Storage: Send + Sync {
/// Persist `bytes` and return where it landed. Implementations should be
/// content-addressed so identical bytes don't get duplicated.
async fn put(&self, bytes: &[u8], extension: Option<&str>) -> Result<StoredObject, StorageError>;
/// Resolve a relative path back to an absolute path on disk. Used by
/// workers that need to read the original bytes (image processing, OCR).
fn absolute_path(&self, relative: &str) -> PathBuf;
/// Persist a derived artifact (thumbnail, etc.) at a deterministic
/// sibling path, keeping the original's extension. Returns the relative
/// path used.
async fn put_derived(
&self,
original_relative: &str,
suffix: &str,
bytes: &[u8],
) -> Result<String, StorageError>;
/// Same, but with an explicit extension. A poster frame lifted out of an
/// `.mp4` is a JPEG, and naming it `.poster.mp4` would have the file
/// server hand it back as `video/mp4`.
async fn put_derived_as(
&self,
original_relative: &str,
suffix: &str,
extension: &str,
bytes: &[u8],
) -> Result<String, StorageError>;
}
⭐
Log in to mark this repository.
2.4 KiB · text
History
07a12d4