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, banService *services.BanService) 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) } cleanedUploads, err := uploadService.CleanupExpiredResumableSessions(time.Now().UTC()) if err != nil { logger.Warn("resumable upload cleanup failed", "source", "housekeeping", "severity", "warn", "code", 4204, "error", err.Error()) return } if cleanedUploads > 0 { logger.Info("resumable uploads cleaned", "source", "housekeeping", "severity", "user_activity", "code", 2204, "cleaned", cleanedUploads) } if banService != nil { cleanedEvents, err := banService.CleanupAbuseEvents(time.Now().UTC()) if err != nil { logger.Warn("ban evidence cleanup failed", "source", "housekeeping", "severity", "warn", "code", 4203, "error", err.Error()) return } if cleanedEvents > 0 { logger.Info("ban evidence cleaned", "source", "housekeeping", "severity", "user_activity", "code", 2203, "cleaned", cleanedEvents) } } }, } } func RunCleanupNow(uploadService *services.UploadService, logger *slog.Logger) (int, error) { cleaned, err := cleanupUnavailableBoxes(uploadService, logger) if err != nil { return cleaned, err } cleanedUploads, err := uploadService.CleanupExpiredResumableSessions(time.Now().UTC()) return cleaned + cleanedUploads, err } 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 }