fraiseql_server/backup/
backup_config.rs1use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct BackupConfig {
10 pub enabled: bool,
12
13 pub schedule: String,
16
17 pub retention_count: u32,
19
20 pub retention_days: u32,
22
23 pub storage: String,
25
26 pub storage_path: String,
28
29 pub compression: Option<String>,
31
32 pub timeout_secs: u64,
34
35 pub verify_after_backup: bool,
37}
38
39impl Default for BackupConfig {
40 fn default() -> Self {
41 Self {
42 enabled: true,
43 schedule: "0 * * * *".to_string(), retention_count: 24, retention_days: 30,
46 storage: "local".to_string(),
47 storage_path: "/var/backups/fraiseql".to_string(),
48 compression: Some("gzip".to_string()),
49 timeout_secs: 600,
50 verify_after_backup: true,
51 }
52 }
53}
54
55impl BackupConfig {
56 pub fn postgres_default() -> Self {
58 Self {
59 enabled: true,
60 schedule: "0 * * * *".to_string(), retention_count: 24,
62 retention_days: 30,
63 storage: "local".to_string(),
64 storage_path: "/var/backups/fraiseql/postgres".to_string(),
65 compression: Some("gzip".to_string()),
66 timeout_secs: 1800,
67 verify_after_backup: true,
68 }
69 }
70
71 pub fn redis_default() -> Self {
73 Self {
74 enabled: true,
75 schedule: "0 0 * * *".to_string(), retention_count: 7,
77 retention_days: 7,
78 storage: "local".to_string(),
79 storage_path: "/var/backups/fraiseql/redis".to_string(),
80 compression: Some("gzip".to_string()),
81 timeout_secs: 600,
82 verify_after_backup: false,
83 }
84 }
85
86 pub fn clickhouse_default() -> Self {
88 Self {
89 enabled: true,
90 schedule: "0 1 * * *".to_string(), retention_count: 7,
92 retention_days: 7,
93 storage: "local".to_string(),
94 storage_path: "/var/backups/fraiseql/clickhouse".to_string(),
95 compression: None, timeout_secs: 3600,
97 verify_after_backup: false,
98 }
99 }
100
101 pub fn elasticsearch_default() -> Self {
103 Self {
104 enabled: true,
105 schedule: "0 2 * * *".to_string(), retention_count: 7,
107 retention_days: 7,
108 storage: "local".to_string(),
109 storage_path: "/var/backups/fraiseql/elasticsearch".to_string(),
110 compression: None, timeout_secs: 3600,
112 verify_after_backup: true,
113 }
114 }
115
116 pub fn timeout(&self) -> Duration {
118 Duration::from_secs(self.timeout_secs)
119 }
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct BackupStatus {
125 pub store_name: String,
127
128 pub enabled: bool,
130
131 pub last_successful_backup: Option<i64>,
133
134 pub last_backup_size: Option<u64>,
136
137 pub available_backups: u32,
139
140 pub last_error: Option<String>,
142
143 pub status: String,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct RecoveryConfig {
150 pub store_name: String,
152
153 pub backup_timestamp: i64,
155
156 pub verify_after_recovery: bool,
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_postgres_default_config() {
166 let config = BackupConfig::postgres_default();
167 assert!(config.enabled);
168 assert_eq!(config.schedule, "0 * * * *");
169 assert_eq!(config.retention_count, 24);
170 }
171
172 #[test]
173 fn test_redis_default_config() {
174 let config = BackupConfig::redis_default();
175 assert!(config.enabled);
176 assert_eq!(config.schedule, "0 0 * * *");
177 assert_eq!(config.retention_count, 7);
178 }
179
180 #[test]
181 fn test_clickhouse_default_config() {
182 let config = BackupConfig::clickhouse_default();
183 assert!(config.enabled);
184 assert_eq!(config.schedule, "0 1 * * *");
185 }
186
187 #[test]
188 fn test_elasticsearch_default_config() {
189 let config = BackupConfig::elasticsearch_default();
190 assert!(config.enabled);
191 assert_eq!(config.schedule, "0 2 * * *");
192 }
193
194 #[test]
195 fn test_timeout_conversion() {
196 let config = BackupConfig::postgres_default();
197 let duration = config.timeout();
198 assert_eq!(duration.as_secs(), 1800);
199 }
200}