Skip to content

Commit 1eaa283

Browse files
authored
Merge pull request #1229 from tursodatabase/bottomless-cli-snapshot
bottomless-cli: added snapshot command
2 parents bc00d3e + da66583 commit 1eaa283

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

bottomless-cli/src/main.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ enum Commands {
106106
#[clap(long, short)]
107107
verbose: bool,
108108
},
109+
#[clap(about = "Generate and upload a snapshot for a given generation or timestamp")]
110+
Snapshot {
111+
#[clap(long, short)]
112+
generation: Option<uuid::Uuid>,
113+
},
109114
}
110115

111116
async fn run() -> Result<()> {
@@ -273,6 +278,44 @@ async fn run() -> Result<()> {
273278
"rm command cannot be run without parameters; see -h or --help for details"
274279
),
275280
},
281+
Commands::Snapshot { generation } => {
282+
tokio::fs::create_dir_all(&database_dir).await?;
283+
let generation = if let Some(gen) = generation {
284+
gen
285+
} else if let Some(gen) = client.latest_generation_before(None).await {
286+
gen
287+
} else {
288+
println!("no generation to snapshot found; nothing to do");
289+
return Ok(());
290+
};
291+
// snapshots mark the state of the DB at the beginning of the generation, therefore
292+
// snapshot at generation N is a final state of database at generation N-1. This can
293+
// be later used for fast restore: restore from generation N = snapshot + all WAL frames
294+
// from that generation.
295+
let parent = if let Some(parent) = client.get_dependency(&generation).await? {
296+
parent
297+
} else {
298+
println!("cannot create a snapshot at the beginning of the generation {}: parent generation not found", generation);
299+
return Ok(());
300+
};
301+
client.restore(Some(parent.clone()), None).await?;
302+
println!(
303+
"restored database at the start of generation {}: preparing snapshot...",
304+
generation
305+
);
306+
let db_path = PathBuf::from(&database);
307+
if let Err(e) = verify_db(&db_path) {
308+
println!("Verification failed: {e}");
309+
std::process::exit(1)
310+
} else {
311+
println!("verification succeeded");
312+
client.set_generation(generation.clone());
313+
client.snapshot_main_db_file(true).await?;
314+
client.wait_until_snapshotted().await?;
315+
println!("snapshot uploaded for generation: {}", generation);
316+
tokio::fs::remove_dir_all(&database_dir).await?;
317+
}
318+
}
276319
};
277320
Ok(())
278321
}

0 commit comments

Comments
 (0)