package jobs import ( "log/slog" "time" "warpbox.dev/backend/libs/config" "warpbox.dev/backend/libs/services" ) func newCleanupJob(cfg config.Config, logger *slog.Logger, uploadService *services.UploadService) job { return job{ name: "cleanup", enabled: cfg.CleanupEnabled, interval: cfg.CleanupEvery, run: func() { cleaned, err := cleanupUnavailableBoxes(uploadService, logger) if err != nil { logger.Warn("cleanup job failed", "source", "housekeeping", "severity", "warn", "code", 4202, "error", err.Error()) return } if cleaned > 0 { logger.Info("cleanup job complete", "source", "housekeeping", "severity", "user_activity", "code", 2202, "cleaned", cleaned) } }, } } func RunCleanupNow(uploadService *services.UploadService, logger *slog.Logger) (int, error) { return cleanupUnavailableBoxes(uploadService, logger) } func cleanupUnavailableBoxes(uploadService *services.UploadService, logger *slog.Logger) (int, error) { boxes, err := uploadService.ListBoxes(0) if err != nil { return 0, err } now := time.Now().UTC() cleaned := 0 for _, box := range boxes { if !shouldDeleteBox(box, now) { continue } if err := uploadService.DeleteBoxWithSource(box.ID, "housekeeping"); err != nil { return cleaned, err } cleaned++ } if cleaned > 0 { logger.Info("unavailable boxes cleaned", "source", "housekeeping", "severity", "user_activity", "code", 2201, "cleaned", cleaned) } return cleaned, nil } func shouldDeleteBox(box services.Box, now time.Time) bool { if !box.ExpiresAt.After(now) { return true } return box.MaxDownloads > 0 && box.DownloadCount >= box.MaxDownloads }