/* * * This abstraction goal is to leverage all the semantic of Garage K2V+S3, * to be as tailored as possible to it ; it aims to be a zero-cost abstraction * compared to when we where directly using the K2V+S3 client. * * My idea: we can encapsulate the causality token * into the object system so it is not exposed. */ pub mod in_memory; pub mod garage; use std::hash::{Hash, Hasher}; use std::collections::HashMap; use futures::future::BoxFuture; use async_trait::async_trait; #[derive(Debug, Clone)] pub enum Alternative { Tombstone, Value(Vec), } type ConcurrentValues = Vec; #[derive(Debug)] pub enum StorageError { NotFound, Internal, } #[derive(Debug, Clone)] pub struct RowUid { shard: String, sort: String, } #[derive(Debug, Clone)] pub struct RowRef { uid: RowUid, causality: Option, } #[derive(Debug, Clone)] pub struct RowVal { row_ref: RowRef, value: ConcurrentValues, } #[derive(Debug, Clone)] pub struct BlobRef(String); #[derive(Debug, Clone)] pub struct BlobVal { blob_ref: BlobRef, meta: HashMap, value: Vec, } pub enum Selector<'a> { Range { shard: &'a str, sort_begin: &'a str, sort_end: &'a str }, List (Vec), // list of (shard_key, sort_key) Prefix { shard: &'a str, sort_prefix: &'a str }, Single(RowRef), } #[async_trait] pub trait IStore { async fn row_fetch<'a>(&self, select: &Selector<'a>) -> Result, StorageError>; async fn row_rm<'a>(&self, select: &Selector<'a>) -> Result<(), StorageError>; async fn row_insert(&self, values: Vec) -> Result<(), StorageError>; async fn row_poll(&self, value: RowRef) -> Result; async fn blob_fetch(&self, blob_ref: &BlobRef) -> Result; async fn blob_copy(&self, src: &BlobRef, dst: &BlobRef) -> Result; async fn blob_list(&self, prefix: &str) -> Result, StorageError>; async fn blob_rm(&self, blob_ref: &BlobRef) -> Result<(), StorageError>; } pub trait IBuilder { fn build(&self) -> Box; } /* #[derive(Clone, Debug, PartialEq)] pub enum OrphanRowRef { Garage(garage::GrgOrphanRowRef), Memory(in_memory::MemOrphanRowRef), } impl std::fmt::Display for StorageError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("Storage Error: ")?; match self { Self::NotFound => f.write_str("Item not found"), Self::Internal => f.write_str("An internal error occured"), Self::IncompatibleOrphan => f.write_str("Incompatible orphan"), } } } impl std::error::Error for StorageError {} // Utils pub type AsyncResult<'a, T> = BoxFuture<'a, Result>; // ----- Builders pub trait IBuilders { fn box_clone(&self) -> Builders; fn row_store(&self) -> Result; fn blob_store(&self) -> Result; fn url(&self) -> &str; } pub type Builders = Box; impl Clone for Builders { fn clone(&self) -> Self { self.box_clone() } } impl std::fmt::Debug for Builders { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("aerogramme::storage::Builder") } } impl PartialEq for Builders { fn eq(&self, other: &Self) -> bool { self.url() == other.url() } } impl Eq for Builders {} impl Hash for Builders { fn hash(&self, state: &mut H) { self.url().hash(state); } } // ------ Row pub trait IRowStore { fn row(&self, partition: &str, sort: &str) -> RowRef; fn select(&self, selector: Selector) -> AsyncResult>; fn rm(&self, selector: Selector) -> AsyncResult<()>; fn from_orphan(&self, orphan: OrphanRowRef) -> Result; } pub type RowStore = Box; pub trait IRowRef: std::fmt::Debug { fn to_orphan(&self) -> OrphanRowRef; fn key(&self) -> (&str, &str); fn set_value(&self, content: &[u8]) -> RowValue; fn fetch(&self) -> AsyncResult; fn rm(&self) -> AsyncResult<()>; fn poll(&self) -> AsyncResult; } pub type RowRef<'a> = Box; pub trait IRowValue: std::fmt::Debug { fn to_ref(&self) -> RowRef; fn content(&self) -> ConcurrentValues; fn push(&self) -> AsyncResult<()>; } pub type RowValue = Box; // ------- Blob pub trait IBlobStore { fn blob(&self, key: &str) -> BlobRef; fn list(&self, prefix: &str) -> AsyncResult>; } pub type BlobStore = Box; pub trait IBlobRef { fn set_value(&self, content: Vec) -> BlobValue; fn key(&self) -> &str; fn fetch(&self) -> AsyncResult; fn copy(&self, dst: &BlobRef) -> AsyncResult<()>; fn rm(&self) -> AsyncResult<()>; } pub type BlobRef = Box; pub trait IBlobValue { fn to_ref(&self) -> BlobRef; fn get_meta(&self, key: &str) -> Option<&[u8]>; fn set_meta(&mut self, key: &str, val: &str); fn content(&self) -> Option<&[u8]>; fn push(&self) -> AsyncResult<()>; } pub type BlobValue = Box; */