Skip to main content

modo/runtime/
run_macro.rs

1/// Waits for a shutdown signal and then shuts down each task in order.
2///
3/// `run!` accepts one or more expressions that implement [`Task`](crate::runtime::Task).
4/// It returns an `async` block that, when `.await`ed:
5///
6/// 1. Calls [`wait_for_shutdown_signal`](crate::runtime::wait_for_shutdown_signal)
7///    and blocks until `SIGINT` or `SIGTERM` is received.
8/// 2. Iterates through each supplied task **in declaration order**, calling
9///    [`Task::shutdown`](crate::runtime::Task::shutdown) on each one.
10/// 3. Logs a tracing `info` event for each step and an `error` event for any
11///    task that returns `Err`.
12/// 4. Returns `Ok::<(), modo::Error>(())`.
13///
14/// # Example
15///
16/// ```rust,no_run
17/// use modo::runtime::Task;
18/// use modo::Result;
19///
20/// struct Worker;
21/// struct HttpServer;
22///
23/// impl Task for Worker {
24///     async fn shutdown(self) -> Result<()> { Ok(()) }
25/// }
26///
27/// impl Task for HttpServer {
28///     async fn shutdown(self) -> Result<()> { Ok(()) }
29/// }
30///
31/// #[tokio::main]
32/// async fn main() -> Result<()> {
33///     let worker = Worker;
34///     let server = HttpServer;
35///     modo::run!(worker, server).await
36/// }
37/// ```
38#[macro_export]
39macro_rules! run {
40    ($($task:expr),+ $(,)?) => {
41        async {
42            $crate::runtime::wait_for_shutdown_signal().await;
43            $crate::tracing::info!("shutdown signal received, stopping services...");
44
45            $(
46                let task_name = stringify!($task);
47                $crate::tracing::info!(task = task_name, "shutting down");
48                if let Err(e) = $crate::runtime::Task::shutdown($task).await {
49                    $crate::tracing::error!(task = task_name, error = %e, "shutdown error");
50                }
51            )+
52
53            $crate::tracing::info!("all services stopped");
54            Ok::<(), $crate::error::Error>(())
55        }
56    };
57}