#[cfg(test)]
use std::collections::HashMap;
use std::sync::Arc;
use datasize::DataSize;
use once_cell::sync::OnceCell;
use tracing::error;
use crate::{
effect::EffectBuilder,
reactor::{joiner::JoinerEvent, participating::ParticipatingEvent},
types::{Deploy, DeployHash, DeployWithFinalizedApprovals},
};
#[derive(Clone, Default, Debug)]
struct CommonEffectBuilder {
joiner: OnceCell<EffectBuilder<JoinerEvent>>,
participating: OnceCell<EffectBuilder<ParticipatingEvent>>,
}
#[derive(Clone, Debug, DataSize)]
pub(crate) struct DeployGetter {
#[data_size(skip)]
effect_builder: Arc<CommonEffectBuilder>,
#[cfg(test)]
deploys: Arc<HashMap<DeployHash, Deploy>>,
}
impl DeployGetter {
pub(crate) fn new(joiner_effect_builder: EffectBuilder<JoinerEvent>) -> Self {
let effect_builder = CommonEffectBuilder::default();
let _ = effect_builder.joiner.set(joiner_effect_builder);
DeployGetter {
effect_builder: Arc::new(effect_builder),
#[cfg(test)]
deploys: Arc::new(HashMap::new()),
}
}
pub(super) fn set_participating_effect_builder(
&self,
effect_builder: EffectBuilder<ParticipatingEvent>,
) {
if self
.effect_builder
.participating
.set(effect_builder)
.is_err()
{
error!("participating effect builder already set in deploy getter");
}
}
#[cfg_attr(test, allow(unreachable_code))]
pub(super) async fn get(&self, deploy_hash: DeployHash) -> Option<Deploy> {
#[cfg(test)]
return self.get_test_deploy(deploy_hash);
let deploy_hashes = vec![deploy_hash];
let mut maybe_deploys =
if let Some(participating_effect_builder) = self.effect_builder.participating.get() {
participating_effect_builder
.get_deploys_from_storage(deploy_hashes)
.await
} else if let Some(joiner_effect_builder) = self.effect_builder.joiner.get() {
joiner_effect_builder
.get_deploys_from_storage(deploy_hashes)
.await
} else {
error!("no effect builder set in deploy getter");
return None;
};
if maybe_deploys.len() != 1 {
panic!("should return exactly one deploy");
}
maybe_deploys
.pop()
.unwrap()
.map(DeployWithFinalizedApprovals::into_naive)
}
}
#[cfg(test)]
impl DeployGetter {
pub(super) fn with_deploys(deploys: HashMap<DeployHash, Deploy>) -> Self {
DeployGetter {
effect_builder: Arc::new(CommonEffectBuilder::default()),
deploys: Arc::new(deploys),
}
}
pub(super) fn get_test_deploy(&self, deploy_hash: DeployHash) -> Option<Deploy> {
self.deploys.get(&deploy_hash).cloned()
}
}