add server restart support w/ admin command
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
2cb31275f0
commit
c6f4b20e17
|
@ -49,6 +49,10 @@ pub(crate) enum ServerCommand {
|
|||
/// - Hot-reload the server
|
||||
Reload,
|
||||
|
||||
#[cfg(unix)]
|
||||
/// - Restart the server
|
||||
Restart,
|
||||
|
||||
/// - Shutdown the server
|
||||
Shutdown,
|
||||
}
|
||||
|
@ -72,6 +76,8 @@ pub(crate) async fn process(command: ServerCommand, body: Vec<&str>) -> Result<R
|
|||
} => admin_notice(body, message).await?,
|
||||
#[cfg(conduit_mods)]
|
||||
ServerCommand::Reload => reload(body).await?,
|
||||
#[cfg(unix)]
|
||||
ServerCommand::Restart => restart(body).await?,
|
||||
ServerCommand::Shutdown => shutdown(body).await?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -112,6 +112,13 @@ pub(crate) async fn reload(_body: Vec<&str>) -> Result<RoomMessageEventContent>
|
|||
Ok(RoomMessageEventContent::notice_plain("Reloading server..."))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub(crate) async fn restart(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
services().server.restart()?;
|
||||
|
||||
Ok(RoomMessageEventContent::notice_plain("Restarting server..."))
|
||||
}
|
||||
|
||||
pub(crate) async fn shutdown(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
warn!("shutdown command");
|
||||
services().server.shutdown()?;
|
||||
|
|
|
@ -23,6 +23,9 @@ pub struct Server {
|
|||
/// is an observable used on shutdown and modifying is not recommended.
|
||||
pub reloading: AtomicBool,
|
||||
|
||||
/// Restart desired; when true, restart it desired after shutdown.
|
||||
pub restarting: AtomicBool,
|
||||
|
||||
/// Handle to the runtime
|
||||
pub runtime: Option<runtime::Handle>,
|
||||
|
||||
|
@ -48,6 +51,7 @@ impl Server {
|
|||
started: SystemTime::now(),
|
||||
stopping: AtomicBool::new(false),
|
||||
reloading: AtomicBool::new(false),
|
||||
restarting: AtomicBool::new(false),
|
||||
runtime,
|
||||
signal: broadcast::channel::<&'static str>(1).0,
|
||||
log,
|
||||
|
@ -75,6 +79,14 @@ impl Server {
|
|||
self.signal("SIGINT")
|
||||
}
|
||||
|
||||
pub fn restart(&self) -> Result<()> {
|
||||
if self.restarting.swap(true, Ordering::AcqRel) {
|
||||
return Err(Error::Err("Restart already in progress".into()));
|
||||
}
|
||||
|
||||
self.shutdown()
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) -> Result<()> {
|
||||
if self.stopping.swap(true, Ordering::AcqRel) {
|
||||
return Err(Error::Err("Shutdown already in progress".into()));
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
pub(crate) mod clap;
|
||||
mod mods;
|
||||
mod restart;
|
||||
mod server;
|
||||
mod signal;
|
||||
|
||||
extern crate conduit_core as conduit;
|
||||
|
||||
use std::{cmp, sync::Arc, time::Duration};
|
||||
use std::{
|
||||
cmp,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use conduit::{debug_info, error, utils::available_parallelism, Error, Result};
|
||||
use server::Server;
|
||||
|
@ -32,8 +37,13 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// explicit drop here to trace thread and tls dtors
|
||||
drop(runtime);
|
||||
debug_info!("Exit");
|
||||
|
||||
#[cfg(unix)]
|
||||
if server.server.restarting.load(Ordering::Acquire) {
|
||||
restart::restart();
|
||||
}
|
||||
|
||||
debug_info!("Exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#![cfg(unix)]
|
||||
|
||||
use std::{env, os::unix::process::CommandExt, process::Command};
|
||||
|
||||
use conduit::{debug, info};
|
||||
|
||||
pub(super) fn restart() -> ! {
|
||||
let exe = env::current_exe().expect("program path must be identified and available");
|
||||
let envs = env::vars();
|
||||
let args = env::args().skip(1);
|
||||
debug!(?exe, ?args, ?envs, "Restart");
|
||||
|
||||
info!("Restart");
|
||||
|
||||
let error = Command::new(exe).args(args).envs(envs).exec();
|
||||
panic!("{error:?}");
|
||||
}
|
Loading…
Reference in New Issue