trillium_server_common/runtime/runtime_trait.rs
1use super::{DroppableFuture, Runtime};
2use futures_lite::{FutureExt, Stream};
3use std::{future::Future, time::Duration};
4
5/// A trait that covers async runtime behavior.
6///
7/// You likely do not need to name this type. For a type-erased runtime, see [`Runtime`]
8pub trait RuntimeTrait: Into<Runtime> + Clone + Send + Sync + 'static {
9 /// Spawn a future on the runtime, returning a future that has detach-on-drop semantics
10 ///
11 /// As the various runtimes each has different behavior for spawn, implementations of this trait
12 /// are expected to conform to the following:
13 ///
14 /// * detach on drop: If the returned [`DroppableFuture`] is dropped immediately, the task will
15 /// continue to execute until completion.
16 ///
17 /// * unwinding: If the spawned future panics, this must not propagate to the join handle.
18 /// Instead, the awaiting the join handle returns None in case of panic.
19 fn spawn<Fut>(
20 &self,
21 fut: Fut,
22 ) -> DroppableFuture<impl Future<Output = Option<Fut::Output>> + Send + 'static>
23 where
24 Fut: Future + Send + 'static,
25 Fut::Output: Send + 'static;
26
27 /// Wake in this amount of wall time
28 fn delay(&self, duration: Duration) -> impl Future<Output = ()> + Send;
29
30 /// Returns a [`Stream`] that yields a `()` on the provided period
31 fn interval(&self, period: Duration) -> impl Stream<Item = ()> + Send + 'static;
32
33 /// Runtime implementation hook for blocking on a top level future.
34 fn block_on<Fut>(&self, fut: Fut) -> Fut::Output
35 where
36 Fut: Future;
37
38 /// Race a future against the provided duration, returning None in case of timeout.
39 fn timeout<'runtime, 'fut, Fut>(
40 &'runtime self,
41 duration: Duration,
42 fut: Fut,
43 ) -> impl Future<Output = Option<Fut::Output>> + Send + 'fut
44 where
45 Fut: Future + Send + 'fut,
46 Fut::Output: Send + 'static,
47 'runtime: 'fut,
48 {
49 async move { Some(fut.await) }.race(async move {
50 self.delay(duration).await;
51 None
52 })
53 }
54
55 /// trap and return a [`Stream`] of signals that match the provided signals
56 fn hook_signals(
57 &self,
58 signals: impl IntoIterator<Item = i32>,
59 ) -> impl Stream<Item = i32> + Send + 'static {
60 let _ = signals;
61 futures_lite::stream::empty()
62 }
63}