wire_framework/service/
shutdown_hook.rs

1use std::{fmt, future::Future};
2
3use futures::{FutureExt, future::BoxFuture};
4
5use crate::{IntoContext, TaskId};
6
7/// A named future that will be invoked after all the tasks are stopped.
8/// The future is expected to perform a cleanup or a shutdown of the service.
9///
10/// All the shutdown hooks will be executed sequentially, so they may assume that
11/// no other tasks are running at the moment of execution on the same node. However,
12/// an unique access to the database is not guaranteed, since the node may run in a
13/// distributed mode, so this should not be used for potentially destructive actions.
14pub struct ShutdownHook {
15    pub(crate) id: TaskId,
16    pub(crate) future: BoxFuture<'static, eyre::Result<()>>,
17}
18
19impl fmt::Debug for ShutdownHook {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        f.debug_struct("ShutdownHook")
22            .field("name", &self.id)
23            .finish()
24    }
25}
26
27impl ShutdownHook {
28    pub fn new(
29        name: &'static str,
30        hook: impl Future<Output = eyre::Result<()>> + Send + 'static,
31    ) -> Self {
32        Self {
33            id: name.into(),
34            future: hook.boxed(),
35        }
36    }
37}
38
39impl IntoContext for ShutdownHook {
40    fn into_context(
41        self,
42        context: &mut super::ServiceContext<'_>,
43    ) -> Result<(), crate::WiringError> {
44        context.add_shutdown_hook(self);
45        Ok(())
46    }
47}