< Summary

Line coverage
56%
Covered lines: 17
Uncovered lines: 13
Coverable lines: 30
Total lines: 219
Line coverage: 56.6%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .cctor()100%11100%
File 2: .ctor(...)100%11100%
File 2: ExecuteAsync()0%620%
File 2: RunCleanupAsync()100%11100%

File(s)

/home/runner/work/anichron/anichron/src/.artifacts/obj/Anichron.Worker/debug/Microsoft.Extensions.Logging.Generators/Microsoft.Extensions.Logging.Generators.LoggerMessageGenerator/LoggerMessage.g.cs

File '/home/runner/work/anichron/anichron/src/.artifacts/obj/Anichron.Worker/debug/Microsoft.Extensions.Logging.Generators/Microsoft.Extensions.Logging.Generators.LoggerMessageGenerator/LoggerMessage.g.cs' does not exist (any more).

/home/runner/work/anichron/anichron/src/Anichron.Worker/Maintenance/TokenCleanupService.cs

#LineLine coverage
 1using Anichron.Core.Data.Repository;
 2using Anichron.Worker.Settings;
 3using Microsoft.Extensions.Options;
 4using NodaTime;
 5
 6namespace Anichron.Worker.Maintenance;
 7
 48public sealed partial class TokenCleanupService(
 49    IServiceScopeFactory scopeFactory,
 410    IClock clock,
 411    IOptions<WorkerSettings> options,
 412    ILogger<TokenCleanupService> logger) : BackgroundService
 13{
 414    private readonly WorkerSettings settings = options.Value;
 15
 16    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
 017    {
 018        using var timer = new PeriodicTimer(TimeSpan.FromHours(settings.TokenCleanupIntervalHours));
 19        do
 020        {
 21            try
 022            {
 023                await RunCleanupAsync(stoppingToken);
 024            }
 025            catch (Exception ex) when (ex is not OperationCanceledException)
 026            {
 027                Log.CleanupFailed(logger, ex);
 028            }
 029        }
 030        while (await timer.WaitForNextTickAsync(stoppingToken));
 031    }
 32
 33    internal async Task RunCleanupAsync(CancellationToken ct)
 434    {
 435        using var scope = scopeFactory.CreateScope();
 436        var repository = scope.ServiceProvider.GetRequiredService<IRefreshTokenRepository>();
 437        var now = clock.GetCurrentInstant();
 438        var deleted = await repository.DeleteExpiredAsync(now, ct);
 339        Log.TokensDeleted(logger, deleted);
 340    }
 41
 42    private static partial class Log
 43    {
 44        [LoggerMessage(Level = LogLevel.Information, Message = "Deleted {Count} expired refresh token(s).")]
 45        public static partial void TokensDeleted(ILogger logger, int count);
 46
 47        [LoggerMessage(Level = LogLevel.Error, Message = "Token cleanup failed; will retry on next tick.")]
 48        public static partial void CleanupFailed(ILogger logger, Exception ex);
 49    }
 50}