Skip to content

Commit

Permalink
Added Ability to restore from backup
Browse files Browse the repository at this point in the history
  • Loading branch information
amigin committed Dec 2, 2024
1 parent 154a91e commit fe0e215
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 113 deletions.
36 changes: 36 additions & 0 deletions src/http_server/controllers/backup/get_backup_files_action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use my_http_server::macros::*;
use my_http_server::{HttpContext, HttpFailResult, HttpOkResult, HttpOutput};
use std::sync::Arc;

use crate::app::AppContext;

#[http_route(
method: "GET",
route: "/api/Backup/List",
description: "Get list of backup files",
summary: "Get list of backup files",
controller: "Backup",
result:[
{status_code: 200, description: "List of Backup files", model: "Vec<String>"},
]
)]
pub struct GetListOfBackupFilesAction {
app: Arc<AppContext>,
}

impl GetListOfBackupFilesAction {
pub fn new(app: Arc<AppContext>) -> Self {
Self { app }
}
}

async fn handle_request(
action: &GetListOfBackupFilesAction,
_ctx: &mut HttpContext,
) -> Result<HttpOkResult, HttpFailResult> {
let list_of_files = crate::operations::backup::get_list_of_files(&action.app).await;

HttpOutput::as_json(list_of_files)
.into_ok_result(true)
.into()
}
8 changes: 8 additions & 0 deletions src/http_server/controllers/backup/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod download_action;
pub use download_action::*;
mod restore_from_backup_action;
pub use restore_from_backup_action::*;
mod get_backup_files_action;
pub use get_backup_files_action::*;
mod restore_from_zip_action;
pub use restore_from_zip_action::*;
68 changes: 68 additions & 0 deletions src/http_server/controllers/backup/restore_from_zip_action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use my_http_server::macros::*;
use my_http_server::types::FileContent;
use my_http_server::{HttpContext, HttpFailResult, HttpOkResult, HttpOutput};
use std::sync::Arc;

use crate::app::AppContext;

#[http_route(
method: "POST",
route: "/api/Backup/RestoreFromBackup",
description: "Restore database from backup zip file",
summary: "Restore database from backup zip file",
controller: "Backup",
input_data: RestoreFromBackupZipFileInputData,
result:[
{status_code: 204, description: "Restored ok"},
]
)]
pub struct RestoreFromZipAction {
app: Arc<AppContext>,
}

impl RestoreFromZipAction {
pub fn new(app: Arc<AppContext>) -> Self {
Self { app }
}
}

async fn handle_request(
action: &RestoreFromZipAction,
input_data: RestoreFromBackupZipFileInputData,
_ctx: &mut HttpContext,
) -> Result<HttpOkResult, HttpFailResult> {
let table_name = input_data.get_table_name().map(|itm| itm.to_string());

let restore_result = crate::operations::backup::restore(
&action.app,
input_data.zip.content,
table_name.as_deref(),
)
.await;

match restore_result {
Ok(_) => HttpOutput::Empty.into_ok_result(true).into(),
Err(err) => Err(HttpFailResult::as_fatal_error(format!("{:?}", err))),
}
}

#[derive(MyHttpInput)]
pub struct RestoreFromBackupZipFileInputData {
#[http_form_data(name = "fileName", description = "File in backup folder")]
pub zip: FileContent,
#[http_form_data(
name = "tableName",
description = "Name of the table or '*' for all tables"
)]
pub table_name: String,
}

impl RestoreFromBackupZipFileInputData {
pub fn get_table_name(&self) -> Option<&str> {
if self.table_name == "*" {
None
} else {
Some(self.table_name.as_str())
}
}
}
4 changes: 0 additions & 4 deletions src/http_server/controllers/backup_controller/mod.rs

This file was deleted.

