using OpenIddict.Abstractions; namespace PrivaPub.Api.Mastodon.Auth { public class OAuthPruner : BackgroundService { static readonly TimeSpan Interval = TimeSpan.FromHours(6); static readonly TimeSpan Threshold = TimeSpan.FromDays(14); readonly IServiceProvider _services; readonly ILogger _logger; public OAuthPruner(IServiceProvider services, ILogger logger) { _services = services; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { try { await Task.Delay(Interval, stoppingToken); var (tokens, authorizations) = await Prune(DateTimeOffset.UtcNow - Threshold, stoppingToken); if (tokens + authorizations > 0) _logger.LogInformation("{Service} removed {Tokens} tokens and {Authorizations} authorizations", nameof(OAuthPruner), tokens, authorizations); } catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) { return; } catch (Exception ex) { _logger.LogWarning(ex, "{Service} pass failed", nameof(OAuthPruner)); } } } //one pass: tokens and authorizations created before the threshold that are no longer valid public async Task<(long Tokens, long Authorizations)> Prune(DateTimeOffset threshold, CancellationToken token) { using var scope = _services.CreateScope(); var tokens = await scope.ServiceProvider.GetRequiredService().PruneAsync(threshold, token); var authorizations = await scope.ServiceProvider.GetRequiredService().PruneAsync(threshold, token); return (tokens, authorizations); } } }