use std::{error, fmt};
use async_trait::async_trait;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Bucket {
ProverJobs,
WitnessInput,
LeafAggregationWitnessJobs,
NodeAggregationWitnessJobs,
SchedulerWitnessJobs,
ProverJobsFri,
LeafAggregationWitnessJobsFri,
NodeAggregationWitnessJobsFri,
SchedulerWitnessJobsFri,
ProofsFri,
ProofsTee,
StorageSnapshot,
DataAvailability,
TeeVerifierInput,
}
impl Bucket {
pub(crate) fn as_str(self) -> &'static str {
match self {
Self::ProverJobs => "prover_jobs",
Self::WitnessInput => "witness_inputs",
Self::LeafAggregationWitnessJobs => "leaf_aggregation_witness_jobs",
Self::NodeAggregationWitnessJobs => "node_aggregation_witness_jobs",
Self::SchedulerWitnessJobs => "scheduler_witness_jobs",
Self::ProverJobsFri => "prover_jobs_fri",
Self::LeafAggregationWitnessJobsFri => "leaf_aggregation_witness_jobs_fri",
Self::NodeAggregationWitnessJobsFri => "node_aggregation_witness_jobs_fri",
Self::SchedulerWitnessJobsFri => "scheduler_witness_jobs_fri",
Self::ProofsFri => "proofs_fri",
Self::ProofsTee => "proofs_tee",
Self::StorageSnapshot => "storage_logs_snapshots",
Self::DataAvailability => "data_availability",
Self::TeeVerifierInput => "tee_verifier_inputs",
}
}
}
impl fmt::Display for Bucket {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
pub type BoxedError = Box<dyn error::Error + Send + Sync>;
#[derive(Debug)]
#[non_exhaustive]
pub enum ObjectStoreError {
Initialization {
source: BoxedError,
is_transient: bool,
},
KeyNotFound(BoxedError),
Serialization(BoxedError),
Other {
source: BoxedError,
is_transient: bool,
},
}
impl ObjectStoreError {
pub fn is_transient(&self) -> bool {
match self {
Self::Initialization { is_transient, .. } | Self::Other { is_transient, .. } => {
*is_transient
}
Self::KeyNotFound(_) | Self::Serialization(_) => false,
}
}
}
impl fmt::Display for ObjectStoreError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Initialization {
source,
is_transient,
} => {
let kind = if *is_transient { "transient" } else { "fatal" };
write!(
formatter,
"{kind} error initializing object store: {source}"
)
}
Self::KeyNotFound(err) => write!(formatter, "key not found: {err}"),
Self::Serialization(err) => write!(formatter, "serialization error: {err}"),
Self::Other {
source,
is_transient,
} => {
let kind = if *is_transient { "transient" } else { "fatal" };
write!(formatter, "{kind} error accessing object store: {source}")
}
}
}
}
impl error::Error for ObjectStoreError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Initialization { source, .. } | Self::Other { source, .. } => {
Some(source.as_ref())
}
Self::KeyNotFound(err) | Self::Serialization(err) => Some(err.as_ref()),
}
}
}
#[async_trait]
pub trait ObjectStore: 'static + fmt::Debug + Send + Sync {
async fn get_raw(&self, bucket: Bucket, key: &str) -> Result<Vec<u8>, ObjectStoreError>;
async fn put_raw(
&self,
bucket: Bucket,
key: &str,
value: Vec<u8>,
) -> Result<(), ObjectStoreError>;
async fn remove_raw(&self, bucket: Bucket, key: &str) -> Result<(), ObjectStoreError>;
fn storage_prefix_raw(&self, bucket: Bucket) -> String;
}