flarrow_builtins/
timer.rs

1use std::time::Duration;
2
3use crate::prelude::*;
4
5static TOKIO_RUNTIME: std::sync::LazyLock<tokio::runtime::Runtime> =
6    std::sync::LazyLock::new(|| {
7        tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime")
8    });
9
10fn default_runtime<T: Send + 'static>(
11    task: impl Future<Output = T> + Send + 'static,
12) -> tokio::task::JoinHandle<T> {
13    match tokio::runtime::Handle::try_current() {
14        Ok(handle) => handle.spawn(task),
15        Err(_) => TOKIO_RUNTIME.spawn(task),
16    }
17}
18
19pub struct Timer {
20    pub output: Output<String>,
21    pub frequency: f64,
22}
23
24#[node(runtime = "default_runtime")]
25impl Node for Timer {
26    async fn new(
27        _: Inputs,
28        mut outputs: Outputs,
29        configuration: serde_yml::Value,
30    ) -> eyre::Result<Box<dyn Node>>
31    where
32        Self: Sized,
33    {
34        let frequency = match configuration.get("frequency") {
35            Some(serde_yml::Value::Number(number)) => number.as_f64().unwrap_or(1.0),
36            _ => 1.0,
37        };
38
39        Ok(Box::new(Self {
40            output: outputs.with("out").await?,
41            frequency,
42        }) as Box<dyn Node>)
43    }
44
45    async fn start(self: Box<Self>) -> eyre::Result<()> {
46        loop {
47            tokio::time::sleep(Duration::from_millis((1000.0 / self.frequency) as u64)).await;
48
49            self.output
50                .send("tick".to_string())
51                .wrap_err("Failed to send message")?;
52        }
53    }
54}