use std::{ops::Range, sync::Arc};
use bytes::Bytes;
use object_store::{ObjectStore, ObjectStoreExt, path::Path};
use serde::{Deserialize, Serialize};
use crate::store::{cache, retry};
#[derive(Clone)]
pub struct DataStore {
store: Arc<dyn ObjectStore>,
pub(super) identity: StoreIdentity,
}
impl DataStore {
#[must_use]
pub fn new(store: Arc<dyn ObjectStore>) -> Self {
let identity = StoreIdentity::of(&store);
Self { store, identity }
}
#[must_use]
pub fn object_store(&self) -> &Arc<dyn ObjectStore> {
&self.store
}
pub(crate) async fn read_range(
&self,
path: &Path,
range: Range<u64>,
) -> object_store::Result<Bytes> {
retry::retrying("a data-file read", path, || {
self.store.get_range(path, range.clone())
})
.await
}
pub(crate) async fn read_ranges(
&self,
path: &Path,
ranges: &[Range<u64>],
) -> object_store::Result<Vec<Bytes>> {
retry::retrying("a data-file read", path, || {
self.store.get_ranges(path, ranges)
})
.await
}
}
impl std::fmt::Debug for DataStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "DataStore({})", self.store)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub(super) enum StoreIdentity {
Durable(u128),
Ephemeral(u128),
}
const IN_MEMORY: &str = "InMemory";
impl StoreIdentity {
pub(super) fn of(store: &Arc<dyn ObjectStore>) -> Self {
let name = store.to_string();
if name.contains(IN_MEMORY) {
Self::Ephemeral(uuid::Uuid::new_v4().as_u128())
} else {
Self::Durable(cache::stable_name(&name).as_u128())
}
}
}