667656cf by Jabis Sevón

fmt

1 parent 1c5a47a0
Showing 1 changed file with 85 additions and 37 deletions
1 use anyhow::{Result, Context}; 1 use anyhow::{Context, Result};
2 use tokio_postgres::{Client, NoTls};
3 use log::{error, info, warn, trace};
4 use std::{fs,env};
5 use std::path::Path;
6 use chrono::Utc; 2 use chrono::Utc;
7 use clap::{Arg, Command}; 3 use clap::{Arg, Command};
8 use dotenv::dotenv; 4 use dotenv::dotenv;
5 use log::{error, info, trace, warn};
6 use std::path::Path;
7 use std::{env, fs};
8 use tokio_postgres::{Client, NoTls};
9 9
10 #[tokio::main] 10 #[tokio::main]
11 async fn main() { 11 async fn main() {
...@@ -22,7 +22,7 @@ async fn main() { ...@@ -22,7 +22,7 @@ async fn main() {
22 .long("data-dir") 22 .long("data-dir")
23 .env("MATTERMOST_DATA_DIRECTORY") 23 .env("MATTERMOST_DATA_DIRECTORY")
24 .help("Path to the Mattermost data directory") 24 .help("Path to the Mattermost data directory")
25 .required(true) 25 .required(true),
26 ) 26 )
27 .arg( 27 .arg(
28 Arg::new("db_name") 28 Arg::new("db_name")
...@@ -30,7 +30,7 @@ async fn main() { ...@@ -30,7 +30,7 @@ async fn main() {
30 .long("db-name") 30 .long("db-name")
31 .env("DATABASE_NAME") 31 .env("DATABASE_NAME")
32 .help("Database name") 32 .help("Database name")
33 .required(true) 33 .required(true),
34 ) 34 )
35 .arg( 35 .arg(
36 Arg::new("db_user") 36 Arg::new("db_user")
...@@ -38,7 +38,7 @@ async fn main() { ...@@ -38,7 +38,7 @@ async fn main() {
38 .long("db-user") 38 .long("db-user")
39 .env("DATABASE_USER") 39 .env("DATABASE_USER")
40 .help("Database user") 40 .help("Database user")
41 .required(true) 41 .required(true),
42 ) 42 )
43 .arg( 43 .arg(
44 Arg::new("db_password") 44 Arg::new("db_password")
...@@ -54,7 +54,7 @@ async fn main() { ...@@ -54,7 +54,7 @@ async fn main() {
54 .long("db-host") 54 .long("db-host")
55 .env("DATABASE_HOST") 55 .env("DATABASE_HOST")
56 .help("Database host") 56 .help("Database host")
57 .required(true) 57 .required(true),
58 ) 58 )
59 .arg( 59 .arg(
60 Arg::new("db_port") 60 Arg::new("db_port")
...@@ -62,7 +62,7 @@ async fn main() { ...@@ -62,7 +62,7 @@ async fn main() {
62 .long("db-port") 62 .long("db-port")
63 .env("DATABASE_PORT") 63 .env("DATABASE_PORT")
64 .help("Database port") 64 .help("Database port")
65 .required(true) 65 .required(true),
66 ) 66 )
67 .arg( 67 .arg(
68 Arg::new("retention_days") 68 Arg::new("retention_days")
...@@ -70,7 +70,7 @@ async fn main() { ...@@ -70,7 +70,7 @@ async fn main() {
70 .long("retention-days") 70 .long("retention-days")
71 .env("RETENTION_DAYS") 71 .env("RETENTION_DAYS")
72 .help("Number of days to retain data") 72 .help("Number of days to retain data")
73 .required(true) 73 .required(true),
74 ) 74 )
75 .arg( 75 .arg(
76 Arg::new("file_batch_size") 76 Arg::new("file_batch_size")
...@@ -84,13 +84,13 @@ async fn main() { ...@@ -84,13 +84,13 @@ async fn main() {
84 Arg::new("remove_posts") 84 Arg::new("remove_posts")
85 .long("remove-posts") 85 .long("remove-posts")
86 .help("Wipe posts older than timestamp") 86 .help("Wipe posts older than timestamp")
87 .required(false) 87 .required(false),
88 ) 88 )
89 .arg( 89 .arg(
90 Arg::new("dry_run") 90 Arg::new("dry_run")
91 .long("dry-run") 91 .long("dry-run")
92 .help("Perform a dry run without making any changes") 92 .help("Perform a dry run without making any changes")
93 .required(false) 93 .required(false),
94 ) 94 )
95 .get_matches(); 95 .get_matches();
96 96
...@@ -105,9 +105,13 @@ async fn main() { ...@@ -105,9 +105,13 @@ async fn main() {
105 let remove_posts = matches.contains_id("remove_posts"); 105 let remove_posts = matches.contains_id("remove_posts");
106 let dry_run = matches.contains_id("dry_run"); 106 let dry_run = matches.contains_id("dry_run");
107 107
108 let retention_days = retention_days.parse::<i64>().expect("fucking hell retention"); 108 let retention_days = retention_days
109 let file_batch_size = file_batch_size.parse::<usize>().expect("fucking hell retention"); 109 .parse::<i64>()
110 //let file_batch_size = file_batch_size.parse::<usize>().expect("fucking hell retention"); 110 .expect("fucking hell retention");
111 let file_batch_size = file_batch_size
112 .parse::<usize>()
113 .expect("fucking hell batch size");
114
111 if let Err(err) = clean( 115 if let Err(err) = clean(
112 mattermost_data_directory, 116 mattermost_data_directory,
113 database_name, 117 database_name,
...@@ -119,7 +123,9 @@ async fn main() { ...@@ -119,7 +123,9 @@ async fn main() {
119 file_batch_size, 123 file_batch_size,
120 remove_posts, 124 remove_posts,
121 dry_run, 125 dry_run,
122 ).await { 126 )
127 .await
128 {
123 error!("Cleaning operation failed: {}", err); 129 error!("Cleaning operation failed: {}", err);
124 } else { 130 } else {
125 info!("Cleaning operation completed successfully."); 131 info!("Cleaning operation completed successfully.");
...@@ -152,7 +158,9 @@ pub async fn clean( ...@@ -152,7 +158,9 @@ pub async fn clean(
152 database_user, database_password, database_host, database_port, database_name 158 database_user, database_password, database_host, database_port, database_name
153 ); 159 );
154 trace!("Connection string: {}", &connection_string); 160 trace!("Connection string: {}", &connection_string);
155 let (client, connection) = tokio_postgres::connect(&connection_string, NoTls).await.context("Failed to connect to the database")?; 161 let (client, connection) = tokio_postgres::connect(&connection_string, NoTls)
162 .await
163 .context("Failed to connect to the database")?;
156 164
157 tokio::spawn(async move { 165 tokio::spawn(async move {
158 if let Err(e) = connection.await { 166 if let Err(e) = connection.await {
...@@ -163,7 +171,14 @@ pub async fn clean( ...@@ -163,7 +171,14 @@ pub async fn clean(
163 info!("Connection established: OK"); 171 info!("Connection established: OK");
164 let millisecond_epoch = (Utc::now() - chrono::Duration::days(retention_days)).timestamp_millis(); 172 let millisecond_epoch = (Utc::now() - chrono::Duration::days(retention_days)).timestamp_millis();
165 173
166 clean_files(&client, millisecond_epoch, mattermost_data_directory, file_batch_size, dry_run).await?; 174 clean_files(
175 &client,
176 millisecond_epoch,
177 mattermost_data_directory,
178 file_batch_size,
179 dry_run,
180 )
181 .await?;
167 delete_file_info_rows(&client, millisecond_epoch, dry_run).await?; 182 delete_file_info_rows(&client, millisecond_epoch, dry_run).await?;
168 if remove_posts { 183 if remove_posts {
169 delete_post_rows(&client, millisecond_epoch, dry_run).await?; 184 delete_post_rows(&client, millisecond_epoch, dry_run).await?;
...@@ -192,7 +207,8 @@ async fn clean_files( ...@@ -192,7 +207,8 @@ async fn clean_files(
192 file_batch_size, 207 file_batch_size,
193 batch, 208 batch,
194 dry_run, 209 dry_run,
195 ).await?; 210 )
211 .await?;
196 batch += 1; 212 batch += 1;
197 } 213 }
198 214
...@@ -214,13 +230,14 @@ async fn clean_files_batch( ...@@ -214,13 +230,14 @@ async fn clean_files_batch(
214 OFFSET $2 230 OFFSET $2
215 LIMIT $3; 231 LIMIT $3;
216 "; 232 ";
217 trace!("Querying: {}",&query); 233 trace!("Querying: {}", &query);
218 let offset = (batch * file_batch_size) as i64; 234 let offset = (batch * file_batch_size) as i64;
219 let limit = file_batch_size as i64; 235 let limit = file_batch_size as i64;
220 trace!("params: {} {} {}",&millisecond_epoch, &offset, &limit); 236 trace!("params: {} {} {}", &millisecond_epoch, &offset, &limit);
221 let rows = client 237 let rows = client
222 .query(query, &[&millisecond_epoch, &offset, &limit]) 238 .query(query, &[&millisecond_epoch, &offset, &limit])
223 .await.context("Failed to fetch file info rows")?; 239 .await
240 .context("Failed to fetch file info rows")?;
224 241
225 let mut more_results = false; 242 let mut more_results = false;
226 243
...@@ -231,23 +248,38 @@ async fn clean_files_batch( ...@@ -231,23 +248,38 @@ async fn clean_files_batch(
231 let preview_path: String = row.get("previewpath"); 248 let preview_path: String = row.get("previewpath");
232 249
233 if dry_run { 250 if dry_run {
234 info!("[DRY RUN] Would remove: {:?}, {:?}, {:?}", path, thumbnail_path, preview_path); 251 info!(
252 "[DRY RUN] Would remove: {:?}, {:?}, {:?}",
253 path, thumbnail_path, preview_path
254 );
235 } else { 255 } else {
236 remove_files(mattermost_data_directory, &path, &thumbnail_path, &preview_path).context("Failed to remove files")?; 256 remove_files(
257 mattermost_data_directory,
258 &path,
259 &thumbnail_path,
260 &preview_path,
261 )
262 .context("Failed to remove files")?;
237 } 263 }
238 } 264 }
239 265
240 Ok(more_results) 266 Ok(more_results)
241 } 267 }
242 268
243 fn remove_files(base_dir: &str, path: &str, thumbnail_path: &str, preview_path: &str) -> Result<()> { 269 fn remove_files(
270 base_dir: &str,
271 path: &str,
272 thumbnail_path: &str,
273 preview_path: &str,
274 ) -> Result<()> {
244 let files = [path, thumbnail_path, preview_path]; 275 let files = [path, thumbnail_path, preview_path];
245 let mut num_deleted = 0; 276 let mut num_deleted = 0;
246 for file in files { 277 for file in files {
247 if !file.is_empty() { 278 if !file.is_empty() {
248 let full_path = Path::new(base_dir).join(file); 279 let full_path = Path::new(base_dir).join(file);
249 if full_path.exists() { 280 if full_path.exists() {
250 fs::remove_file(full_path.clone()).context(format!("Failed to delete file: {:?}", &full_path))?; 281 fs::remove_file(full_path.clone())
282 .context(format!("Failed to delete file: {:?}", &full_path))?;
251 trace!("Removed: {:#?} ", &full_path); 283 trace!("Removed: {:#?} ", &full_path);
252 num_deleted += 1; 284 num_deleted += 1;
253 } else { 285 } else {
...@@ -256,25 +288,35 @@ fn remove_files(base_dir: &str, path: &str, thumbnail_path: &str, preview_path: ...@@ -256,25 +288,35 @@ fn remove_files(base_dir: &str, path: &str, thumbnail_path: &str, preview_path:
256 } 288 }
257 } 289 }
258 if num_deleted > 0 { 290 if num_deleted > 0 {
259 info!("Deleted: {} files. Main file: {}",num_deleted,path); 291 info!("Deleted: {} files. Main file: {}", num_deleted, path);
260 } else { 292 } else {
261 trace!("No files to be deleted"); 293 trace!("No files to be deleted");
262 } 294 }
263 Ok(()) 295 Ok(())
264 } 296 }
265 297
266 async fn delete_file_info_rows(client: &Client, millisecond_epoch: i64, dry_run: bool) -> Result<()> { 298 async fn delete_file_info_rows(
299 client: &Client,
300 millisecond_epoch: i64,
301 dry_run: bool,
302 ) -> Result<()> {
267 let query = " 303 let query = "
268 DELETE FROM fileinfo 304 DELETE FROM fileinfo
269 WHERE createat < $1; 305 WHERE createat < $1;
270 "; 306 ";
271 trace!("Querying: {}",&query); 307 trace!("Querying: {}", &query);
272 trace!("Params: {:#?}",&millisecond_epoch); 308 trace!("Params: {:#?}", &millisecond_epoch);
273 if dry_run { 309 if dry_run {
274 info!("[DRY RUN] Would delete file info rows older than {}", millisecond_epoch); 310 info!(
311 "[DRY RUN] Would delete file info rows older than {}",
312 millisecond_epoch
313 );
275 return Ok(()); 314 return Ok(());
276 } 315 }
277 let result = client.execute(query, &[&millisecond_epoch]).await.context("Failed to delete file info rows")?; 316 let result = client
317 .execute(query, &[&millisecond_epoch])
318 .await
319 .context("Failed to delete file info rows")?;
278 info!("Removed {} file information rows", result); 320 info!("Removed {} file information rows", result);
279 Ok(()) 321 Ok(())
280 } 322 }
...@@ -284,13 +326,19 @@ async fn delete_post_rows(client: &Client, millisecond_epoch: i64, dry_run: bool ...@@ -284,13 +326,19 @@ async fn delete_post_rows(client: &Client, millisecond_epoch: i64, dry_run: bool
284 DELETE FROM posts 326 DELETE FROM posts
285 WHERE createat < $1; 327 WHERE createat < $1;
286 "; 328 ";
287 trace!("Querying: {}",&query); 329 trace!("Querying: {}", &query);
288 trace!("Params: {:#?}",&millisecond_epoch); 330 trace!("Params: {:#?}", &millisecond_epoch);
289 if dry_run { 331 if dry_run {
290 info!("[DRY RUN] Would delete post rows older than {}", millisecond_epoch); 332 info!(
333 "[DRY RUN] Would delete post rows older than {}",
334 millisecond_epoch
335 );
291 return Ok(()); 336 return Ok(());
292 } 337 }
293 let result = client.execute(query, &[&millisecond_epoch]).await.context("Failed to delete post rows")?; 338 let result = client
339 .execute(query, &[&millisecond_epoch])
340 .await
341 .context("Failed to delete post rows")?;
294 info!("Removed {} post rows", result); 342 info!("Removed {} post rows", result);
295 Ok(()) 343 Ok(())
296 } 344 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!