use std::collections::BTreeSet;
use std::sync::Arc;
use crate::collection::{
CollectionHandle, CollectionRead, CollectionRecord, CollectionRecordSelector,
};
use crate::inline::encodings::hash::Handle;
use crate::inline::InlineEncoding;
use crate::repo::{BlobStoreGet, BlobStoreList, CapabilityProofRead};
#[cfg(test)]
mod tests;
#[derive(Clone)]
pub struct AcquiringReader<S> {
frozen: S,
runtime: RuntimeDriver,
}
#[derive(Clone)]
enum RuntimeDriver {
Owned(Arc<tokio::runtime::Runtime>),
Borrowed(tokio::runtime::Handle),
}
impl RuntimeDriver {
fn block_on<F: std::future::Future>(&self, future: F) -> F::Output {
match self {
Self::Owned(runtime) => runtime.block_on(future),
Self::Borrowed(runtime) => runtime.block_on(future),
}
}
}
impl<S> AcquiringReader<S> {
pub fn into_frozen(self) -> S {
self.frozen
}
pub fn with_handle(snapshot: S, runtime: tokio::runtime::Handle) -> Self {
Self {
frozen: snapshot,
runtime: RuntimeDriver::Borrowed(runtime),
}
}
pub fn new(snapshot: S, runtime: Arc<tokio::runtime::Runtime>) -> Self {
Self {
frozen: snapshot,
runtime: RuntimeDriver::Owned(runtime),
}
}
}
impl<S: crate::repo::StoreSnapshot> crate::repo::StoreSnapshot for AcquiringReader<S> {
fn changes_since(&self, previous: &Self) -> crate::repo::StoreChanges {
self.frozen.changes_since(&previous.frozen)
}
fn changes_for(
&self,
previous: &Self,
dependencies: &crate::repo::StoreDependencies,
) -> crate::repo::StoreChanges {
self.frozen.changes_for(&previous.frozen, dependencies)
}
}
impl<S: crate::repo::async_store::AsyncBlobStoreGet> BlobStoreGet for AcquiringReader<S> {
type GetError<E: std::error::Error + Send + Sync + 'static> = S::GetError<E>;
fn get<T, E>(
&self,
handle: crate::inline::Inline<Handle<E>>,
) -> Result<T, Self::GetError<T::Error>>
where
E: crate::blob::BlobEncoding + 'static,
T: crate::blob::TryFromBlob<E>,
Handle<E>: InlineEncoding,
{
self.runtime.block_on(self.frozen.get(handle))
}
}
impl<S: crate::repo::async_store::AsyncBlobStoreGet> crate::repo::async_store::AsyncBlobStoreGet
for AcquiringReader<S>
{
type GetError<E: std::error::Error + Send + Sync + 'static> = S::GetError<E>;
fn get<T, E>(
&self,
handle: crate::inline::Inline<Handle<E>>,
) -> impl std::future::Future<Output = Result<T, Self::GetError<T::Error>>> + Send
where
E: crate::blob::BlobEncoding + 'static,
T: crate::blob::TryFromBlob<E>,
Handle<E>: InlineEncoding,
{
self.frozen.get(handle)
}
}
impl<S: CapabilityProofRead> CapabilityProofRead for AcquiringReader<S> {
type ProofsError = S::ProofsError;
type ProofIter<'a>
= S::ProofIter<'a>
where
Self: 'a;
fn proofs(&self) -> Result<Self::ProofIter<'_>, Self::ProofsError> {
self.frozen.proofs()
}
fn proof(
&self,
id: crate::capability::CapabilityProofId,
) -> Result<Option<crate::capability::CapabilityProof>, Self::ProofsError> {
self.frozen.proof(id)
}
}
impl<S: BlobStoreList> BlobStoreList for AcquiringReader<S> {
type Err = S::Err;
type Iter<'a>
= S::Iter<'a>
where
Self: 'a;
fn blobs(&self) -> Self::Iter<'_> {
self.frozen.blobs()
}
fn contains_blob<E>(&self, handle: crate::inline::Inline<Handle<E>>) -> Result<bool, Self::Err>
where
E: crate::blob::BlobEncoding + 'static,
Handle<E>: InlineEncoding,
{
self.frozen.contains_blob(handle)
}
}
impl<S: crate::repo::BlobStoreMeta> crate::repo::BlobStoreMeta for AcquiringReader<S> {
type MetaError = S::MetaError;
fn metadata<E>(
&self,
handle: crate::inline::Inline<Handle<E>>,
) -> Result<Option<crate::repo::BlobMetadata>, Self::MetaError>
where
E: crate::blob::BlobEncoding + 'static,
Handle<E>: InlineEncoding,
{
self.frozen.metadata(handle)
}
}
impl<S: CollectionRead> CollectionRead for AcquiringReader<S> {
type RecordsError = crate::repo::ReadFailure;
type RecordIter<'a>
= Box<dyn Iterator<Item = Result<CollectionRecord, Self::RecordsError>> + 'a>
where
Self: 'a;
fn records(&self) -> Result<Self::RecordIter<'_>, Self::RecordsError> {
self.frozen
.records()
.map(|records| {
Box::new(records.map(|record| record.map_err(crate::repo::ReadFailure::new)))
as Self::RecordIter<'_>
})
.map_err(crate::repo::ReadFailure::new)
}
fn collections(&self) -> Result<Vec<CollectionHandle>, Self::RecordsError> {
self.frozen
.collections()
.map_err(crate::repo::ReadFailure::new)
}
fn select_records(
&self,
selectors: &BTreeSet<CollectionRecordSelector>,
) -> Result<Vec<CollectionRecord>, Self::RecordsError> {
self.frozen
.select_records(selectors)
.map_err(crate::repo::ReadFailure::new)
}
}
impl<S> crate::collection::CoverageRead for AcquiringReader<S>
where
S: crate::collection::CoverageRead
+ CapabilityProofRead
+ crate::repo::async_store::AsyncBlobStoreGet,
{
fn index(
&self,
lineage: &BTreeSet<CollectionHandle>,
) -> Result<crate::collection::coverage::CoverageIndex, Self::RecordsError> {
let mut index = self
.frozen
.index(lineage)
.map_err(crate::repo::ReadFailure::new)?;
let attempt = crate::repo::read_attempt::ReadAttempt::new(self);
index.retry_collections(
&crate::collection::coverage::StoreWriters::new(&attempt),
lineage,
);
attempt.finish()?;
Ok(index)
}
}
impl<S: crate::repo::WantRead> crate::repo::WantRead for AcquiringReader<S> {
type WantsError = S::WantsError;
type WantIter<'a>
= S::WantIter<'a>
where
Self: 'a;
fn wants(&self) -> Result<Self::WantIter<'_>, Self::WantsError> {
self.frozen.wants()
}
}