couchdb_orm/client/couchdb/actions/db/backup/
mod.rs

1// Copyright (C) 2020-2023  OpenToolAdd
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15// contact: contact@tool-add.com
16
17use crate::client::couchdb::actions::db::all_docs::get_all_docs;
18use crate::regexes::COUCHDB_DB_RULE;
19use awc::Client;
20use chrono::Utc;
21use serde::{de::DeserializeOwned, Serialize};
22use std::fmt::Debug;
23use std::path::PathBuf;
24
25pub mod errors;
26
27use errors::DBBackupError;
28
29pub async fn backup_db<T: Clone + Serialize + DeserializeOwned + Debug>(
30    client: &Client,
31    db_name: &str,
32    seed_name: &str,
33    host: &str,
34) -> Result<bool, Box<dyn std::error::Error>> {
35    if !COUCHDB_DB_RULE.is_match(db_name) {
36        return Err(Box::new(DBBackupError::new(&format!(
37            "{} string doesn't respect the regex rule {}",
38            db_name,
39            COUCHDB_DB_RULE.as_str()
40        ))));
41    }
42
43    let mut skip: usize = 0;
44    let mut max_rows: usize = 1000;
45    let limit: usize = 100;
46    // println!("{}", uri);
47
48    let exe_path: PathBuf = std::env::current_exe().unwrap();
49    let backup_path: PathBuf = exe_path
50        .parent()
51        .unwrap()
52        .to_path_buf()
53        .parent()
54        .unwrap()
55        .to_path_buf()
56        .parent()
57        .unwrap()
58        .to_path_buf()
59        .join("backups");
60
61    let timestamp: i64 = Utc::now().timestamp();
62    let folder_path = backup_path.join(format!("{}/{}/{}", db_name, seed_name, timestamp));
63
64    // println!("{:#?}", backup_path);
65    std::fs::create_dir_all(&backup_path)?;
66    // println!("{:#?}", folder_path);
67    std::fs::create_dir_all(&folder_path)?;
68
69    while skip < max_rows {
70        let index = skip / 100;
71        println!("chunk {} backuped", index);
72        // println!("max rows {}", max_rows);
73        // println!("skip {}", skip);
74        // println!("limit {}", limit);
75        let all_docs = get_all_docs::<T>(client, db_name, host, skip, limit).await?;
76        max_rows = all_docs.total_rows;
77        let all_docs: Vec<T> = all_docs.rows.iter().map(|o| o.doc.clone()).collect();
78
79        let file_path = folder_path.join(format!("{}.json", index));
80        std::fs::write(
81            &file_path,
82            format!("{}", serde_json::to_string_pretty(&all_docs).unwrap()),
83        )?;
84        // println!("{:#?}", all_docs);
85        // println!("{:#?}", file_path);
86        skip += limit;
87    }
88    println!("backup saved in: {}", folder_path.display());
89
90    Ok(true)
91}
92
93#[cfg(test)]
94mod tests {}