feat: implement backup layers using meta manager
							parent
							
								
									a236c36a4f
								
							
						
					
					
						commit
						29636ffcdb
					
				|  | @ -0,0 +1,46 @@ | ||||||
|  | use std::error::Error; | ||||||
|  | use std::fmt; | ||||||
|  | use std::str::FromStr; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub struct ManagerConfig { | ||||||
|  |     pub name: String, | ||||||
|  |     pub frequency: u32, | ||||||
|  |     pub chain_len: u64, | ||||||
|  |     pub chains: u64, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct ParseManagerConfigErr; | ||||||
|  | 
 | ||||||
|  | impl Error for ParseManagerConfigErr {} | ||||||
|  | 
 | ||||||
|  | impl fmt::Display for ParseManagerConfigErr { | ||||||
|  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|  |         write!(f, "parse manager config err") | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl FromStr for ManagerConfig { | ||||||
|  |     type Err = ParseManagerConfigErr; | ||||||
|  | 
 | ||||||
|  |     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||
|  |         let splits: Vec<&str> = s.split(',').collect(); | ||||||
|  | 
 | ||||||
|  |         if let [name, frequency, chains, chain_len] = splits[..] { | ||||||
|  |             let name: String = name.parse().map_err(|_| ParseManagerConfigErr)?; | ||||||
|  |             let frequency: u32 = frequency.parse().map_err(|_| ParseManagerConfigErr)?; | ||||||
|  |             let chains: u64 = chains.parse().map_err(|_| ParseManagerConfigErr)?; | ||||||
|  |             let chain_len: u64 = chain_len.parse().map_err(|_| ParseManagerConfigErr)?; | ||||||
|  | 
 | ||||||
|  |             Ok(ManagerConfig { | ||||||
|  |                 name, | ||||||
|  |                 chains, | ||||||
|  |                 chain_len, | ||||||
|  |                 frequency, | ||||||
|  |             }) | ||||||
|  |         } else { | ||||||
|  |             Err(ParseManagerConfigErr) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,83 @@ | ||||||
|  | use super::{Manager, ManagerConfig}; | ||||||
|  | use chrono::Utc; | ||||||
|  | use serde::Deserialize; | ||||||
|  | use serde::Serialize; | ||||||
|  | use std::io; | ||||||
|  | use std::path::PathBuf; | ||||||
|  | 
 | ||||||
|  | pub struct MetaManager<T> | ||||||
|  | where | ||||||
|  |     T: Clone + Serialize + for<'de> Deserialize<'de>, | ||||||
|  | { | ||||||
|  |     backup_dir: PathBuf, | ||||||
|  |     config_dir: PathBuf, | ||||||
|  |     world_dir: PathBuf, | ||||||
|  |     default_metadata: T, | ||||||
|  |     managers: Vec<Manager<T>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T> MetaManager<T> | ||||||
|  | where | ||||||
|  |     T: Clone + Serialize + for<'de> Deserialize<'de>, | ||||||
|  | { | ||||||
|  |     pub fn new<P1: Into<PathBuf>, P2: Into<PathBuf>, P3: Into<PathBuf>>( | ||||||
|  |         backup_dir: P1, | ||||||
|  |         config_dir: P2, | ||||||
|  |         world_dir: P3, | ||||||
|  |         default_metadata: T, | ||||||
|  |     ) -> Self { | ||||||
|  |         MetaManager { | ||||||
|  |             backup_dir: backup_dir.into(), | ||||||
|  |             config_dir: config_dir.into(), | ||||||
|  |             world_dir: world_dir.into(), | ||||||
|  |             default_metadata, | ||||||
|  |             managers: Vec::new(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn add(&mut self, config: &ManagerConfig) -> io::Result<()> { | ||||||
|  |         // Backup dir itself should exist, but we control its contents, so we can create
 | ||||||
|  |         // separate directories for each layer
 | ||||||
|  |         let path = self.backup_dir.join(&config.name); | ||||||
|  |         std::fs::create_dir(&path)?; | ||||||
|  | 
 | ||||||
|  |         let mut manager = Manager::new( | ||||||
|  |             path, | ||||||
|  |             self.config_dir.clone(), | ||||||
|  |             self.world_dir.clone(), | ||||||
|  |             self.default_metadata.clone(), | ||||||
|  |             config.chain_len, | ||||||
|  |             config.chains, | ||||||
|  |             chrono::Duration::minutes(config.frequency.into()), | ||||||
|  |         ); | ||||||
|  |         manager.load()?; | ||||||
|  |         self.managers.push(manager); | ||||||
|  | 
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn add_all(&mut self, configs: &Vec<ManagerConfig>) -> io::Result<()> { | ||||||
|  |         for config in configs { | ||||||
|  |             self.add(config)?; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn next_scheduled_time(&self) -> Option<chrono::DateTime<Utc>> { | ||||||
|  |         self.managers.iter().map(|m| m.next_scheduled_time()).min() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn perform_backup_cycle(&mut self) -> io::Result<()> { | ||||||
|  |         if let Some(manager) = self | ||||||
|  |             .managers | ||||||
|  |             .iter_mut() | ||||||
|  |             .min_by_key(|m| m.next_scheduled_time()) | ||||||
|  |         { | ||||||
|  |             manager.create_backup()?; | ||||||
|  |             manager.remove_old_backups() | ||||||
|  |         } else { | ||||||
|  |             Ok(()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,3 +1,9 @@ | ||||||
|  | mod config; | ||||||
|  | mod meta; | ||||||
|  | 
 | ||||||
|  | pub use config::ManagerConfig; | ||||||
|  | pub use meta::MetaManager; | ||||||
|  | 
 | ||||||
| use super::Backup; | use super::Backup; | ||||||
| use chrono::Utc; | use chrono::Utc; | ||||||
| use serde::Deserialize; | use serde::Deserialize; | ||||||
|  | @ -26,7 +32,6 @@ where | ||||||
| { | { | ||||||
|     const METADATA_FILE: &str = "alex.json"; |     const METADATA_FILE: &str = "alex.json"; | ||||||
| 
 | 
 | ||||||
|     /// Initialize a new instance of a `BackupManager`.
 |  | ||||||
|     pub fn new<P1: Into<PathBuf>, P2: Into<PathBuf>, P3: Into<PathBuf>>( |     pub fn new<P1: Into<PathBuf>, P2: Into<PathBuf>, P3: Into<PathBuf>>( | ||||||
|         backup_dir: P1, |         backup_dir: P1, | ||||||
|         config_dir: P2, |         config_dir: P2, | ||||||
|  | @ -1,9 +1,11 @@ | ||||||
| mod delta; | mod delta; | ||||||
| mod manager; | pub mod manager; | ||||||
| mod path; | mod path; | ||||||
| 
 | 
 | ||||||
| use delta::Delta; | use delta::Delta; | ||||||
| pub use manager::Manager; | pub use manager::Manager; | ||||||
|  | pub use manager::ManagerConfig; | ||||||
|  | pub use manager::MetaManager; | ||||||
| 
 | 
 | ||||||
| use chrono::Utc; | use chrono::Utc; | ||||||
| use flate2::write::GzEncoder; | use flate2::write::GzEncoder; | ||||||
|  |  | ||||||
							
								
								
									
										76
									
								
								src/cli.rs
								
								
								
								
							
							
						
						
									
										76
									
								
								src/cli.rs
								
								
								
								
							|  | @ -1,52 +1,7 @@ | ||||||
|  | use crate::backup::ManagerConfig; | ||||||
| use crate::server::ServerType; | use crate::server::ServerType; | ||||||
| use clap::{Args, Parser, Subcommand}; | use clap::{Args, Parser, Subcommand}; | ||||||
| use std::error::Error; |  | ||||||
| use std::fmt; |  | ||||||
| use std::path::PathBuf; | use std::path::PathBuf; | ||||||
| use std::str::FromStr; |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, Debug)] |  | ||||||
| pub struct ManagerConfig { |  | ||||||
|     name: String, |  | ||||||
|     frequency: u32, |  | ||||||
|     chain_len: u64, |  | ||||||
|     chains: u64, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct ParseManagerConfigErr; |  | ||||||
| 
 |  | ||||||
| impl Error for ParseManagerConfigErr {} |  | ||||||
| 
 |  | ||||||
| impl fmt::Display for ParseManagerConfigErr { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |  | ||||||
|         write!(f, "parse manager config err") |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl FromStr for ManagerConfig { |  | ||||||
|     type Err = ParseManagerConfigErr; |  | ||||||
| 
 |  | ||||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { |  | ||||||
|         let splits: Vec<&str> = s.split(',').collect(); |  | ||||||
| 
 |  | ||||||
|         if let [name, frequency, chains, chain_len] = splits[..] { |  | ||||||
|             let name: String = name.parse().map_err(|_| ParseManagerConfigErr)?; |  | ||||||
|             let frequency: u32 = frequency.parse().map_err(|_| ParseManagerConfigErr)?; |  | ||||||
|             let chains: u64 = chains.parse().map_err(|_| ParseManagerConfigErr)?; |  | ||||||
|             let chain_len: u64 = chain_len.parse().map_err(|_| ParseManagerConfigErr)?; |  | ||||||
| 
 |  | ||||||
|             Ok(ManagerConfig { |  | ||||||
|                 name, |  | ||||||
|                 chains, |  | ||||||
|                 chain_len, |  | ||||||
|                 frequency, |  | ||||||
|             }) |  | ||||||
|         } else { |  | ||||||
|             Err(ParseManagerConfigErr) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #[derive(Parser)] | #[derive(Parser)] | ||||||
| #[command(author, version, about, long_about = None)] | #[command(author, version, about, long_about = None)] | ||||||
|  | @ -86,35 +41,6 @@ pub struct Cli { | ||||||
|     #[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>, | ||||||
| 
 | 
 | ||||||
|     /// Length of a backup chain
 |  | ||||||
|     #[arg(
 |  | ||||||
|         short = 'l', |  | ||||||
|         long, |  | ||||||
|         default_value_t = 4, |  | ||||||
|         env = "ALEX_CHAIN_LEN", |  | ||||||
|         global = true |  | ||||||
|     )] |  | ||||||
|     pub chain_len: u64, |  | ||||||
|     /// How many backup chains to keep
 |  | ||||||
|     #[arg(
 |  | ||||||
|         short = 'n', |  | ||||||
|         long, |  | ||||||
|         default_value_t = 7, |  | ||||||
|         env = "ALEX_CHAINS", |  | ||||||
|         global = true |  | ||||||
|     )] |  | ||||||
|     pub chains: u64, |  | ||||||
| 
 |  | ||||||
|     /// How frequently to perform a backup, in minutes; 0 to disable.
 |  | ||||||
|     #[arg(
 |  | ||||||
|         short = 't', |  | ||||||
|         long, |  | ||||||
|         default_value_t = 0, |  | ||||||
|         env = "ALEX_FREQUENCY", |  | ||||||
|         global = true |  | ||||||
|     )] |  | ||||||
|     pub frequency: u32, |  | ||||||
| 
 |  | ||||||
|     /// Type of server
 |     /// Type of server
 | ||||||
|     #[arg(long, default_value = "unknown", env = "ALEX_SERVER", global = true)] |     #[arg(long, default_value = "unknown", env = "ALEX_SERVER", global = true)] | ||||||
|     pub server: ServerType, |     pub server: ServerType, | ||||||
|  |  | ||||||
							
								
								
									
										43
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										43
									
								
								src/main.rs
								
								
								
								
							|  | @ -5,7 +5,7 @@ mod signals; | ||||||
| mod stdin; | mod stdin; | ||||||
| 
 | 
 | ||||||
| use clap::Parser; | use clap::Parser; | ||||||
| use cli::{BackupArgs, Cli, Commands, RunArgs}; | use cli::{Cli, Commands, RunArgs}; | ||||||
| use std::io; | use std::io; | ||||||
| use std::sync::{Arc, Mutex}; | use std::sync::{Arc, Mutex}; | ||||||
| 
 | 
 | ||||||
|  | @ -13,7 +13,7 @@ fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) { | ||||||
|     loop { |     loop { | ||||||
|         let next_scheduled_time = { |         let next_scheduled_time = { | ||||||
|             let server = counter.lock().unwrap(); |             let server = counter.lock().unwrap(); | ||||||
|             server.backups.next_scheduled_time() |             server.backups.next_scheduled_time().unwrap() | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let now = chrono::offset::Utc::now(); |         let now = chrono::offset::Utc::now(); | ||||||
|  | @ -39,11 +39,9 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { | ||||||
|         .config(cli.config.clone()) |         .config(cli.config.clone()) | ||||||
|         .world(cli.world.clone()) |         .world(cli.world.clone()) | ||||||
|         .backup(cli.backup.clone()) |         .backup(cli.backup.clone()) | ||||||
|  |         .managers(cli.layers.clone()) | ||||||
|         .xms(args.xms) |         .xms(args.xms) | ||||||
|         .xmx(args.xmx) |         .xmx(args.xmx); | ||||||
|         .chain_len(cli.chain_len) |  | ||||||
|         .chains_to_keep(cli.chains) |  | ||||||
|         .frequency(cli.frequency); |  | ||||||
|     cmd.canonicalize()?; |     cmd.canonicalize()?; | ||||||
| 
 | 
 | ||||||
|     if args.dry { |     if args.dry { | ||||||
|  | @ -54,7 +52,7 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { | ||||||
| 
 | 
 | ||||||
|     let counter = Arc::new(Mutex::new(cmd.spawn()?)); |     let counter = Arc::new(Mutex::new(cmd.spawn()?)); | ||||||
| 
 | 
 | ||||||
|     if cli.frequency > 0 { |     if !cli.layers.is_empty() { | ||||||
|         let clone = Arc::clone(&counter); |         let clone = Arc::clone(&counter); | ||||||
|         std::thread::spawn(move || backups_thread(clone)); |         std::thread::spawn(move || backups_thread(clone)); | ||||||
|     } |     } | ||||||
|  | @ -67,32 +65,23 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { | ||||||
|     signals::handle_signals(&mut signals, counter) |     signals::handle_signals(&mut signals, counter) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> { | // 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);
 | ||||||
|  | //     meta.add_all(&cli.layers)?;
 | ||||||
| 
 | 
 | ||||||
|     let mut manager = backup::Manager::new( | //     manager.create_backup()?;
 | ||||||
|         cli.backup.clone(), | //     manager.remove_old_backups()
 | ||||||
|         cli.config.clone(), | // }
 | ||||||
|         cli.world.clone(), |  | ||||||
|         metadata, |  | ||||||
|         cli.chain_len, |  | ||||||
|         cli.chains, |  | ||||||
|         chrono::Duration::minutes(cli.frequency.into()), |  | ||||||
|     ); |  | ||||||
|     manager.load()?; |  | ||||||
| 
 |  | ||||||
|     manager.create_backup()?; |  | ||||||
|     manager.remove_old_backups() |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| fn main() -> io::Result<()> { | fn main() -> io::Result<()> { | ||||||
|     let cli = Cli::parse(); |     let cli = Cli::parse(); | ||||||
| 
 | 
 | ||||||
|     match &cli.command { |     match &cli.command { | ||||||
|         Commands::Run(args) => command_run(&cli, args), |         Commands::Run(args) => command_run(&cli, args), | ||||||
|         Commands::Backup(args) => commands_backup(&cli, args), |         Commands::Backup(_) => Ok(()), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,40 +1,12 @@ | ||||||
| use crate::backup::Manager as BackupManager; | use crate::backup::ManagerConfig; | ||||||
| use crate::server::ServerProcess; | use crate::backup::MetaManager; | ||||||
| use clap::ValueEnum; | use crate::server::{Metadata, ServerProcess, ServerType}; | ||||||
| use serde::{Deserialize, Serialize}; |  | ||||||
| use std::fmt; | use std::fmt; | ||||||
| use std::fs::File; | use std::fs::File; | ||||||
| use std::io::Write; | use std::io::Write; | ||||||
| use std::path::{Path, PathBuf}; | use std::path::{Path, PathBuf}; | ||||||
| use std::process::{Command, Stdio}; | use std::process::{Command, Stdio}; | ||||||
| 
 | 
 | ||||||
| #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)] |  | ||||||
| pub enum ServerType { |  | ||||||
|     Unknown, |  | ||||||
|     Paper, |  | ||||||
|     Forge, |  | ||||||
|     Vanilla, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl fmt::Display for ServerType { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |  | ||||||
|         let s = match self { |  | ||||||
|             ServerType::Unknown => "Unknown", |  | ||||||
|             ServerType::Paper => "PaperMC", |  | ||||||
|             ServerType::Forge => "Forge", |  | ||||||
|             ServerType::Vanilla => "Vanilla", |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         write!(f, "{}", s) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, Serialize, Deserialize)] |  | ||||||
| pub struct Metadata { |  | ||||||
|     pub server_type: ServerType, |  | ||||||
|     pub server_version: String, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct ServerCommand { | pub struct ServerCommand { | ||||||
|     type_: ServerType, |     type_: ServerType, | ||||||
|     version: String, |     version: String, | ||||||
|  | @ -45,9 +17,7 @@ pub struct ServerCommand { | ||||||
|     backup_dir: PathBuf, |     backup_dir: PathBuf, | ||||||
|     xms: u64, |     xms: u64, | ||||||
|     xmx: u64, |     xmx: u64, | ||||||
|     chain_len: u64, |     managers: Vec<ManagerConfig>, | ||||||
|     chains_to_keep: u64, |  | ||||||
|     frequency: u32, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ServerCommand { | impl ServerCommand { | ||||||
|  | @ -62,9 +32,7 @@ impl ServerCommand { | ||||||
|             backup_dir: PathBuf::from("backups"), |             backup_dir: PathBuf::from("backups"), | ||||||
|             xms: 1024, |             xms: 1024, | ||||||
|             xmx: 2048, |             xmx: 2048, | ||||||
|             chain_len: 4, |             managers: Vec::new(), | ||||||
|             chains_to_keep: 7, |  | ||||||
|             frequency: 0, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -105,18 +73,9 @@ impl ServerCommand { | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn chain_len(mut self, v: u64) -> Self { |     pub fn managers(mut self, configs: Vec<ManagerConfig>) -> Self { | ||||||
|         self.chain_len = v; |         self.managers = configs; | ||||||
|         self |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     pub fn chains_to_keep(mut self, v: u64) -> Self { |  | ||||||
|         self.chains_to_keep = v; |  | ||||||
|         self |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn frequency(mut self, v: u32) -> Self { |  | ||||||
|         self.frequency = v; |  | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -207,22 +166,19 @@ impl ServerCommand { | ||||||
|             server_type: self.type_, |             server_type: self.type_, | ||||||
|             server_version: self.version.clone(), |             server_version: self.version.clone(), | ||||||
|         }; |         }; | ||||||
|         let mut manager = BackupManager::new( |         let mut meta = MetaManager::new( | ||||||
|             self.backup_dir.clone(), |             self.backup_dir.clone(), | ||||||
|             self.config_dir.clone(), |             self.config_dir.clone(), | ||||||
|             self.world_dir.clone(), |             self.world_dir.clone(), | ||||||
|             metadata, |             metadata, | ||||||
|             self.chain_len, |  | ||||||
|             self.chains_to_keep, |  | ||||||
|             chrono::Duration::minutes(self.frequency.into()), |  | ||||||
|         ); |         ); | ||||||
|         manager.load()?; |         meta.add_all(&self.managers)?; | ||||||
| 
 | 
 | ||||||
|         let mut cmd = self.create_cmd(); |         let mut cmd = self.create_cmd(); | ||||||
|         self.accept_eula()?; |         self.accept_eula()?; | ||||||
|         let child = cmd.spawn()?; |         let child = cmd.spawn()?; | ||||||
| 
 | 
 | ||||||
|         Ok(ServerProcess::new(manager, child)) |         Ok(ServerProcess::new(meta, child)) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,36 @@ | ||||||
| mod command; | mod command; | ||||||
| mod process; | mod process; | ||||||
| 
 | 
 | ||||||
| pub use command::{Metadata, ServerCommand, ServerType}; | pub use command::ServerCommand; | ||||||
| pub use process::ServerProcess; | pub use process::ServerProcess; | ||||||
|  | 
 | ||||||
|  | use clap::ValueEnum; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | use std::fmt; | ||||||
|  | 
 | ||||||
|  | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)] | ||||||
|  | pub enum ServerType { | ||||||
|  |     Unknown, | ||||||
|  |     Paper, | ||||||
|  |     Forge, | ||||||
|  |     Vanilla, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl fmt::Display for ServerType { | ||||||
|  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|  |         let s = match self { | ||||||
|  |             ServerType::Unknown => "Unknown", | ||||||
|  |             ServerType::Paper => "PaperMC", | ||||||
|  |             ServerType::Forge => "Forge", | ||||||
|  |             ServerType::Vanilla => "Vanilla", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         write!(f, "{}", s) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Serialize, Deserialize)] | ||||||
|  | pub struct Metadata { | ||||||
|  |     pub server_type: ServerType, | ||||||
|  |     pub server_version: String, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,15 +1,15 @@ | ||||||
| use crate::backup::Manager as BackupManager; | use crate::backup::MetaManager; | ||||||
| use crate::server::Metadata; | use crate::server::Metadata; | ||||||
| use std::io::Write; | use std::io::Write; | ||||||
| use std::process::Child; | use std::process::Child; | ||||||
| 
 | 
 | ||||||
| pub struct ServerProcess { | pub struct ServerProcess { | ||||||
|     child: Child, |     child: Child, | ||||||
|     pub backups: BackupManager<Metadata>, |     pub backups: MetaManager<Metadata>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ServerProcess { | impl ServerProcess { | ||||||
|     pub fn new(manager: BackupManager<Metadata>, child: Child) -> ServerProcess { |     pub fn new(manager: MetaManager<Metadata>, child: Child) -> ServerProcess { | ||||||
|         ServerProcess { |         ServerProcess { | ||||||
|             child, |             child, | ||||||
|             backups: manager, |             backups: manager, | ||||||
|  | @ -59,16 +59,12 @@ impl ServerProcess { | ||||||
|         std::thread::sleep(std::time::Duration::from_secs(10)); |         std::thread::sleep(std::time::Duration::from_secs(10)); | ||||||
| 
 | 
 | ||||||
|         let start_time = chrono::offset::Utc::now(); |         let start_time = chrono::offset::Utc::now(); | ||||||
|         let res = self.backups.create_backup(); |         let res = self.backups.perform_backup_cycle(); | ||||||
| 
 | 
 | ||||||
|         // The server's save feature needs to be enabled again even if the archive failed to create
 |         // The server's save feature needs to be enabled again even if the archive failed to create
 | ||||||
|         self.custom("save-on")?; |         self.custom("save-on")?; | ||||||
|         self.custom("save-all")?; |         self.custom("save-all")?; | ||||||
| 
 | 
 | ||||||
|         if res.is_ok() { |  | ||||||
|             self.backups.remove_old_backups()?; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let duration = chrono::offset::Utc::now() - start_time; |         let duration = chrono::offset::Utc::now() - start_time; | ||||||
|         let duration_str = format!( |         let duration_str = format!( | ||||||
|             "{}m{}s", |             "{}m{}s", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue