pub mod local;
#[cfg(feature = "storage-s3")]
pub mod s3;
use std::time::Duration;
use crate::errors::app_error::AppResult;
use async_trait::async_trait;
#[async_trait]
pub trait Storage: Send + Sync + std::fmt::Debug {
async fn put(&self, key: &str, data: &[u8], content_type: &str) -> AppResult<()>;
async fn get(&self, key: &str) -> AppResult<Vec<u8>>;
async fn delete(&self, key: &str) -> AppResult<()>;
async fn url(&self, key: &str) -> AppResult<String>;
async fn presigned_upload(&self, _key: &str, _ttl: Duration) -> AppResult<String> {
Ok(String::new())
}
}
pub fn create_storage(
config: &crate::config::app::AppConfig,
) -> AppResult<std::sync::Arc<dyn Storage>> {
match config.storage_driver.as_str() {
"local" => {
tracing::info!(upload_dir = %config.upload_dir, "Storage driver: local");
Ok(std::sync::Arc::new(local::LocalStorage::new(
&config.upload_dir,
&config.base_url,
)?))
}
#[cfg(feature = "storage-s3")]
"s3" => {
tracing::info!(bucket = %config.s3_bucket, "Storage driver: s3");
Ok(std::sync::Arc::new(s3::S3Storage::from_config(config)?))
}
#[cfg(not(feature = "storage-s3"))]
"s3" => {
tracing::error!("storage-s3 feature not enabled");
Err(crate::errors::app_error::AppError::BadRequest(
"storage-s3 feature not enabled".into(),
))
}
other => Err(crate::errors::app_error::AppError::BadRequest(format!(
"unknown STORAGE_DRIVER: {other}"
))),
}
}