add server restart support w/ admin command
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
2cb31275f0
commit
c6f4b20e17
5 changed files with 54 additions and 2 deletions
|
@ -49,6 +49,10 @@ pub(crate) enum ServerCommand {
|
||||||
/// - Hot-reload the server
|
/// - Hot-reload the server
|
||||||
Reload,
|
Reload,
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
/// - Restart the server
|
||||||
|
Restart,
|
||||||
|
|
||||||
/// - Shutdown the server
|
/// - Shutdown the server
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
}
|
||||||
|
@ -72,6 +76,8 @@ pub(crate) async fn process(command: ServerCommand, body: Vec<&str>) -> Result<R
|
||||||
} => admin_notice(body, message).await?,
|
} => admin_notice(body, message).await?,
|
||||||
#[cfg(conduit_mods)]
|
#[cfg(conduit_mods)]
|
||||||
ServerCommand::Reload => reload(body).await?,
|
ServerCommand::Reload => reload(body).await?,
|
||||||
|
#[cfg(unix)]
|
||||||
|
ServerCommand::Restart => restart(body).await?,
|
||||||
ServerCommand::Shutdown => shutdown(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..."))
|
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> {
|
pub(crate) async fn shutdown(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
warn!("shutdown command");
|
warn!("shutdown command");
|
||||||
services().server.shutdown()?;
|
services().server.shutdown()?;
|
||||||
|
|
|
@ -23,6 +23,9 @@ pub struct Server {
|
||||||
/// is an observable used on shutdown and modifying is not recommended.
|
/// is an observable used on shutdown and modifying is not recommended.
|
||||||
pub reloading: AtomicBool,
|
pub reloading: AtomicBool,
|
||||||
|
|
||||||
|
/// Restart desired; when true, restart it desired after shutdown.
|
||||||
|
pub restarting: AtomicBool,
|
||||||
|
|
||||||
/// Handle to the runtime
|
/// Handle to the runtime
|
||||||
pub runtime: Option<runtime::Handle>,
|
pub runtime: Option<runtime::Handle>,
|
||||||
|
|
||||||
|
@ -48,6 +51,7 @@ impl Server {
|
||||||
started: SystemTime::now(),
|
started: SystemTime::now(),
|
||||||
stopping: AtomicBool::new(false),
|
stopping: AtomicBool::new(false),
|
||||||
reloading: AtomicBool::new(false),
|
reloading: AtomicBool::new(false),
|
||||||
|
restarting: AtomicBool::new(false),
|
||||||
runtime,
|
runtime,
|
||||||
signal: broadcast::channel::<&'static str>(1).0,
|
signal: broadcast::channel::<&'static str>(1).0,
|
||||||
log,
|
log,
|
||||||
|
@ -75,6 +79,14 @@ impl Server {
|
||||||
self.signal("SIGINT")
|
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<()> {
|
pub fn shutdown(&self) -> Result<()> {
|
||||||
if self.stopping.swap(true, Ordering::AcqRel) {
|
if self.stopping.swap(true, Ordering::AcqRel) {
|
||||||
return Err(Error::Err("Shutdown already in progress".into()));
|
return Err(Error::Err("Shutdown already in progress".into()));
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
pub(crate) mod clap;
|
pub(crate) mod clap;
|
||||||
mod mods;
|
mod mods;
|
||||||
|
mod restart;
|
||||||
mod server;
|
mod server;
|
||||||
mod signal;
|
mod signal;
|
||||||
|
|
||||||
extern crate conduit_core as conduit;
|
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 conduit::{debug_info, error, utils::available_parallelism, Error, Result};
|
||||||
use server::Server;
|
use server::Server;
|
||||||
|
@ -32,8 +37,13 @@ fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
// explicit drop here to trace thread and tls dtors
|
// explicit drop here to trace thread and tls dtors
|
||||||
drop(runtime);
|
drop(runtime);
|
||||||
debug_info!("Exit");
|
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
if server.server.restarting.load(Ordering::Acquire) {
|
||||||
|
restart::restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_info!("Exit");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/main/restart.rs
Normal file
17
src/main/restart.rs
Normal file
|
@ -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…
Add table
Reference in a new issue