Skip to main content

systemprompt_runtime/context/
shutdown.rs

1//! In-process request for a graceful restart.
2//!
3//! An admin action that swaps the services root cannot take effect in the
4//! running process: the loader, the router and every cached catalog were
5//! built from the old tree. Rather than rebuild them in place, the handler
6//! asks the process to drain and exit, and the supervisor starts it again on
7//! the new composition.
8//!
9//! Copyright (c) systemprompt.io — Business Source License 1.1.
10//! See <https://systemprompt.io> for licensing details.
11
12use std::sync::Arc;
13
14use tokio::sync::Notify;
15
16/// Handle used to ask the running process to drain and exit.
17///
18/// One handle is created at the composition root and shared by clone between
19/// the [`super::AppContext`] and the server's shutdown selector; the server
20/// binds its listener before the context exists, so both must be handed the
21/// same handle rather than each making its own. A request raised before
22/// anyone is waiting is held as a permit and delivered to the first waiter,
23/// so a restart asked for during boot is not lost.
24#[derive(Debug, Clone)]
25pub struct ShutdownRequest {
26    notify: Arc<Notify>,
27}
28
29impl Default for ShutdownRequest {
30    fn default() -> Self {
31        Self {
32            notify: Arc::new(Notify::new()),
33        }
34    }
35}
36
37impl ShutdownRequest {
38    pub fn request(&self, reason: &str) {
39        tracing::warn!(reason = %reason, "Graceful restart requested");
40        self.notify.notify_one();
41    }
42
43    pub async fn requested(&self) {
44        self.notify.notified().await;
45    }
46}