Skip to content

Commit 10848a7

Browse files
committed
wip: better env handling and scheduling
1 parent 17828f3 commit 10848a7

File tree

3 files changed

+45
-33
lines changed

3 files changed

+45
-33
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ aws-config = "0.54"
1212
aws-sdk-s3 = "0.24"
1313
aws-smithy-http = "0.54"
1414
chrono = "0.4"
15-
clap = { version = "4", features = ["derive"] }
15+
clap = { version = "4", features = ["derive", "env"] }
1616
cron = "0.12"
1717
dotenvy = "0.15"
1818
flate2 = "1"
1919
tar = "0.4"
2020
tempfile = "3"
2121
tokio = { version = "1", features = ["full"] }
22-
tokio-cron-scheduler = "0.9"
22+
tokio-cron-scheduler = { version = "0.9", features = ["signal"] }
2323

2424
[dev-dependencies]
2525
ctor = "0.1"

src/config.rs

+31-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{env, path::PathBuf};
1+
use std::path::PathBuf;
22

33
use anyhow::{anyhow, Context, Result};
44
use aws_config::meta::region::RegionProviderChain;
@@ -12,31 +12,49 @@ use crate::prelude::*;
1212
#[command(version, about, long_about = None)]
1313
struct Cli {
1414
/// Path to the folder to backup
15-
///
16-
/// If not specified, defaults to "/dockerbck"
17-
#[arg(value_hint = clap::ValueHint::DirPath)]
15+
#[arg(value_hint = clap::ValueHint::DirPath, env = "DOCKERBCK_FOLDER")]
1816
folder: Option<PathBuf>,
1917

2018
/// Specify a cron expression to run the backup periodically
2119
///
2220
/// If not specified, the backup will only run once
23-
#[arg(short, long, value_name = "CRON")]
21+
#[arg(short, long, value_name = "CRON", env = "DOCKERBCK_SCHEDULE")]
2422
schedule: Option<String>,
2523

2624
/// The AWS S3 region
27-
#[arg(short = 'r', long = "region", value_name = "REGION")]
25+
#[arg(
26+
short = 'r',
27+
long = "region",
28+
value_name = "REGION",
29+
env = "AWS_REGION"
30+
)]
2831
aws_region: Option<String>,
2932

3033
/// The AWS S3 bucket name
31-
#[arg(short = 'b', long = "bucket", value_name = "BUCKET")]
34+
#[arg(
35+
short = 'b',
36+
long = "bucket",
37+
value_name = "BUCKET",
38+
env = "AWS_BUCKET"
39+
)]
3240
aws_bucket: Option<String>,
3341

3442
/// The AWS S3 access key ID
35-
#[arg(short = 'i', long = "id", value_name = "KEY_ID")]
43+
#[arg(
44+
short = 'i',
45+
long = "id",
46+
value_name = "KEY_ID",
47+
env = "AWS_ACCESS_KEY_ID"
48+
)]
3649
aws_key_id: Option<String>,
3750

3851
/// The AWS S3 secret access key
39-
#[arg(short = 't', long = "token", value_name = "KEY")]
52+
#[arg(
53+
short = 't',
54+
long = "token",
55+
value_name = "KEY",
56+
env = "AWS_SECRET_ACCESS_KEY"
57+
)]
4058
aws_key: Option<String>,
4159
}
4260

@@ -58,27 +76,11 @@ pub struct Params {
5876

5977
/// Parse the command-line arguments and environment variables into runtime params
6078
pub async fn parse_config() -> Result<Params> {
61-
let mut params = Cli::parse();
62-
63-
params.folder = params
64-
.folder
65-
.or_else(|| env::var("DOCKERBCK_FOLDER").ok().map(PathBuf::from))
66-
.or_else(|| Some(PathBuf::from("/dockerbox")));
67-
68-
params.schedule = params
69-
.schedule
70-
.or_else(|| env::var("DOCKERBCK_SCHEDULE").ok());
79+
let params = Cli::parse();
7180

72-
params.aws_region = params.aws_region.or_else(|| env::var("AWS_REGION").ok());
73-
params.aws_bucket = params.aws_bucket.or_else(|| env::var("AWS_BUCKET").ok());
74-
params.aws_key_id = params
75-
.aws_key_id
76-
.or_else(|| env::var("AWS_ACCESS_KEY_ID").ok());
77-
params.aws_key = params
78-
.aws_key
79-
.or_else(|| env::var("AWS_SECRET_ACCESS_KEY").ok());
80-
81-
let folder = params.folder.or_panic(); // Ok to unwrap due to default value
81+
let Some(folder) = params.folder else {
82+
return Err(anyhow!("No folder path was provided"));
83+
};
8284
let folder = folder
8385
.canonicalize()
8486
.with_context(|| anyhow!("Could not resolve path {}", folder.to_string_lossy()))?;

src/main.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![warn(clippy::unwrap_used)]
44
#![warn(clippy::expect_used)]
55

6-
use std::sync::Arc;
6+
use std::{sync::Arc, time::Duration};
77

88
use anyhow::{anyhow, Context, Result};
99
use dotenvy::dotenv;
@@ -26,7 +26,7 @@ async fn main() -> Result<()> {
2626

2727
match params.schedule.clone() {
2828
Some(schedule) => {
29-
let sched = JobScheduler::new().await?;
29+
let mut sched = JobScheduler::new().await?;
3030
let job = Job::new_async(schedule, move |_, _| {
3131
let shared_params = Arc::clone(&params);
3232
Box::pin(async move {
@@ -37,6 +37,16 @@ async fn main() -> Result<()> {
3737
})
3838
})?;
3939
sched.add(job).await?;
40+
sched.shutdown_on_ctrl_c();
41+
sched.set_shutdown_handler(Box::new(|| {
42+
Box::pin(async move {
43+
println!("Shut down done");
44+
})
45+
}));
46+
sched.start().await?;
47+
loop {
48+
tokio::time::sleep(Duration::from_millis(500)).await;
49+
}
4050
}
4151
None => {
4252
backup(&params)

0 commit comments

Comments
 (0)