pub mod digitalocean; use anyhow::Result; use std::sync::Arc; #[derive(Clone)] pub enum StorageProvider { Local, DigitalOcean(Arc), } impl StorageProvider { pub async fn new(provider: &str, config: &crate::config::StorageConfig) -> Result { match provider { "digitalocean" | "do-spaces" => { let client = digitalocean::SpacesClient::new( config.do_spaces_endpoint.as_ref().unwrap(), config.do_spaces_bucket.as_ref().unwrap(), config.do_spaces_access_key.as_ref().unwrap(), config.do_spaces_secret_key.as_ref().unwrap(), ) .await?; Ok(StorageProvider::DigitalOcean(Arc::new(client))) } _ => Ok(StorageProvider::Local), } } pub async fn upload_blob(&self, path: &str, data: &[u8]) -> Result { match self { StorageProvider::Local => { let full_path = format!("/var/data/scratchback/blobs/{}", path); if let Some(parent) = Path::new(&full_path).parent() { std::fs::create_dir_all(parent)?; } std::fs::write(&full_path, data)?; Ok(path.to_string()) } StorageProvider::DigitalOcean(client) => { client.upload_object(path, data).await } } } pub async fn download_blob(&self, path: &str) -> Result> { match self { StorageProvider::Local => { let full_path = format!("/var/data/scratchback/blobs/{}", path); Ok(std::fs::read(&full_path)?) } StorageProvider::DigitalOcean(client) => { client.download_object(path).await } } } } use std::path::Path;