hopr_transport_protocol/
timer.rs1use futures::future::{select, Either};
2use futures::pin_mut;
3use futures::FutureExt;
4use std::time::Duration;
5use tracing::{trace, warn};
6
7use hopr_async_runtime::prelude::sleep;
8use hopr_platform::time::native::current_time;
9use hopr_primitive_types::prelude::AsUnixTimestamp;
10
11pub async fn execute_on_tick<F>(cycle: Duration, action: impl Fn() -> F, operation: String)
14where
15 F: std::future::Future<Output = ()> + Send,
16{
17 loop {
18 let start = current_time().as_unix_timestamp();
19
20 let timeout = sleep(cycle).fuse();
21 let todo = (action)().fuse();
22
23 pin_mut!(timeout, todo);
24
25 match select(timeout, todo).await {
26 Either::Left(_) => warn!(operation, "Timer tick interrupted by timeout"),
27 Either::Right(_) => {
28 trace!(operation, "Timer tick finished");
29
30 let action_duration = current_time().as_unix_timestamp().saturating_sub(start);
31 if let Some(remaining) = cycle.checked_sub(action_duration) {
32 trace!(
33 remaining_time_in_ms = remaining.as_millis(),
34 "Universal timer sleeping for",
35 );
36 sleep(remaining).await
37 }
38 }
39 };
40 }
41}