Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit 7aece6b

Browse files
authored
bottomless restore to temp file first, replace only on success (#732)
* bottomless restore to temp file first, replace only on success * fixed clippy errors
1 parent a3d67e9 commit 7aece6b

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

bottomless/src/replicator.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,12 @@ impl Replicator {
676676
gzip_path.join("db.gz")
677677
}
678678

679+
fn restore_db_path(&self) -> PathBuf {
680+
let mut gzip_path = PathBuf::from(&self.db_path);
681+
gzip_path.pop();
682+
gzip_path.join("data.tmp")
683+
}
684+
679685
// Replicates local WAL pages to S3, if local WAL is present.
680686
// This function is called under the assumption that if local WAL
681687
// file is present, it was already detected to be newer than its
@@ -976,35 +982,40 @@ impl Replicator {
976982

977983
// at this point we know, we should do a full restore
978984

979-
let backup_path = format!("{}.bottomless.backup", self.db_path);
980-
tokio::fs::rename(&self.db_path, &backup_path).await.ok(); // Best effort
981-
match self.full_restore(generation, timestamp, last_frame).await {
985+
let restore_path = self.restore_db_path();
986+
let _ = tokio::fs::remove_file(&restore_path).await; // remove previous (failed) restoration
987+
match self
988+
.full_restore(&restore_path, generation, timestamp, last_frame)
989+
.await
990+
{
982991
Ok(result) => {
983992
let elapsed = Instant::now() - start_ts;
984993
tracing::info!("Finished database restoration in {:?}", elapsed);
985-
tokio::fs::remove_file(backup_path).await.ok();
994+
tokio::fs::rename(&restore_path, &self.db_path).await?;
995+
let _ = self.remove_wal_files().await; // best effort, WAL files may not exists
986996
Ok(result)
987997
}
988998
Err(e) => {
989999
tracing::error!("failed to restore the database: {}. Rollback", e);
990-
tokio::fs::rename(&backup_path, &self.db_path).await.ok();
1000+
let _ = tokio::fs::remove_file(restore_path).await;
9911001
Err(e)
9921002
}
9931003
}
9941004
}
9951005

9961006
async fn full_restore(
9971007
&mut self,
1008+
restore_path: &Path,
9981009
generation: Uuid,
9991010
timestamp: Option<NaiveDateTime>,
10001011
last_frame: u32,
10011012
) -> Result<(RestoreAction, bool)> {
1002-
let _ = self.remove_wal_files().await; // best effort, WAL files may not exists
1013+
tracing::debug!("Restoring database to `{}`", restore_path.display());
10031014
let mut db = OpenOptions::new()
10041015
.create(true)
10051016
.read(true)
10061017
.write(true)
1007-
.open(&self.db_path)
1018+
.open(restore_path)
10081019
.await?;
10091020

10101021
let mut restore_stack = Vec::new();

0 commit comments

Comments
 (0)