//! Storage backend trait definition use async_trait::async_trait; use bytes::Bytes; use lightningstor_types::ObjectId; use std::io; use thiserror::Error; /// Storage backend error #[derive(Debug, Error)] pub enum StorageError { #[error("IO error: {0}")] Io(#[from] io::Error), #[error("Object not found: {0}")] NotFound(ObjectId), #[error("Storage backend error: {0}")] Backend(String), #[error("Invalid object ID: {0}")] InvalidObjectId(String), } /// Storage result type pub type StorageResult = std::result::Result; impl From for lightningstor_types::Error { fn from(err: StorageError) -> Self { match err { StorageError::Io(e) => lightningstor_types::Error::StorageError(e.to_string()), StorageError::NotFound(id) => { lightningstor_types::Error::ObjectNotFound { bucket: String::new(), key: id.to_string(), } } StorageError::Backend(msg) => lightningstor_types::Error::StorageError(msg), StorageError::InvalidObjectId(msg) => { lightningstor_types::Error::InvalidArgument(msg) } } } } /// Storage backend trait for object data storage /// /// This trait abstracts the storage of object data, allowing different /// implementations (local filesystem, distributed storage, cloud storage). #[async_trait] pub trait StorageBackend: Send + Sync { /// Write object data /// /// # Arguments /// * `object_id` - Internal object identifier /// * `data` - Object data bytes /// /// # Returns /// * `Ok(())` if write succeeded /// * `Err(StorageError)` if write failed async fn put_object(&self, object_id: &ObjectId, data: Bytes) -> StorageResult<()>; /// Read object data /// /// # Arguments /// * `object_id` - Internal object identifier /// /// # Returns /// * `Ok(Bytes)` if object exists /// * `Err(StorageError::NotFound)` if object does not exist /// * `Err(StorageError)` for other errors async fn get_object(&self, object_id: &ObjectId) -> StorageResult; /// Delete object data /// /// # Arguments /// * `object_id` - Internal object identifier /// /// # Returns /// * `Ok(())` if delete succeeded (or object didn't exist) /// * `Err(StorageError)` for other errors async fn delete_object(&self, object_id: &ObjectId) -> StorageResult<()>; /// Check if object exists /// /// # Arguments /// * `object_id` - Internal object identifier /// /// # Returns /// * `Ok(true)` if object exists /// * `Ok(false)` if object does not exist /// * `Err(StorageError)` for other errors async fn object_exists(&self, object_id: &ObjectId) -> StorageResult; /// Get object size in bytes /// /// # Arguments /// * `object_id` - Internal object identifier /// /// # Returns /// * `Ok(u64)` if object exists /// * `Err(StorageError::NotFound)` if object does not exist /// * `Err(StorageError)` for other errors async fn object_size(&self, object_id: &ObjectId) -> StorageResult; /// Write part data (for multipart uploads) /// /// # Arguments /// * `upload_id` - Multipart upload ID /// * `part_number` - Part number (1-based) /// * `data` - Part data bytes /// /// # Returns /// * `Ok(())` if write succeeded /// * `Err(StorageError)` if write failed async fn put_part( &self, upload_id: &str, part_number: u32, data: Bytes, ) -> StorageResult<()>; /// Read part data (for multipart uploads) /// /// # Arguments /// * `upload_id` - Multipart upload ID /// * `part_number` - Part number (1-based) /// /// # Returns /// * `Ok(Bytes)` if part exists /// * `Err(StorageError::NotFound)` if part does not exist /// * `Err(StorageError)` for other errors async fn get_part( &self, upload_id: &str, part_number: u32, ) -> StorageResult; /// Delete part data (for multipart uploads) /// /// # Arguments /// * `upload_id` - Multipart upload ID /// * `part_number` - Part number (1-based) /// /// # Returns /// * `Ok(())` if delete succeeded /// * `Err(StorageError)` for other errors async fn delete_part(&self, upload_id: &str, part_number: u32) -> StorageResult<()>; /// Delete all parts for a multipart upload /// /// # Arguments /// * `upload_id` - Multipart upload ID /// /// # Returns /// * `Ok(())` if delete succeeded /// * `Err(StorageError)` for other errors async fn delete_upload_parts(&self, upload_id: &str) -> StorageResult<()>; }