use std::{
fmt::{self, Debug, Formatter},
sync::Arc,
};
use futures::future::BoxFuture;
use prometheus::Registry;
use casper_types::{Chainspec, ChainspecRawBytes};
use super::network::NetworkedReactor;
use crate::{
components::{network::Identity as NetworkIdentity, ComponentState},
effect::{EffectBuilder, Effects},
reactor::{EventQueueHandle, Finalize, Reactor},
types::NodeId,
NodeRng,
};
type ConditionChecker<R> = Box<dyn Fn(&<R as Reactor>::Event) -> bool + Send>;
pub(crate) struct ConditionCheckReactor<R: Reactor> {
reactor: R,
condition_checker: Option<ConditionChecker<R>>,
condition_result: bool,
}
impl<R: Reactor> ConditionCheckReactor<R> {
pub(crate) fn set_condition_checker(&mut self, condition_checker: ConditionChecker<R>) {
self.condition_checker = Some(condition_checker);
self.condition_result = false;
}
pub(crate) fn condition_result(&self) -> bool {
self.condition_result
}
pub(crate) fn inner(&self) -> &R {
&self.reactor
}
pub(crate) fn inner_mut(&mut self) -> &mut R {
&mut self.reactor
}
}
impl<R: Reactor> Reactor for ConditionCheckReactor<R> {
type Event = R::Event;
type Config = R::Config;
type Error = R::Error;
fn new(
config: Self::Config,
chainspec: Arc<Chainspec>,
chainspec_raw_bytes: Arc<ChainspecRawBytes>,
network_identity: NetworkIdentity,
registry: &Registry,
event_queue: EventQueueHandle<Self::Event>,
rng: &mut NodeRng,
) -> Result<(Self, Effects<Self::Event>), Self::Error> {
let (reactor, effects) = R::new(
config,
chainspec,
chainspec_raw_bytes,
network_identity,
registry,
event_queue,
rng,
)?;
Ok((
Self {
reactor,
condition_checker: None,
condition_result: false,
},
effects,
))
}
fn dispatch_event(
&mut self,
effect_builder: EffectBuilder<Self::Event>,
rng: &mut NodeRng,
event: Self::Event,
) -> Effects<Self::Event> {
self.condition_result = self
.condition_checker
.as_ref()
.map(|condition_checker| condition_checker(&event))
.unwrap_or_default();
if self.condition_result {
self.condition_checker = None;
}
self.reactor.dispatch_event(effect_builder, rng, event)
}
fn get_component_state(&self, name: &str) -> Option<&ComponentState> {
self.inner().get_component_state(name)
}
}
impl<R: Reactor + Finalize> Finalize for ConditionCheckReactor<R> {
fn finalize(self) -> BoxFuture<'static, ()> {
self.reactor.finalize()
}
}
impl<R: Reactor + NetworkedReactor> NetworkedReactor for ConditionCheckReactor<R> {
fn node_id(&self) -> NodeId {
self.reactor.node_id()
}
}
impl<R: Reactor + Debug> Debug for ConditionCheckReactor<R> {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
formatter
.debug_struct("ConditionCheckReactor")
.field("reactor", &self.reactor)
.field("condition_check_result", &self.condition_result)
.finish()
}
}