f2d35ca792
- JWT secret auto-generates and persists to <STORAGE_PATH>/.jwt_secret - Remove setup token: first admin setup is open until system initialized - Fix schema.sql: move CREATE EXTENSION pg_trgm/ltree to top - Update login UI and auth.js to remove setup token fields
78 lines
2.6 KiB
Rust
Executable File
78 lines
2.6 KiB
Rust
Executable File
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
use tokio::time;
|
|
use tracing::{debug, error, info, instrument};
|
|
|
|
use crate::common::errors::Result;
|
|
use crate::domain::repositories::trash_repository::TrashRepository;
|
|
use crate::infrastructure::repositories::pg::trash_db_repository::TrashDbRepository;
|
|
|
|
/// Service for automatic cleanup of expired items in the trash.
|
|
///
|
|
/// Uses `TrashRepository::delete_expired_bulk` to purge all expired items
|
|
/// in **2 SQL statements inside a single transaction**, instead of the
|
|
/// previous N+1 pattern that issued 3 queries per expired item.
|
|
pub struct TrashCleanupService {
|
|
trash_repository: Arc<TrashDbRepository>,
|
|
cleanup_interval_hours: u64,
|
|
}
|
|
|
|
impl TrashCleanupService {
|
|
pub fn new(trash_repository: Arc<TrashDbRepository>, cleanup_interval_hours: u64) -> Self {
|
|
Self {
|
|
trash_repository,
|
|
cleanup_interval_hours: cleanup_interval_hours.max(1), // Minimum 1 hour
|
|
}
|
|
}
|
|
|
|
/// Starts the periodic cleanup job
|
|
#[instrument(skip(self))]
|
|
pub async fn start_cleanup_job(&self) {
|
|
let trash_repository = self.trash_repository.clone();
|
|
let interval_hours = self.cleanup_interval_hours;
|
|
|
|
info!(
|
|
"Starting trash cleanup job with interval of {} hours",
|
|
interval_hours
|
|
);
|
|
|
|
tokio::spawn(async move {
|
|
let interval_duration = Duration::from_secs(interval_hours * 60 * 60);
|
|
let mut interval = time::interval(interval_duration);
|
|
|
|
// First immediate execution
|
|
Self::cleanup_expired_items(trash_repository.clone())
|
|
.await
|
|
.unwrap_or_else(|e| error!("Error in initial trash cleanup: {:?}", e));
|
|
|
|
loop {
|
|
interval.tick().await;
|
|
debug!("Running scheduled trash cleanup task");
|
|
|
|
if let Err(e) = Self::cleanup_expired_items(trash_repository.clone()).await {
|
|
error!("Error in scheduled trash cleanup: {:?}", e);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Bulk-delete all expired trash items in a single transaction.
|
|
#[instrument(skip(trash_repository))]
|
|
async fn cleanup_expired_items(trash_repository: Arc<TrashDbRepository>) -> Result<()> {
|
|
debug!("Starting bulk cleanup of expired trash items");
|
|
|
|
let (files, folders) = trash_repository.delete_expired_bulk().await?;
|
|
|
|
if files == 0 && folders == 0 {
|
|
debug!("No expired items to clean up");
|
|
} else {
|
|
info!(
|
|
"Trash cleanup completed: {} files + {} folders purged",
|
|
files, folders
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|