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}