1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! Scheduled tasks for the database.

use chrono::{Days, Utc};
use diesel::{debug_query, pg::Pg, BoolExpressionMethods, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use log::debug;
use std::sync::Arc;

use super::connection::Pool;

use crate::schema::{layers, maps};

/// How often the deleted maps are cleaned up in seconds.
const CLEANUP_INTERVAL: u64 = 60 * 60 * 24;

/// Permanently remove deleted maps older than 30 days from the database.
/// Runs every [`CLEANUP_INTERVAL`] seconds.
pub async fn cleanup_maps(pool: Arc<Pool>) -> ! {
    loop {
        tokio::time::sleep(std::time::Duration::from_secs(CLEANUP_INTERVAL)).await;
        log::info!("Running maps cleanup...");

        let Some(one_month_ago) = Utc::now().date_naive().checked_sub_days(Days::new(30)) else {
            log::error!("Failed to calculate date one month ago");
            continue;
        };
        let query = diesel::delete(
            maps::table.filter(
                maps::deletion_date
                    .is_not_null()
                    .and(maps::deletion_date.lt(one_month_ago)),
            ),
        );
        debug!("{}", debug_query::<Pg, _>(&query));

        match pool.get().await {
            Ok(mut conn) => match query.execute(&mut conn).await {
                Ok(delete_rows) => log::info!("Removed {delete_rows} maps"),
                Err(e) => log::error!("Failed to execute query: {}", e),
            },
            Err(e) => {
                log::error!("Failed to get connection from pool: {}", e);
            }
        }
    }
}

/// Permanently remove deleted layers older than 1 day from the database.
/// TODO: increase time in the future
/// Runs every [`CLEANUP_INTERVAL`] seconds.
pub async fn cleanup_layers(pool: Arc<Pool>) -> ! {
    loop {
        tokio::time::sleep(std::time::Duration::from_secs(CLEANUP_INTERVAL)).await;

        log::info!("Running layers cleanup...");

        let one_day_ago = Utc::now().naive_utc() - chrono::Duration::days(1);
        let query = diesel::delete(
            layers::table.filter(
                layers::marked_deleted
                    .is_not_null()
                    .and(layers::marked_deleted.lt(one_day_ago)),
            ),
        );
        debug!("{}", debug_query::<Pg, _>(&query));

        match pool.get().await {
            Ok(mut conn) => match query.execute(&mut conn).await {
                Ok(delete_rows) => log::info!("Removed {delete_rows} layers"),
                Err(e) => log::error!("Failed to execute query: {}", e),
            },
            Err(e) => {
                log::error!("Failed to get connection from pool: {}", e);
            }
        }
    }
}