use crate::features::storage::api::{Result, StorageError};
#[cfg(feature = "rhodium-backend")]
use super::{BlobAckMode, BlobDurabilityTarget, BlobPutOptions, BlobPutResult};
#[cfg(feature = "rhodium-backend")]
use rhodium_cache::core::storage::blob::{
AckPolicy as RhodiumAckPolicy, PutOptions as RhodiumPutOptions, PutResult as RhodiumPutResult,
};
#[cfg(feature = "rhodium-backend")]
use rhodium_cache::core::storage::StorageError as RhodiumStorageError;
pub(super) fn validate_local_blob_id(blob_id: &str) -> Result<()> {
if blob_id.is_empty() {
return Err(StorageError::InvalidInput(
"blob_id must not be empty".to_string(),
));
}
if blob_id.contains('/') || blob_id.contains('\\') {
return Err(StorageError::InvalidInput(
"blob_id must not contain path separators".to_string(),
));
}
Ok(())
}
#[cfg(feature = "rhodium-backend")]
pub(super) fn validate_rhodium_blob_id(blob_id: &str) -> Result<()> {
if blob_id.is_empty() {
return Err(StorageError::InvalidInput(
"blob_id must not be empty".to_string(),
));
}
Ok(())
}
pub(super) fn unsupported_prefix_error() -> StorageError {
StorageError::InvalidInput("prefix listing not supported by this backend".to_string())
}
#[cfg(not(feature = "rhodium-backend"))]
pub(super) fn rhodium_not_wired_message() -> String {
"rhodium blob backend is not wired yet; enable `rhodium-backend` and complete adapter implementation"
.to_string()
}
#[cfg(feature = "rhodium-backend")]
pub(super) fn to_rhodium_put_options(options: BlobPutOptions) -> RhodiumPutOptions {
let overwrite_policy = if options.deny_if_exists {
rhodium_cache::core::storage::blob::OverwritePolicy::DenyIfExists
} else {
rhodium_cache::core::storage::blob::OverwritePolicy::AllowOverwrite
};
let target = match options.durability_target {
BlobDurabilityTarget::Memory => rhodium_cache::core::storage::blob::DurabilityTier::Memory,
BlobDurabilityTarget::Disk => rhodium_cache::core::storage::blob::DurabilityTier::Disk,
BlobDurabilityTarget::Remote => rhodium_cache::core::storage::blob::DurabilityTier::Remote,
};
let ack = match options.ack_mode {
BlobAckMode::FireAndForget => RhodiumAckPolicy::FireAndForget,
BlobAckMode::Flush => RhodiumAckPolicy::Flush {
target,
timeout_ms: options.timeout_ms,
},
};
RhodiumPutOptions {
overwrite_policy,
ack,
idempotent: options.idempotent,
verify_content_hash: options.verify_content_hash,
quorum_override: None,
ttl_secs: None,
}
}
#[cfg(feature = "rhodium-backend")]
pub(super) fn from_rhodium_put_result(result: RhodiumPutResult) -> BlobPutResult {
BlobPutResult {
inserted: result.inserted,
overwritten: result.overwritten,
idempotent_noop: result.idempotent_noop,
}
}
#[cfg(feature = "rhodium-backend")]
pub(super) fn map_rhodium_error(err: RhodiumStorageError) -> StorageError {
match err {
RhodiumStorageError::NotFound => StorageError::InvalidInput("blob not found".to_string()),
RhodiumStorageError::AlreadyExists => {
StorageError::InvalidInput("blob already exists".to_string())
}
RhodiumStorageError::Unsupported(message) => StorageError::InvalidInput(message),
RhodiumStorageError::Retryable { class, message } => {
StorageError::Sstable(format!("rhodium retryable {:?}: {}", class, message))
}
RhodiumStorageError::Terminal { class, message } => {
StorageError::InvalidInput(format!("rhodium terminal {:?}: {}", class, message))
}
RhodiumStorageError::Timeout { timeout_ms } => {
StorageError::Sstable(format!("rhodium timeout after {}ms", timeout_ms))
}
RhodiumStorageError::Internal(message) => {
StorageError::Sstable(format!("rhodium internal: {}", message))
}
}
}
#[cfg(not(feature = "rhodium-backend"))]
#[derive(Debug)]
pub struct RhodiumBlobStore {}
#[cfg(not(feature = "rhodium-backend"))]
impl RhodiumBlobStore {
pub fn new(root: std::path::PathBuf) -> Result<Self> {
let _ = root;
Ok(Self {})
}
}
#[cfg(not(feature = "rhodium-backend"))]
impl super::BlobStore for RhodiumBlobStore {
fn put_blob_with_options(
&mut self,
_blob_id: &str,
_bytes: &[u8],
_options: super::BlobPutOptions,
) -> Result<super::BlobPutResult> {
Err(StorageError::InvalidInput(rhodium_not_wired_message()))
}
fn get_blob_with_options(
&self,
_blob_id: &str,
_options: super::BlobReadOptions,
) -> Result<Option<super::BlobGetResult>> {
Err(StorageError::InvalidInput(rhodium_not_wired_message()))
}
fn has_blob(&self, _blob_id: &str) -> Result<bool> {
Err(StorageError::InvalidInput(rhodium_not_wired_message()))
}
fn delete_blob(&mut self, _blob_id: &str) -> Result<()> {
Err(StorageError::InvalidInput(rhodium_not_wired_message()))
}
}