Skip to content

Commit a9886c5

Browse files
authored
Merge pull request #2257 from input-output-hk/sfa/2215/enhance_Snapshotter_to_avoid_file_deletion_on_error
Do not delete an already existing archive on error
2 parents 58a4935 + 7f68d52 commit a9886c5

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-aggregator/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.6.23"
3+
version = "0.6.24"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/services/snapshotter/compressed_archive_snapshotter.rs

+72-10
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ impl CompressedArchiveSnapshotter {
106106
}
107107

108108
fn snapshot<T: TarAppender>(&self, filepath: &Path, appender: T) -> StdResult<OngoingSnapshot> {
109+
let temporary_archive_path = self
110+
.ongoing_snapshot_directory
111+
.join(filepath.with_extension("tmp"));
109112
let archive_path = self.ongoing_snapshot_directory.join(filepath);
110113
if let Some(archive_dir) = archive_path.parent() {
111114
fs::create_dir_all(archive_dir).with_context(|| {
@@ -115,17 +118,33 @@ impl CompressedArchiveSnapshotter {
115118
)
116119
})?;
117120
}
118-
let filesize = self.create_and_verify_archive(&archive_path, appender).inspect_err(|_err| {
119-
if archive_path.exists() {
120-
if let Err(remove_error) = fs::remove_file(&archive_path) {
121-
warn!(
122-
self.logger, " > Post snapshotter.snapshot failure, could not remove temporary archive";
123-
"archive_path" => archive_path.display(),
124-
"error" => remove_error
125-
);
121+
let filesize = self
122+
.create_and_verify_archive(&temporary_archive_path, appender)
123+
.inspect_err(|_err| {
124+
if temporary_archive_path.exists() {
125+
if let Err(remove_error) = fs::remove_file(&temporary_archive_path) {
126+
warn!(
127+
self.logger, " > Post snapshotter.snapshot failure, could not remove temporary archive";
128+
"archive_path" => temporary_archive_path.display(),
129+
"error" => remove_error
130+
);
131+
}
126132
}
127-
}
128-
}).with_context(|| format!("CompressedArchiveSnapshotter can not create and verify archive: '{}'", archive_path.display()))?;
133+
})
134+
.with_context(|| {
135+
format!(
136+
"CompressedArchiveSnapshotter can not create and verify archive: '{}'",
137+
archive_path.display()
138+
)
139+
})?;
140+
141+
fs::rename(&temporary_archive_path, &archive_path).with_context(|| {
142+
format!(
143+
"CompressedArchiveSnapshotter can not rename temporary archive: '{}' to final archive: '{}'",
144+
temporary_archive_path.display(),
145+
archive_path.display()
146+
)
147+
})?;
129148

130149
Ok(OngoingSnapshot {
131150
filepath: archive_path,
@@ -331,6 +350,8 @@ mod tests {
331350

332351
use mithril_common::digesters::DummyCardanoDbBuilder;
333352

353+
use mithril_common::test_utils::assert_equivalent;
354+
334355
use crate::services::snapshotter::test_tools::*;
335356
use crate::test_tools::TestLogger;
336357
use crate::ZstandardCompressionParameters;
@@ -412,6 +433,47 @@ mod tests {
412433
assert_eq!(vec!["other-process.file".to_string()], remaining_files);
413434
}
414435

436+
#[test]
437+
fn should_not_delete_an_alreay_existing_archive_with_same_name_if_snapshotting_fail() {
438+
let test_dir = get_test_directory(
439+
"should_not_delete_an_alreay_existing_archive_with_same_name_if_snapshotting_fail",
440+
);
441+
let pending_snapshot_directory = test_dir.join("pending_snapshot");
442+
let db_directory = test_dir.join("db");
443+
444+
let snapshotter = Arc::new(
445+
CompressedArchiveSnapshotter::new(
446+
db_directory,
447+
pending_snapshot_directory.clone(),
448+
SnapshotterCompressionAlgorithm::Gzip,
449+
TestLogger::stdout(),
450+
)
451+
.unwrap(),
452+
);
453+
454+
// this file should not be deleted by the archive creation
455+
create_file(&pending_snapshot_directory, "other-process.file");
456+
create_file(&pending_snapshot_directory, "whatever.tar.gz");
457+
// an already existing temporary archive file should be deleted
458+
create_file(&pending_snapshot_directory, "whatever.tar.tmp");
459+
460+
let _ = snapshotter
461+
.snapshot_all(Path::new("whatever.tar.gz"))
462+
.expect_err("Snapshotter::snapshot should fail if the db is empty.");
463+
let remaining_files: Vec<String> = fs::read_dir(&pending_snapshot_directory)
464+
.unwrap()
465+
.map(|f| f.unwrap().file_name().to_str().unwrap().to_owned())
466+
.collect();
467+
468+
assert_equivalent(
469+
vec![
470+
"other-process.file".to_string(),
471+
"whatever.tar.gz".to_string(),
472+
],
473+
remaining_files,
474+
);
475+
}
476+
415477
#[test]
416478
fn should_create_a_valid_archive_with_gzip_snapshotter() {
417479
let test_dir = get_test_directory("should_create_a_valid_archive_with_gzip_snapshotter");

0 commit comments

Comments
 (0)