mod sync;
mod s3;
mod wal;
use anyhow::Result;
use clap::{Parser, Subcommand};
use std::path::PathBuf;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[derive(Parser)]
#[command(name = "walsync")]
#[command(about = "Lightweight SQLite WAL sync to S3/Tigris")]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Watch {
#[arg(required = true)]
databases: Vec<PathBuf>,
#[arg(short, long)]
bucket: String,
#[arg(long, default_value = "3600")]
snapshot_interval: u64,
#[arg(long, env = "AWS_ENDPOINT_URL_S3")]
endpoint: Option<String>,
},
Restore {
name: String,
#[arg(short, long)]
output: PathBuf,
#[arg(short, long)]
bucket: String,
#[arg(long, env = "AWS_ENDPOINT_URL_S3")]
endpoint: Option<String>,
#[arg(long)]
point_in_time: Option<String>,
},
List {
#[arg(short, long)]
bucket: String,
#[arg(long, env = "AWS_ENDPOINT_URL_S3")]
endpoint: Option<String>,
},
Snapshot {
database: PathBuf,
#[arg(short, long)]
bucket: String,
#[arg(long, env = "AWS_ENDPOINT_URL_S3")]
endpoint: Option<String>,
},
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new(
std::env::var("RUST_LOG").unwrap_or_else(|_| "walsync=info".into()),
))
.with(tracing_subscriber::fmt::layer())
.init();
let cli = Cli::parse();
match cli.command {
Commands::Watch {
databases,
bucket,
snapshot_interval,
endpoint,
} => {
sync::watch(databases, &bucket, snapshot_interval, endpoint.as_deref()).await?;
}
Commands::Restore {
name,
output,
bucket,
endpoint,
point_in_time,
} => {
sync::restore(&name, &output, &bucket, endpoint.as_deref(), point_in_time.as_deref()).await?;
}
Commands::List { bucket, endpoint } => {
sync::list(&bucket, endpoint.as_deref()).await?;
}
Commands::Snapshot {
database,
bucket,
endpoint,
} => {
sync::snapshot(&database, &bucket, endpoint.as_deref()).await?;
}
}
Ok(())
}