mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 06:35:16 +08:00
fix: harden official resource sync retries
This commit is contained in:
@@ -11,6 +11,7 @@ use std::time::Duration;
|
||||
const EXIT_ERROR: i32 = 1;
|
||||
const EXIT_LOCKED: i32 = 75;
|
||||
const DEFAULT_WATCH_INTERVAL_SECONDS: u64 = 60 * 60;
|
||||
const DEFAULT_ERROR_RETRY_SECONDS: u64 = 60;
|
||||
|
||||
fn main() {
|
||||
match run() {
|
||||
@@ -64,6 +65,7 @@ struct CliOptions {
|
||||
config: OfficialUpdateConfig,
|
||||
watch: bool,
|
||||
interval: Duration,
|
||||
error_retry_interval: Duration,
|
||||
quiet_up_to_date: bool,
|
||||
quiet_up_to_date_explicit: bool,
|
||||
}
|
||||
@@ -74,6 +76,7 @@ impl Default for CliOptions {
|
||||
config: OfficialUpdateConfig::default(),
|
||||
watch: false,
|
||||
interval: Duration::from_secs(DEFAULT_WATCH_INTERVAL_SECONDS),
|
||||
error_retry_interval: Duration::from_secs(DEFAULT_ERROR_RETRY_SECONDS),
|
||||
quiet_up_to_date: false,
|
||||
quiet_up_to_date_explicit: false,
|
||||
}
|
||||
@@ -87,8 +90,14 @@ fn run_watch(options: CliOptions) -> anyhow::Result<()> {
|
||||
if options.interval.is_zero() {
|
||||
return Err(anyhow::anyhow!("watch interval must be greater than zero"));
|
||||
}
|
||||
if options.error_retry_interval.is_zero() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"watch error retry interval must be greater than zero"
|
||||
));
|
||||
}
|
||||
let service = OfficialUpdateService::new();
|
||||
loop {
|
||||
let mut sleep_for = options.interval;
|
||||
match service.run(&options.config) {
|
||||
Ok(report) => {
|
||||
if should_print_status(report.update_status, options.quiet_up_to_date) {
|
||||
@@ -96,17 +105,18 @@ fn run_watch(options: CliOptions) -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
sleep_for = options.error_retry_interval;
|
||||
let payload = ErrorReport {
|
||||
status: "error",
|
||||
exit_code: EXIT_ERROR,
|
||||
error: error.to_string(),
|
||||
next_retry_seconds: Some(options.interval.as_secs()),
|
||||
next_retry_seconds: Some(sleep_for.as_secs()),
|
||||
};
|
||||
eprintln!("{}", serde_json::to_string_pretty(&payload)?);
|
||||
}
|
||||
}
|
||||
|
||||
thread::sleep(options.interval);
|
||||
thread::sleep(sleep_for);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +215,16 @@ fn parse_args_from(raw_args: impl IntoIterator<Item = String>) -> anyhow::Result
|
||||
.map_err(|error| anyhow::anyhow!("invalid seconds for {flag}: {error}"))?;
|
||||
options.interval = Duration::from_secs(seconds);
|
||||
}
|
||||
"--error-retry" => {
|
||||
options.error_retry_interval =
|
||||
parse_duration(&next_option_value(&mut args, &flag)?)?;
|
||||
}
|
||||
"--error-retry-seconds" => {
|
||||
let seconds = next_option_value(&mut args, &flag)?
|
||||
.parse::<u64>()
|
||||
.map_err(|error| anyhow::anyhow!("invalid seconds for {flag}: {error}"))?;
|
||||
options.error_retry_interval = Duration::from_secs(seconds);
|
||||
}
|
||||
"--quiet-up-to-date" => {
|
||||
options.quiet_up_to_date = true;
|
||||
options.quiet_up_to_date_explicit = true;
|
||||
@@ -227,6 +247,11 @@ fn parse_args_from(raw_args: impl IntoIterator<Item = String>) -> anyhow::Result
|
||||
if options.interval.is_zero() {
|
||||
return Err(anyhow::anyhow!("watch interval must be greater than zero"));
|
||||
}
|
||||
if options.error_retry_interval.is_zero() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"watch error retry interval must be greater than zero"
|
||||
));
|
||||
}
|
||||
if options.watch && !options.quiet_up_to_date_explicit {
|
||||
options.quiet_up_to_date = true;
|
||||
}
|
||||
@@ -248,7 +273,7 @@ fn print_usage(binary: &str) {
|
||||
[--app-version 1.70.0] [--connection-group <name>] [--launcher-version 1.7.2] \
|
||||
[--platforms Windows,Android] [--output official_update_output] [--snapshot official-sync-snapshot.json] \
|
||||
[--curl curl] [--unzip unzip] [--dry-run] [--plan] [--force] [--audit-local|--no-audit-local] [--repair|--no-repair] \
|
||||
[--watch] [--interval 1h|60m|3600s] [--quiet-up-to-date|--no-quiet-up-to-date]"
|
||||
[--watch] [--interval 1h|60m|3600s] [--error-retry 60s] [--quiet-up-to-date|--no-quiet-up-to-date]"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -337,6 +362,10 @@ mod tests {
|
||||
options.interval,
|
||||
Duration::from_secs(DEFAULT_WATCH_INTERVAL_SECONDS)
|
||||
);
|
||||
assert_eq!(
|
||||
options.error_retry_interval,
|
||||
Duration::from_secs(DEFAULT_ERROR_RETRY_SECONDS)
|
||||
);
|
||||
assert!(!options.quiet_up_to_date);
|
||||
assert!(!options.quiet_up_to_date_explicit);
|
||||
}
|
||||
@@ -385,10 +414,38 @@ mod tests {
|
||||
|
||||
assert!(options.watch);
|
||||
assert_eq!(options.interval, Duration::from_secs(30 * 60));
|
||||
assert_eq!(
|
||||
options.error_retry_interval,
|
||||
Duration::from_secs(DEFAULT_ERROR_RETRY_SECONDS)
|
||||
);
|
||||
assert!(options.quiet_up_to_date);
|
||||
assert!(!options.quiet_up_to_date_explicit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_explicit_watch_error_retry_interval() {
|
||||
let options = parse(&[
|
||||
"bat-official-sync",
|
||||
"--watch",
|
||||
"--interval",
|
||||
"1h",
|
||||
"--error-retry",
|
||||
"45s",
|
||||
])
|
||||
.unwrap();
|
||||
assert_eq!(options.interval, Duration::from_secs(3600));
|
||||
assert_eq!(options.error_retry_interval, Duration::from_secs(45));
|
||||
|
||||
let options = parse(&[
|
||||
"bat-official-sync",
|
||||
"--watch",
|
||||
"--error-retry-seconds",
|
||||
"30",
|
||||
])
|
||||
.unwrap();
|
||||
assert_eq!(options.error_retry_interval, Duration::from_secs(30));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_no_quiet_up_to_date_overrides_watch_default() {
|
||||
let options = parse(&[
|
||||
@@ -413,6 +470,10 @@ mod tests {
|
||||
let error =
|
||||
parse(&["bat-official-sync", "--watch", "--interval-seconds", "0"]).unwrap_err();
|
||||
assert!(error.to_string().contains("greater than zero"));
|
||||
|
||||
let error =
|
||||
parse(&["bat-official-sync", "--watch", "--error-retry-seconds", "0"]).unwrap_err();
|
||||
assert!(error.to_string().contains("error retry interval"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user