docbox_core/files/
purge_expired_presigned_tasks.rs

1use chrono::Utc;
2use docbox_database::{
3    DatabasePoolCache, DbPool,
4    models::{
5        presigned_upload_task::{PresignedTaskStatus, PresignedUploadTask},
6        tenant::Tenant,
7    },
8};
9use docbox_storage::{StorageLayerFactory, TenantStorageLayer};
10use std::sync::Arc;
11
12pub async fn safe_purge_expired_presigned_tasks(
13    db_cache: Arc<DatabasePoolCache>,
14    storage: StorageLayerFactory,
15) {
16    if let Err(cause) = purge_expired_presigned_tasks(db_cache, storage).await {
17        tracing::error!(?cause, "failed to purge presigned tasks");
18    }
19}
20
21pub async fn purge_expired_presigned_tasks(
22    db_cache: Arc<DatabasePoolCache>,
23    storage: StorageLayerFactory,
24) -> anyhow::Result<()> {
25    let db = db_cache.get_root_pool().await?;
26    let tenants = Tenant::all(&db).await?;
27    drop(db);
28
29    for tenant in tenants {
30        // Create the database connection pool
31        let db = db_cache.get_tenant_pool(&tenant).await?;
32        let storage = storage.create_storage_layer(&tenant);
33
34        if let Err(cause) = purge_expired_presigned_tasks_tenant(&db, &storage).await {
35            tracing::error!(
36                ?cause,
37                ?tenant,
38                "failed to purge presigned tasks for tenant"
39            );
40        }
41    }
42
43    Ok(())
44}
45
46pub async fn purge_expired_presigned_tasks_tenant(
47    db: &DbPool,
48    storage: &TenantStorageLayer,
49) -> anyhow::Result<()> {
50    let current_date = Utc::now();
51    let tasks = PresignedUploadTask::find_expired(db, current_date).await?;
52    if tasks.is_empty() {
53        return Ok(());
54    }
55
56    for task in tasks {
57        // Delete the task itself
58        if let Err(cause) = PresignedUploadTask::delete(db, task.id).await {
59            tracing::error!(?cause, "failed to delete presigned upload task")
60        }
61
62        // Delete incomplete file uploads
63        match task.status {
64            PresignedTaskStatus::Completed { .. } => {
65                // Upload completed, nothing to revert
66            }
67            PresignedTaskStatus::Failed { .. } | PresignedTaskStatus::Pending => {
68                if let Err(cause) = storage.delete_file(&task.file_key).await {
69                    tracing::error!(
70                        ?cause,
71                        "failed to delete expired presigned task file from tenant"
72                    );
73                }
74            }
75        }
76    }
77
78    Ok(())
79}