diff options
Diffstat (limited to 'src/modules/delay.rs')
-rw-r--r-- | src/modules/delay.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/modules/delay.rs b/src/modules/delay.rs new file mode 100644 index 0000000..ab46a90 --- /dev/null +++ b/src/modules/delay.rs @@ -0,0 +1,47 @@ +use super::{Node, NodeContext, NodeKind, NodeRequest, NodeResponse}; +use crate::{config::DynNode, error::ServiceError}; +use anyhow::Result; +use rand_distr::Distribution; +use serde::Deserialize; +use serde_yml::Value; +use std::{future::Future, pin::Pin, sync::Arc, time::Duration}; +use tokio::time::sleep; + +pub struct DelayKind; + +#[derive(Deserialize)] +struct Delay { + duration: u64, + stdev: u64, + next: DynNode, +} + +impl NodeKind for DelayKind { + fn name(&self) -> &'static str { + "delay" + } + fn instanciate(&self, config: Value) -> Result<Arc<dyn Node>> { + Ok(Arc::new(serde_yml::from_value::<Delay>(config)?)) + } +} +impl Node for Delay { + fn handle<'a>( + &'a self, + context: &'a mut NodeContext, + request: NodeRequest, + ) -> Pin<Box<dyn Future<Output = Result<NodeResponse, ServiceError>> + Send + Sync + 'a>> { + Box::pin(async move { + sleep(Duration::from_millis(if self.stdev == 0 { + self.duration + } else { + self.duration.saturating_add_signed( + rand_distr::Normal::new(0., self.stdev as f32) + .unwrap() + .sample(&mut rand::rng()) as i64, + ) + })) + .await; + self.next.handle(context, request).await + }) + } +} |