blob: ff52d676c543b70a1bf2bfcbf6729b25d6d531b1 [file] [log] [blame]
use {
crate::{
interchange::DataInterchange,
metadata::{MetadataPath, MetadataVersion, TargetPath},
repository::{RepositoryProvider, RepositoryStorage},
Error, Result,
},
futures_io::AsyncRead,
futures_util::future::{BoxFuture, FutureExt},
std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
pub(crate) struct ErrorRepository<R> {
repo: R,
fail_metadata_stores: Arc<AtomicBool>,
}
impl<R> ErrorRepository<R> {
pub(crate) fn new(repo: R) -> Self {
Self {
repo,
fail_metadata_stores: Arc::new(AtomicBool::new(false)),
}
}
pub(crate) fn fail_metadata_stores(&self, fail_metadata_stores: bool) {
self.fail_metadata_stores
.store(fail_metadata_stores, Ordering::SeqCst);
}
}
impl<D, R> RepositoryProvider<D> for ErrorRepository<R>
where
R: RepositoryProvider<D> + Sync,
D: DataInterchange + Sync,
{
fn fetch_metadata<'a>(
&'a self,
meta_path: &MetadataPath,
version: MetadataVersion,
) -> BoxFuture<'a, Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
self.repo.fetch_metadata(meta_path, version)
}
fn fetch_target<'a>(
&'a self,
target_path: &TargetPath,
) -> BoxFuture<'a, Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
self.repo.fetch_target(target_path)
}
}
impl<D, R> RepositoryStorage<D> for ErrorRepository<R>
where
R: RepositoryStorage<D> + Sync,
D: DataInterchange + Sync,
{
fn store_metadata<'a>(
&'a mut self,
meta_path: &MetadataPath,
version: MetadataVersion,
metadata: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
) -> BoxFuture<'a, Result<()>> {
if self.fail_metadata_stores.load(Ordering::SeqCst) {
async { Err(Error::Encoding("failed".into())) }.boxed()
} else {
self.repo.store_metadata(meta_path, version, metadata)
}
}
fn store_target<'a>(
&'a mut self,
target_path: &TargetPath,
target: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
) -> BoxFuture<'a, Result<()>> {
self.repo.store_target(target_path, target)
}
}