14 changes: 10 additions & 4 deletions src/http_server/controllers/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,19 @@ pub fn build(app: &Arc<AppContext>) -> ControllersMiddleware {

// Backup controller

result.register_get_action(Arc::new(super::backup_controller::DownloadAction::new(
result.register_get_action(Arc::new(super::backup::DownloadAction::new(app.clone())));

result.register_get_action(Arc::new(super::backup::GetListOfBackupFilesAction::new(
app.clone(),
)));

result.register_post_action(Arc::new(
super::backup_controller::RestoreFromBackupAction::new(app.clone()),
));
result.register_post_action(Arc::new(super::backup::RestoreFromBackupAction::new(
app.clone(),
)));

result.register_post_action(Arc::new(super::backup::RestoreFromZipAction::new(
app.clone(),
)));

result
}
2 changes: 1 addition & 1 deletion src/http_server/controllers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ pub mod status_controller;
pub mod tables_controller;
pub mod transactions;
pub use mappers::*;
mod backup_controller;
pub mod backup;
pub mod partitions;
51 changes: 2 additions & 49 deletions src/operations/backup/gc_backups.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,18 @@
use my_no_sql_sdk::core::rust_extensions::ShortString;

use crate::app::AppContext;

use std::{collections::BTreeMap, path::MAIN_SEPARATOR};

use super::utils::compile_backup_file;

pub async fn gc_backups(app: &AppContext) {
let backup_folder = app.settings.get_backup_folder();

let mut read_dir = tokio::fs::read_dir(backup_folder.as_str()).await.unwrap();

let mut result = BTreeMap::new();

while let Ok(entry) = read_dir.next_entry().await {
if entry.is_none() {
break;
}

let entry = entry.unwrap();

let file_type = entry.file_type().await.unwrap();

if file_type.is_file() {
let path = entry.path();

let path = format!("{}", path.display());

let file_name = extract_file_name(path.as_str(), MAIN_SEPARATOR);

if if_filename_is_backup(file_name) {
result.insert(file_name.to_string(), ());
}
}
}
let mut result = super::get_list_of_files(app).await;

while result.len() > app.settings.max_backups_to_keep {
let file_name: ShortString = result.keys().next().unwrap().into();
let file_name = result.pop().unwrap();
println!("Deleting backup file: {}", file_name.as_str());
delete_backup(app, file_name.as_str()).await;
result.remove(file_name.as_str());
}
}

async fn delete_backup(app: &AppContext, file_name: &str) {
let file_full_path = compile_backup_file(app, file_name);
tokio::fs::remove_file(file_full_path).await.unwrap();
}

pub fn extract_file_name(full_path: &str, separator: char) -> &str {
let full_path_as_bytes = full_path.as_bytes();

for index in (0..full_path_as_bytes.len()).rev() {
if full_path_as_bytes[index] == separator as u8 {
return &full_path[index + 1..];
}
}

panic!("Can not extract filename from full path [{}]", full_path);
}

fn if_filename_is_backup(src: &str) -> bool {
return src.ends_with(".zip");
}
51 changes: 51 additions & 0 deletions src/operations/backup/get_list_of_files.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::collections::BTreeMap;

use crate::app::AppContext;

pub async fn get_list_of_files(app: &AppContext) -> Vec<String> {
let backup_folder = app.settings.get_backup_folder();

let mut read_dir = tokio::fs::read_dir(backup_folder.as_str()).await.unwrap();

let mut result = BTreeMap::new();

while let Ok(entry) = read_dir.next_entry().await {
if entry.is_none() {
break;
}

let entry = entry.unwrap();

let file_type = entry.file_type().await.unwrap();

if file_type.is_file() {
let path = entry.path();

let path = format!("{}", path.display());

let file_name = extract_file_name(path.as_str(), std::path::MAIN_SEPARATOR);

if if_filename_is_backup(file_name) {
result.insert(file_name.to_string(), ());
}
}
}

result.into_iter().map(|x| x.0).collect()
}

pub fn extract_file_name(full_path: &str, separator: char) -> &str {
let full_path_as_bytes = full_path.as_bytes();

for index in (0..full_path_as_bytes.len()).rev() {
if full_path_as_bytes[index] == separator as u8 {
return &full_path[index + 1..];
}
}

panic!("Can not extract filename from full path [{}]", full_path);
}

fn if_filename_is_backup(src: &str) -> bool {
return src.ends_with(".zip");
}
2 changes: 2 additions & 0 deletions src/operations/backup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ mod restore;
pub use restore::*;
mod restore_file_name;
pub use restore_file_name::*;
mod get_list_of_files;
pub use get_list_of_files::*;
54 changes: 0 additions & 54 deletions src/scripts/serializers/db_partition.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/scripts/serializers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pub mod db_partition;
pub mod table_attrs;

0 comments on commit fe0e215

Please sign in to comment.