use crate::client::couchdb::actions::db::all_docs::get_all_docs;
use crate::regexes::COUCHDB_DB_RULE;
use awc::Client;
use chrono::Utc;
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;
use std::path::PathBuf;
pub mod errors;
use errors::DBBackupError;
pub async fn backup_db<T: Clone + Serialize + DeserializeOwned + Debug>(
client: &Client,
db_name: &str,
seed_name: &str,
host: &str,
) -> Result<bool, Box<dyn std::error::Error>> {
if !COUCHDB_DB_RULE.is_match(db_name) {
return Err(Box::new(DBBackupError::new(&format!(
"{} string doesn't respect the regex rule {}",
db_name,
COUCHDB_DB_RULE.as_str()
))));
}
let mut skip: usize = 0;
let mut max_rows: usize = 1000;
let limit: usize = 100;
let exe_path: PathBuf = std::env::current_exe().unwrap();
let backup_path: PathBuf = exe_path
.parent()
.unwrap()
.to_path_buf()
.parent()
.unwrap()
.to_path_buf()
.parent()
.unwrap()
.to_path_buf()
.join("backups");
let timestamp: i64 = Utc::now().timestamp();
let folder_path = backup_path.join(format!("{}/{}/{}", db_name, seed_name, timestamp));
std::fs::create_dir_all(&backup_path)?;
std::fs::create_dir_all(&folder_path)?;
while skip < max_rows {
let index = skip / 100;
println!("chunk {} backuped", index);
let all_docs = get_all_docs::<T>(client, db_name, host, skip, limit).await?;
max_rows = all_docs.total_rows;
let all_docs: Vec<T> = all_docs.rows.iter().map(|o| o.doc.clone()).collect();
let file_path = folder_path.join(format!("{}.json", index));
std::fs::write(
&file_path,
format!("{}", serde_json::to_string_pretty(&all_docs).unwrap()),
)?;
skip += limit;
}
println!("backup saved in: {}", folder_path.display());
Ok(true)
}
#[cfg(test)]
mod tests {}