cratefield_runtime_native/ports/
clock.rs1use async_trait::async_trait;
6use futures_core::future::BoxFuture;
7use std::any::Any;
8use std::time::Duration;
9
10#[derive(Debug, Clone, Copy, Default)]
15pub struct TokioClock;
16
17#[async_trait]
18impl cratefield_core::Clock for TokioClock {
19 fn now(&self) -> time::OffsetDateTime {
20 time::OffsetDateTime::now_utc()
21 }
22
23 async fn timeout_any(
24 &self,
25 fut: BoxFuture<'static, Box<dyn Any + Send>>,
26 after: Duration,
27 ) -> Option<Box<dyn Any + Send>> {
28 tokio::time::timeout(after, fut).await.ok()
29 }
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35 use cratefield_core::Clock as _;
36
37 #[tokio::test]
38 async fn timeout_abandons_a_slow_future() {
39 let slow: BoxFuture<'static, Box<dyn Any + Send>> = Box::pin(async {
40 tokio::time::sleep(Duration::from_secs(30)).await;
41 Box::new(()) as Box<dyn Any + Send>
42 });
43 let started = std::time::Instant::now();
44 let out = TokioClock
45 .timeout_any(slow, Duration::from_millis(20))
46 .await;
47 assert!(out.is_none());
48 assert!(
49 started.elapsed() < Duration::from_secs(5),
50 "abandoned, not awaited"
51 );
52 }
53
54 #[tokio::test]
55 async fn timeout_returns_a_fast_future() {
56 let fast: BoxFuture<'static, Box<dyn Any + Send>> =
57 Box::pin(async { Box::new(7_u32) as Box<dyn Any + Send> });
58 let out = TokioClock.timeout_any(fast, Duration::from_secs(5)).await;
59 let value = out
60 .and_then(|any| any.downcast::<u32>().ok())
61 .map(|boxed| *boxed);
62 assert_eq!(value, Some(7));
63 }
64}