refactor: let backup manager calculate next backup time
ci/woodpecker/push/clippy Pipeline was successful Details
ci/woodpecker/push/lint Pipeline was successful Details
ci/woodpecker/push/build Pipeline was successful Details

export-backup
Jef Roosens 2023-06-22 21:15:40 +02:00
parent 4e8d0a8d25
commit 0a459ee30b
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
6 changed files with 54 additions and 14 deletions

View File

@ -1,3 +1,3 @@
[alias]
runs = "run -- run paper 1.19.4-550 --config data/config --backup data/backups --world data/worlds --jar paper-1.19.4-550.jar"
runs = "run -- run --config data/config --backup data/backups --world data/worlds --jar paper-1.19.4-550.jar --frequency 2"
runrs = "run --release -- paper 1.19.4-545 --config data/config --backup data/backups --world data/worlds --jar data/paper-1.19.4-525.jar"

View File

@ -1,4 +1,5 @@
use super::Backup;
use chrono::Utc;
use serde::Deserialize;
use serde::Serialize;
use std::fs::File;
@ -15,6 +16,7 @@ where
default_metadata: T,
chain_len: u64,
chains_to_keep: u64,
frequency: chrono::Duration,
chains: Vec<Vec<Backup<T>>>,
}
@ -32,6 +34,7 @@ where
metadata: T,
chain_len: u64,
chains_to_keep: u64,
frequency: chrono::Duration,
) -> Self {
Self {
backup_dir: backup_dir.into(),
@ -40,6 +43,7 @@ where
default_metadata: metadata,
chain_len,
chains_to_keep,
frequency,
chains: Vec::new(),
}
}
@ -137,4 +141,16 @@ where
Ok(())
}
/// Calculate the next time a backup should be created. If no backup has been created yet, it
/// will return now.
pub fn next_scheduled_time(&self) -> chrono::DateTime<Utc> {
if let Some(last_chain) = self.chains.last() {
if let Some(last_backup) = last_chain.last() {
return last_backup.start_time + self.frequency;
}
}
chrono::offset::Utc::now()
}
}

View File

@ -53,11 +53,22 @@ pub struct Cli {
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
#[arg(long, default_value = "unknown", env = "ALEX_SERVER")]
#[arg(long, default_value = "unknown", env = "ALEX_SERVER", global = true)]
pub server: ServerType,
/// Version string for the server, e.g. 1.19.4-545
#[arg(long, default_value = "", env = "ALEX_SERVER_VERSION")]
#[arg(long, default_value = "", env = "ALEX_SERVER_VERSION", global = true)]
pub server_version: String,
}
@ -92,10 +103,6 @@ pub struct RunArgs {
#[arg(long, default_value_t = 2048, env = "ALEX_XMX")]
pub xmx: u64,
/// How frequently to perform a backup, in minutes; 0 to disable.
#[arg(short = 't', long, default_value_t = 0, env = "ALEX_FREQUENCY")]
pub frequency: 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)]

View File

@ -9,9 +9,17 @@ use cli::{BackupArgs, Cli, Commands, RunArgs};
use std::io;
use std::sync::{Arc, Mutex};
fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>, frequency: u64) {
fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) {
loop {
std::thread::sleep(std::time::Duration::from_secs(frequency * 60));
let next_scheduled_time = {
let server = counter.lock().unwrap();
server.backups.next_scheduled_time()
};
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();
@ -34,7 +42,8 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
.xms(args.xms)
.xmx(args.xmx)
.chain_len(cli.chain_len)
.chains_to_keep(cli.chains);
.chains_to_keep(cli.chains)
.frequency(cli.frequency);
cmd.canonicalize()?;
if args.dry {
@ -45,10 +54,9 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
let counter = Arc::new(Mutex::new(cmd.spawn()?));
if args.frequency > 0 {
if cli.frequency > 0 {
let clone = Arc::clone(&counter);
let frequency = args.frequency;
std::thread::spawn(move || backups_thread(clone, frequency));
std::thread::spawn(move || backups_thread(clone));
}
// Spawn thread that handles the main stdin loop
@ -72,6 +80,7 @@ fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> {
metadata,
cli.chain_len,
cli.chains,
chrono::Duration::minutes(cli.frequency.into()),
);
manager.load()?;

View File

@ -47,6 +47,7 @@ pub struct ServerCommand {
xmx: u64,
chain_len: u64,
chains_to_keep: u64,
frequency: u32,
}
impl ServerCommand {
@ -63,6 +64,7 @@ impl ServerCommand {
xmx: 2048,
chain_len: 4,
chains_to_keep: 7,
frequency: 0,
}
}
@ -113,6 +115,11 @@ impl ServerCommand {
self
}
pub fn frequency(mut self, v: u32) -> Self {
self.frequency = v;
self
}
fn accept_eula(&self) -> std::io::Result<()> {
let mut eula_path = self.config_dir.clone();
eula_path.push("eula.txt");
@ -207,6 +214,7 @@ impl ServerCommand {
metadata,
self.chain_len,
self.chains_to_keep,
chrono::Duration::minutes(self.frequency.into()),
);
manager.load()?;

View File

@ -5,7 +5,7 @@ use std::process::Child;
pub struct ServerProcess {
child: Child,
backups: BackupManager<Metadata>,
pub backups: BackupManager<Metadata>,
}
impl ServerProcess {