Skip to main content

fedimint_core/
runtime.rs

1//! Abstraction over an executor so we can spawn tasks under WASM the same way
2//! we do usually.
3
4use std::future::Future;
5
6use fedimint_logging::LOG_RUNTIME;
7pub use n0_future::task::{JoinError, JoinHandle};
8pub use n0_future::time::{Duration, Elapsed, Instant, sleep, sleep_until, timeout};
9use tracing::{Instrument, Span};
10
11use crate::task::MaybeSend;
12
13pub fn spawn<F, T>(name: &str, future: F) -> JoinHandle<T>
14where
15    F: Future<Output = T> + 'static + MaybeSend,
16    T: MaybeSend + 'static,
17{
18    let span = tracing::debug_span!(target: LOG_RUNTIME, parent: None, "spawn", task = name);
19    n0_future::task::spawn(future.instrument(span))
20}
21
22/// Like [`spawn`] but with an explicit parent span.
23///
24/// Events from the spawned future inherit fields from `parent` (e.g. `fed_id`
25/// from the client span), including the lifecycle events emitted by
26/// [`crate::task::TaskGroup`] around the user future.
27pub fn spawn_with_span<F, T>(parent: &Span, name: &str, future: F) -> JoinHandle<T>
28where
29    F: Future<Output = T> + 'static + MaybeSend,
30    T: MaybeSend + 'static,
31{
32    let span = tracing::debug_span!(target: LOG_RUNTIME, parent: parent, "spawn", task = name);
33    n0_future::task::spawn(future.instrument(span))
34}
35
36/// Runs CPU-bound work off the async workers so they stay schedulable.
37///
38/// Meant for the pairings that verify signature and decryption shares. Wasm
39/// has no blocking pool, so there the work runs inline.
40pub async fn spawn_blocking<F, R>(f: F) -> R
41where
42    F: FnOnce() -> R + MaybeSend + 'static,
43    R: MaybeSend + 'static,
44{
45    #[cfg(not(target_family = "wasm"))]
46    {
47        tokio::task::spawn_blocking(f)
48            .await
49            .expect("Blocking task panicked")
50    }
51    #[cfg(target_family = "wasm")]
52    {
53        f()
54    }
55}
56
57// Note: These functions only exist on non-wasm platforms and you need to handle
58// them conditionally at the call site of packages that compile on wasm
59#[cfg(not(target_family = "wasm"))]
60pub fn block_in_place<F, R>(f: F) -> R
61where
62    F: FnOnce() -> R,
63{
64    // nosemgrep: ban-raw-block-in-place
65    tokio::task::block_in_place(f)
66}
67
68#[cfg(not(target_family = "wasm"))]
69pub fn block_on<F: Future>(future: F) -> F::Output {
70    // nosemgrep: ban-raw-block-on
71    tokio::runtime::Handle::current().block_on(future)
72}