]>
git.proxmox.com Git - proxmox-backup.git/blob - proxmox-rest-server/src/state.rs
2 use lazy_static
::lazy_static
;
7 use tokio
::signal
::unix
::{signal, SignalKind}
;
9 use pbs_tools
::broadcast_future
::BroadcastData
;
11 #[derive(PartialEq, Copy, Clone, Debug)]
17 pub struct ServerState
{
19 pub shutdown_listeners
: BroadcastData
<()>,
20 pub last_worker_listeners
: BroadcastData
<()>,
21 pub worker_count
: usize,
22 pub internal_task_count
: usize,
23 pub reload_request
: bool
,
27 static ref SERVER_STATE
: Mutex
<ServerState
> = Mutex
::new(ServerState
{
28 mode
: ServerMode
::Normal
,
29 shutdown_listeners
: BroadcastData
::new(),
30 last_worker_listeners
: BroadcastData
::new(),
32 internal_task_count
: 0,
33 reload_request
: false,
37 /// Listen to ``SIGINT`` and ``SIGHUP`` signals
39 /// * ``SIGINT``: start server shutdown
41 /// * ``SIGHUP``: start server reload
42 pub fn catch_shutdown_and_reload_signals() -> Result
<(), Error
> {
44 let mut stream
= signal(SignalKind
::interrupt())?
;
46 let future
= async
move {
47 while stream
.recv().await
.is_some() {
48 log
::info
!("got shutdown request (SIGINT)");
49 SERVER_STATE
.lock().unwrap().reload_request
= false;
50 crate::request_shutdown();
54 let abort_future
= last_worker_future().map_err(|_
| {}
);
55 let task
= futures
::future
::select(future
, abort_future
);
57 tokio
::spawn(task
.map(|_
| ()));
59 let mut stream
= signal(SignalKind
::hangup())?
;
61 let future
= async
move {
62 while stream
.recv().await
.is_some() {
63 log
::info
!("got reload request (SIGHUP)");
64 SERVER_STATE
.lock().unwrap().reload_request
= true;
65 crate::request_shutdown();
69 let abort_future
= last_worker_future().map_err(|_
| {}
);
70 let task
= futures
::future
::select(future
, abort_future
);
72 tokio
::spawn(task
.map(|_
| ()));
77 pub fn is_reload_request() -> bool
{
78 let data
= SERVER_STATE
.lock().unwrap();
80 data
.mode
== ServerMode
::Shutdown
&& data
.reload_request
83 pub fn server_shutdown() {
84 let mut data
= SERVER_STATE
.lock().unwrap();
86 log
::info
!("request_shutdown");
88 data
.mode
= ServerMode
::Shutdown
;
90 data
.shutdown_listeners
.notify_listeners(Ok(()));
97 pub fn shutdown_future() -> impl Future
<Output
= ()> {
98 let mut data
= SERVER_STATE
.lock().unwrap();
105 pub fn last_worker_future() -> impl Future
<Output
= Result
<(), Error
>> {
106 let mut data
= SERVER_STATE
.lock().unwrap();
107 data
.last_worker_listeners
.listen()
110 pub fn set_worker_count(count
: usize) {
111 SERVER_STATE
.lock().unwrap().worker_count
= count
;
116 pub fn check_last_worker() {
117 let mut data
= SERVER_STATE
.lock().unwrap();
119 if !(data
.mode
== ServerMode
::Shutdown
&& data
.worker_count
== 0 && data
.internal_task_count
== 0) { return; }
121 data
.last_worker_listeners
.notify_listeners(Ok(()));
124 /// Spawns a tokio task that will be tracked for reload
125 /// and if it is finished, notify the last_worker_listener if we
126 /// are in shutdown mode
127 pub fn spawn_internal_task
<T
>(task
: T
)
129 T
: Future
+ Send
+ '
static,
130 T
::Output
: Send
+ '
static,
132 let mut data
= SERVER_STATE
.lock().unwrap();
133 data
.internal_task_count
+= 1;
135 tokio
::spawn(async
move {
136 let _
= tokio
::spawn(task
).await
; // ignore errors
139 let mut data
= SERVER_STATE
.lock().unwrap();
140 if data
.internal_task_count
> 0 {
141 data
.internal_task_count
-= 1;