using Cleanuparr.Persistence; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace Cleanuparr.Infrastructure.Events; /// /// Background service that periodically cleans up old events /// public class EventCleanupService : BackgroundService { private readonly ILogger _logger; private readonly IServiceScopeFactory _scopeFactory; private readonly TimeSpan _cleanupInterval = TimeSpan.FromHours(4); // Run every 4 hours private readonly int _retentionDays = 30; // Keep events for 30 days public EventCleanupService(ILogger logger, IServiceScopeFactory scopeFactory) { _logger = logger; _scopeFactory = scopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("Event cleanup service started. Interval: {interval}, Retention: {retention} days", _cleanupInterval, _retentionDays); while (!stoppingToken.IsCancellationRequested) { try { if (stoppingToken.IsCancellationRequested) { break; } await PerformCleanupAsync(); await Task.Delay(_cleanupInterval, stoppingToken); } catch (OperationCanceledException) { // Service is stopping break; } catch (Exception ex) { _logger.LogError(ex, "Error during event cleanup"); } } _logger.LogInformation("Event cleanup service stopped"); } private async Task PerformCleanupAsync() { try { await using var scope = _scopeFactory.CreateAsyncScope(); var context = scope.ServiceProvider.GetRequiredService(); var cutoffDate = DateTime.UtcNow.AddDays(-_retentionDays); await context.Events .Where(e => e.Timestamp < cutoffDate) .ExecuteDeleteAsync(); } catch (Exception ex) { _logger.LogError(ex, "Failed to perform event cleanup"); } } public override async Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Event cleanup service stopping..."); await base.StopAsync(cancellationToken); } }