-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement optional and configurable disk archiver for closed segments (messages) and state log (storage). This is related to #290 and is the first iteration of working data archiver e.g. for the data backups purposes or just storing the old data in general.
- Loading branch information
Showing
38 changed files
with
1,496 additions
and
370 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use crate::archiver::ArchiverSetup; | ||
use server::archiver::Archiver; | ||
use server::streaming::utils::file; | ||
use std::path::Path; | ||
use tokio::io::{AsyncReadExt, AsyncWriteExt}; | ||
|
||
#[tokio::test] | ||
async fn should_init_base_archiver_directory() { | ||
let setup = ArchiverSetup::init().await; | ||
let archiver = setup.archiver(); | ||
let result = archiver.init().await; | ||
assert!(result.is_ok()); | ||
let path = Path::new(&setup.archive_path); | ||
assert!(path.exists()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn should_archive_file_on_disk_by_making_a_copy_of_original_file() { | ||
let setup = ArchiverSetup::init().await; | ||
let archiver = setup.archiver(); | ||
let content = "hello world"; | ||
let file_to_archive_path = format!("{}/file_to_archive", setup.base_path); | ||
create_file(&file_to_archive_path, content).await; | ||
let files_to_archive = vec![file_to_archive_path.as_ref()]; | ||
|
||
let result = archiver.archive(&files_to_archive, None).await; | ||
assert!(result.is_ok()); | ||
let archived_file_path = format!("{}/{}", setup.archive_path, file_to_archive_path); | ||
assert_archived_file(&file_to_archive_path, &archived_file_path, content).await; | ||
} | ||
|
||
#[tokio::test] | ||
async fn should_archive_file_on_disk_within_additional_base_directory() { | ||
let setup = ArchiverSetup::init().await; | ||
let archiver = setup.archiver(); | ||
let base_directory = "base"; | ||
let content = "hello world"; | ||
let file_to_archive_path = format!("{}/file_to_archive", setup.base_path); | ||
create_file(&file_to_archive_path, content).await; | ||
let files_to_archive = vec![file_to_archive_path.as_ref()]; | ||
|
||
let result = archiver | ||
.archive(&files_to_archive, Some(base_directory.to_string())) | ||
.await; | ||
assert!(result.is_ok()); | ||
let archived_file_path = format!( | ||
"{}/{base_directory}/{}", | ||
setup.archive_path, file_to_archive_path | ||
); | ||
assert_archived_file(&file_to_archive_path, &archived_file_path, content).await; | ||
} | ||
|
||
#[tokio::test] | ||
async fn should_return_true_when_file_is_archived() { | ||
let setup = ArchiverSetup::init().await; | ||
let archiver = setup.archiver(); | ||
let content = "hello world"; | ||
let file_to_archive_path = format!("{}/file_to_archive", setup.base_path); | ||
create_file(&file_to_archive_path, content).await; | ||
let files_to_archive = vec![file_to_archive_path.as_ref()]; | ||
archiver.archive(&files_to_archive, None).await.unwrap(); | ||
|
||
let is_archived = archiver.is_archived(&file_to_archive_path, None).await; | ||
assert!(is_archived.is_ok()); | ||
assert!(is_archived.unwrap()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn should_return_false_when_file_is_not_archived() { | ||
let setup = ArchiverSetup::init().await; | ||
let archiver = setup.archiver(); | ||
let content = "hello world"; | ||
let file_to_archive_path = format!("{}/file_to_archive", setup.base_path); | ||
create_file(&file_to_archive_path, content).await; | ||
|
||
let is_archived = archiver.is_archived(&file_to_archive_path, None).await; | ||
assert!(is_archived.is_ok()); | ||
assert!(!is_archived.unwrap()); | ||
} | ||
|
||
async fn create_file(path: &str, content: &str) { | ||
let mut file = file::overwrite(path).await.unwrap(); | ||
file.write_all(content.as_bytes()).await.unwrap(); | ||
} | ||
|
||
async fn assert_archived_file(file_to_archive_path: &str, archived_file_path: &str, content: &str) { | ||
assert!(Path::new(&file_to_archive_path).exists()); | ||
assert!(Path::new(&archived_file_path).exists()); | ||
let archived_file = file::open(archived_file_path).await; | ||
assert!(archived_file.is_ok()); | ||
let mut archived_file = archived_file.unwrap(); | ||
let mut archived_file_content = String::new(); | ||
archived_file | ||
.read_to_string(&mut archived_file_content) | ||
.await | ||
.unwrap(); | ||
assert_eq!(content, archived_file_content); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use server::archiver::disk::DiskArchiver; | ||
use server::configs::server::DiskArchiverConfig; | ||
use tokio::fs::create_dir; | ||
use uuid::Uuid; | ||
|
||
mod disk; | ||
|
||
pub struct ArchiverSetup { | ||
base_path: String, | ||
archive_path: String, | ||
archiver: DiskArchiver, | ||
} | ||
|
||
impl ArchiverSetup { | ||
pub async fn init() -> ArchiverSetup { | ||
let base_path = format!("test_local_data_{}", Uuid::new_v4().to_u128_le()); | ||
let archive_path = format!("{}/archive", base_path); | ||
let config = DiskArchiverConfig { | ||
path: archive_path.clone(), | ||
}; | ||
let archiver = DiskArchiver::new(config); | ||
create_dir(&base_path).await.unwrap(); | ||
|
||
Self { | ||
base_path, | ||
archive_path, | ||
archiver, | ||
} | ||
} | ||
|
||
pub fn archiver(&self) -> &DiskArchiver { | ||
&self.archiver | ||
} | ||
} | ||
|
||
impl Drop for ArchiverSetup { | ||
fn drop(&mut self) { | ||
std::fs::remove_dir_all(&self.base_path).unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
mod archiver; | ||
mod bench; | ||
mod cli; | ||
mod config_provider; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.