Files
2026-01-30 11:18:56 -03:00

73 lines
2.9 KiB
C#

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using MotoresArgentinosV2.Infrastructure.Data;
namespace MotoresArgentinosV2.Infrastructure.Services;
public class TokenCleanupService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<TokenCleanupService> _logger;
private readonly TimeSpan _cleanupInterval = TimeSpan.FromHours(24); // Ejecutar cada 24hs
public TokenCleanupService(IServiceProvider serviceProvider, ILogger<TokenCleanupService> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Servicio de Limpieza de Tokens iniciado.");
while (!stoppingToken.IsCancellationRequested)
{
try
{
await CleanExpiredTokensAsync(stoppingToken);
// Esperar hasta la próxima ejecución
await Task.Delay(_cleanupInterval, stoppingToken);
}
catch (OperationCanceledException)
{
// El servicio se está deteniendo, es normal
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error durante la limpieza de tokens.");
// Si hay un error, esperamos un poco antes de reintentar (evitar bucle infinito de errores)
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
}
}
private async Task CleanExpiredTokensAsync(CancellationToken stoppingToken)
{
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<MotoresV2DbContext>();
// Definir criterios de limpieza
var cutoffDate = DateTime.UtcNow; // Tokens ya expirados
var revokedCutoff = DateTime.UtcNow.AddDays(-30); // Tokens revocados hace más de 30 días (auditoría)
_logger.LogInformation("Ejecutando limpieza de RefreshTokens expirados o antiguos...");
// Opción 1: Borrado con SQL Raw para eficiencia en lotes grandes
// Asumimos que la tabla se llama 'RefreshTokens' en la DB
var rowsAffected = await context.Database.ExecuteSqlRawAsync(
"DELETE FROM [RefreshTokens] WHERE [Expires] < @cutoffDate OR ([Revoked] IS NOT NULL AND [Revoked] < @revokedCutoff)",
new[] {
new Microsoft.Data.SqlClient.SqlParameter("@cutoffDate", cutoffDate),
new Microsoft.Data.SqlClient.SqlParameter("@revokedCutoff", revokedCutoff)
},
stoppingToken);
_logger.LogInformation("Limpieza completada. {Count} tokens eliminados.", rowsAffected);
}
}
}