using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Akari.Prototype.Server.Services { public class AuthLifetimeService : IHostedService { public static TimeSpan CleanupInterval => TimeSpan.FromSeconds(5); public static TimeSpan AuthLifetime => TimeSpan.FromSeconds(30); private readonly ILogger _logger; private readonly IAuthManager _authManager; private CancellationTokenSource _cleanupCancellationTokenSource; private Timer _timer; public AuthLifetimeService(ILogger logger, IAuthManager authManager) { _logger = logger; _authManager = authManager; } public Task StartAsync(CancellationToken cancellationToken) { _cleanupCancellationTokenSource = new CancellationTokenSource(); _timer = new Timer(AuthCleanup, _cleanupCancellationTokenSource.Token, CleanupInterval, CleanupInterval); _logger.LogDebug("Cleanup timer is running"); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogDebug("Stopping"); _timer?.Change(Timeout.Infinite, Timeout.Infinite); _cleanupCancellationTokenSource?.Cancel(); return Task.CompletedTask; } private void AuthCleanup(object state) { var cancellationToken = (CancellationToken)state; var date = DateTime.Now; if (cancellationToken.IsCancellationRequested) { _logger.LogDebug("Cancellation requested, aborted cleanup"); return; } _logger.LogDebug($"Running cleanup at: {date}"); foreach (var (key, value) in _authManager.Pairs) { if (cancellationToken.IsCancellationRequested) { _logger.LogDebug("Cancellation requested, aborted cleanup"); return; } if (date - value.CreationDate >= AuthLifetime) { _logger.LogDebug($"'{key}' auth expired"); _authManager.Remove(key); } } } public void Dispose() { _timer?.Dispose(); } } }