< Summary

Information
Class: Anichron.API.Infrastructure.ApplicationExtensions
Assembly: Anichron.API
File(s): /home/runner/work/anichron/anichron/src/Anichron.API/Infrastructure/ApplicationExtensions.cs
Tag: 228_36821334185
Line coverage
0%
Covered lines: 0
Uncovered lines: 38
Coverable lines: 38
Total lines: 78
Line coverage: 0%
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
MapApiEndpoints(...)100%210%
MigrateAndSeedDatabaseAsync()0%620%

File(s)

/home/runner/work/anichron/anichron/src/Anichron.API/Infrastructure/ApplicationExtensions.cs

#LineLine coverage
 1using Anichron.API.Endpoints;
 2using Anichron.API.Services;
 3using Anichron.API.Settings;
 4using Anichron.Core.Data;
 5using Anichron.Infrastructure.Data;
 6using Microsoft.AspNetCore.Diagnostics.HealthChecks;
 7
 8namespace Anichron.API.Infrastructure;
 9
 10public static partial class ApplicationExtensions
 11{
 12    extension(WebApplication app)
 13    {
 14        public WebApplication MapApiEndpoints()
 015        {
 016            app.MapHealthChecks(ApiPaths.Healthz, new HealthCheckOptions
 017            {
 018                ResponseWriter = HealthCheckResponseWriter.WriteResponseAsync
 019            }).AllowAnonymous();
 20
 021            var api = app.MapGroup(ApiPaths.Base);
 022            api.MapAuthEndpoints();
 023            api.MapUserEndpoints();
 024            api.MapAdminEndpoints();
 025            return app;
 26        }
 27
 28        public async Task MigrateAndSeedDatabaseAsync(CancellationToken ct)
 029        {
 30            const int maxAttempts = AppDefaults.Startup.MaxDbRetryAttempts;
 31            const int retryDelaySeconds = AppDefaults.Startup.DbRetryDelaySeconds;
 32
 033            for (var attempt = 1; attempt <= maxAttempts; attempt++)
 034            {
 35                try
 036                {
 037                    await using var scope = app.Services.CreateAsyncScope();
 038                    var dbContext = scope.ServiceProvider.GetRequiredService<AnichronDbContext>();
 039                    var logger = scope.ServiceProvider.GetRequiredService<ILogger<AnichronDbContext>>();
 40
 041                    await dbContext.Database.MigrateWithAdvisoryLockAsync(ct);
 042                    Log.MigrationApplied(logger);
 43
 044                    var bootstrapSeeder = scope.ServiceProvider.GetRequiredService<IBootstrapSeeder>();
 045                    await bootstrapSeeder.SeedAsync(ct);
 46
 047                    var adminResetService = scope.ServiceProvider.GetRequiredService<IBootstrapResetService>();
 048                    await adminResetService.ResetIfRequestedAsync(ct);
 049                    return;
 050                }
 051                catch (Exception ex) when (attempt < maxAttempts)
 052                {
 053                    Log.DatabaseNotReady(app.Logger, ex, attempt, maxAttempts, retryDelaySeconds);
 054                    await Task.Delay(TimeSpan.FromSeconds(retryDelaySeconds), ct);
 055                }
 056                catch (Exception ex)
 057                {
 058                    Log.DatabaseUnavailable(app.Logger, ex, AppDefaults.Startup.MaxDbRetryAttempts);
 059                    throw new InvalidOperationException(
 060                        $"Database unavailable after {AppDefaults.Startup.MaxDbRetryAttempts} attempts. Aborting.",
 061                        ex);
 62                }
 063            }
 064        }
 65    }
 66
 67    private static partial class Log
 68    {
 69        [LoggerMessage(Level = LogLevel.Information, Message = "Database migration applied successfully.")]
 70        public static partial void MigrationApplied(ILogger logger);
 71
 72        [LoggerMessage(Level = LogLevel.Warning, Message = "Database not ready (attempt {Attempt}/{Max}). Retrying in {D
 73        public static partial void DatabaseNotReady(ILogger logger, Exception ex, int attempt, int max, int delay);
 74
 75        [LoggerMessage(Level = LogLevel.Error, Message = "Database unavailable after {Max} attempts. Aborting.")]
 76        public static partial void DatabaseUnavailable(ILogger logger, Exception ex, int max);
 77    }
 78}