73 lines
2.9 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|