refactor: structure code to allow expanding cli functionality
parent
d5cea49c8b
commit
1cfe13674d
|
@ -0,0 +1,12 @@
|
||||||
|
use clap::{Args, Subcommand};
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum BackupCommands {
|
||||||
|
List,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
pub struct BackupArgs {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: BackupCommands,
|
||||||
|
}
|
|
@ -1,8 +1,23 @@
|
||||||
|
mod backup;
|
||||||
|
mod run;
|
||||||
|
|
||||||
|
pub use backup::{BackupArgs, BackupCommands};
|
||||||
|
pub use run::RunArgs;
|
||||||
|
|
||||||
use crate::backup::ManagerConfig;
|
use crate::backup::ManagerConfig;
|
||||||
use crate::server::ServerType;
|
use crate::server::ServerType;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Commands {
|
||||||
|
/// Run the server
|
||||||
|
Run(RunArgs),
|
||||||
|
/// Interact with the backup system without starting a server
|
||||||
|
Backup(BackupArgs),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
|
@ -36,7 +51,7 @@ pub struct Cli {
|
||||||
)]
|
)]
|
||||||
pub backup: PathBuf,
|
pub backup: PathBuf,
|
||||||
|
|
||||||
/// What backup layers to employ, provided as a list of tuples name,frequency,chain_len,chains
|
/// What backup layers to employ, provided as a list of tuples name,frequency,chains,chain_len
|
||||||
/// delimited by semicolons (;).
|
/// delimited by semicolons (;).
|
||||||
#[arg(long, env = "ALEX_LAYERS", global = true, value_delimiter = ';')]
|
#[arg(long, env = "ALEX_LAYERS", global = true, value_delimiter = ';')]
|
||||||
pub layers: Vec<ManagerConfig>,
|
pub layers: Vec<ManagerConfig>,
|
||||||
|
@ -49,42 +64,11 @@ pub struct Cli {
|
||||||
pub server_version: String,
|
pub server_version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
impl Cli {
|
||||||
pub enum Commands {
|
pub fn run(&self) -> io::Result<()> {
|
||||||
/// Run the server
|
match &self.command {
|
||||||
Run(RunArgs),
|
Commands::Run(args) => args.run(self),
|
||||||
/// Create a new backup of the server. This command should only be used when the server is not
|
Commands::Backup(_) => Ok(()),
|
||||||
/// running.
|
}
|
||||||
Backup(BackupArgs),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
|
||||||
pub struct RunArgs {
|
|
||||||
/// Server jar to execute
|
|
||||||
#[arg(
|
|
||||||
long,
|
|
||||||
value_name = "JAR_PATH",
|
|
||||||
default_value = "server.jar",
|
|
||||||
env = "ALEX_JAR"
|
|
||||||
)]
|
|
||||||
pub jar: PathBuf,
|
|
||||||
|
|
||||||
/// Java command to run the server jar with
|
|
||||||
#[arg(long, value_name = "JAVA_CMD", default_value_t = String::from("java"), env = "ALEX_JAVA")]
|
|
||||||
pub java: String,
|
|
||||||
|
|
||||||
/// XMS value in megabytes for the server instance
|
|
||||||
#[arg(long, default_value_t = 1024, env = "ALEX_XMS")]
|
|
||||||
pub xms: u64,
|
|
||||||
/// XMX value in megabytes for the server instance
|
|
||||||
#[arg(long, default_value_t = 2048, env = "ALEX_XMX")]
|
|
||||||
pub xmx: u64,
|
|
||||||
|
|
||||||
/// Don't actually run the server, but simply output the server configuration that would have
|
|
||||||
/// been ran
|
|
||||||
#[arg(short, long, default_value_t = false)]
|
|
||||||
pub dry: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
|
||||||
pub struct BackupArgs {}
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
use crate::cli::Cli;
|
||||||
|
use crate::server;
|
||||||
|
use crate::signals;
|
||||||
|
use crate::stdin;
|
||||||
|
use clap::Args;
|
||||||
|
use std::io;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
pub struct RunArgs {
|
||||||
|
/// Server jar to execute
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
value_name = "JAR_PATH",
|
||||||
|
default_value = "server.jar",
|
||||||
|
env = "ALEX_JAR"
|
||||||
|
)]
|
||||||
|
pub jar: PathBuf,
|
||||||
|
|
||||||
|
/// Java command to run the server jar with
|
||||||
|
#[arg(long, value_name = "JAVA_CMD", default_value_t = String::from("java"), env = "ALEX_JAVA")]
|
||||||
|
pub java: String,
|
||||||
|
|
||||||
|
/// XMS value in megabytes for the server instance
|
||||||
|
#[arg(long, default_value_t = 1024, env = "ALEX_XMS")]
|
||||||
|
pub xms: u64,
|
||||||
|
/// XMX value in megabytes for the server instance
|
||||||
|
#[arg(long, default_value_t = 2048, env = "ALEX_XMX")]
|
||||||
|
pub xmx: u64,
|
||||||
|
|
||||||
|
/// Don't actually run the server, but simply output the server configuration that would have
|
||||||
|
/// been ran
|
||||||
|
#[arg(short, long, default_value_t = false)]
|
||||||
|
pub dry: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) {
|
||||||
|
loop {
|
||||||
|
let next_scheduled_time = {
|
||||||
|
let server = counter.lock().unwrap();
|
||||||
|
server.backups.next_scheduled_time().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let now = chrono::offset::Utc::now();
|
||||||
|
if next_scheduled_time > now {
|
||||||
|
std::thread::sleep((next_scheduled_time - now).to_std().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut server = counter.lock().unwrap();
|
||||||
|
|
||||||
|
// We explicitely ignore the error here, as we don't want the thread to fail
|
||||||
|
let _ = server.backup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RunArgs {
|
||||||
|
pub fn run(&self, cli: &Cli) -> io::Result<()> {
|
||||||
|
let (_, mut signals) = signals::install_signal_handlers()?;
|
||||||
|
|
||||||
|
let mut cmd = server::ServerCommand::new(cli.server, &cli.server_version)
|
||||||
|
.java(&self.java)
|
||||||
|
.jar(self.jar.clone())
|
||||||
|
.config(cli.config.clone())
|
||||||
|
.world(cli.world.clone())
|
||||||
|
.backup(cli.backup.clone())
|
||||||
|
.managers(cli.layers.clone())
|
||||||
|
.xms(self.xms)
|
||||||
|
.xmx(self.xmx);
|
||||||
|
cmd.canonicalize()?;
|
||||||
|
|
||||||
|
if self.dry {
|
||||||
|
print!("{}", cmd);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let counter = Arc::new(Mutex::new(cmd.spawn()?));
|
||||||
|
|
||||||
|
if !cli.layers.is_empty() {
|
||||||
|
let clone = Arc::clone(&counter);
|
||||||
|
std::thread::spawn(move || backups_thread(clone));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn thread that handles the main stdin loop
|
||||||
|
let clone = Arc::clone(&counter);
|
||||||
|
std::thread::spawn(move || stdin::handle_stdin(clone));
|
||||||
|
|
||||||
|
// Signal handler loop exits the process when necessary
|
||||||
|
signals::handle_signals(&mut signals, counter)
|
||||||
|
}
|
||||||
|
}
|
81
src/main.rs
81
src/main.rs
|
@ -4,84 +4,31 @@ mod server;
|
||||||
mod signals;
|
mod signals;
|
||||||
mod stdin;
|
mod stdin;
|
||||||
|
|
||||||
|
use crate::cli::Cli;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::{Cli, Commands, RunArgs};
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) {
|
// fn commands_backup(cli: &Cli, args: &BackupArgs) -> io::Result<()> {
|
||||||
loop {
|
|
||||||
let next_scheduled_time = {
|
|
||||||
let server = counter.lock().unwrap();
|
|
||||||
server.backups.next_scheduled_time().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let now = chrono::offset::Utc::now();
|
|
||||||
if next_scheduled_time > now {
|
|
||||||
std::thread::sleep((next_scheduled_time - now).to_std().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut server = counter.lock().unwrap();
|
|
||||||
|
|
||||||
// We explicitely ignore the error here, as we don't want the thread to fail
|
|
||||||
let _ = server.backup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
|
|
||||||
let (_, mut signals) = signals::install_signal_handlers()?;
|
|
||||||
|
|
||||||
let mut cmd = server::ServerCommand::new(cli.server, &cli.server_version)
|
|
||||||
.java(&args.java)
|
|
||||||
.jar(args.jar.clone())
|
|
||||||
.config(cli.config.clone())
|
|
||||||
.world(cli.world.clone())
|
|
||||||
.backup(cli.backup.clone())
|
|
||||||
.managers(cli.layers.clone())
|
|
||||||
.xms(args.xms)
|
|
||||||
.xmx(args.xmx);
|
|
||||||
cmd.canonicalize()?;
|
|
||||||
|
|
||||||
if args.dry {
|
|
||||||
print!("{}", cmd);
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let counter = Arc::new(Mutex::new(cmd.spawn()?));
|
|
||||||
|
|
||||||
if !cli.layers.is_empty() {
|
|
||||||
let clone = Arc::clone(&counter);
|
|
||||||
std::thread::spawn(move || backups_thread(clone));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn thread that handles the main stdin loop
|
|
||||||
let clone = Arc::clone(&counter);
|
|
||||||
std::thread::spawn(move || stdin::handle_stdin(clone));
|
|
||||||
|
|
||||||
// Signal handler loop exits the process when necessary
|
|
||||||
signals::handle_signals(&mut signals, counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> {
|
|
||||||
// let metadata = server::Metadata {
|
// let metadata = server::Metadata {
|
||||||
// server_type: cli.server,
|
// server_type: cli.server,
|
||||||
// server_version: cli.server_version.clone(),
|
// server_version: cli.server_version.clone(),
|
||||||
// };
|
// };
|
||||||
// let mut meta = MetaManager::new(cli.backup, cli.config, cli.world, metadata);
|
// let dirs = vec![
|
||||||
|
// (PathBuf::from("config"), cli.config.clone()),
|
||||||
|
// (PathBuf::from("worlds"), cli.world.clone()),
|
||||||
|
// ];
|
||||||
|
// let mut meta = MetaManager::new(cli.backup.clone(), dirs, metadata);
|
||||||
// meta.add_all(&cli.layers)?;
|
// meta.add_all(&cli.layers)?;
|
||||||
|
|
||||||
// manager.create_backup()?;
|
// match &args.command {
|
||||||
// manager.remove_old_backups()
|
// BackupCommands::List => ()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // manager.create_backup()?;
|
||||||
|
// // manager.remove_old_backups()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
cli.run()
|
||||||
match &cli.command {
|
|
||||||
Commands::Run(args) => command_run(&cli, args),
|
|
||||||
Commands::Backup(_) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue