Skip to content

Commit

Permalink
Add data clients to health check, where a failing data client will pu…
Browse files Browse the repository at this point in the history
…t the overall API into `Degraded`
  • Loading branch information
NixFey committed Dec 25, 2024
1 parent 95e1c80 commit ee6b8d3
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 4 deletions.
2 changes: 1 addition & 1 deletion FiMAdminApi.Data/Enums/DataSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ public enum DataSources
FrcEvents,
BlueAlliance,
FtcEvents,
OrangeAlliance
//OrangeAlliance
}
9 changes: 9 additions & 0 deletions FiMAdminApi/Clients/BlueAllianceDataClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ public Task<List<QualRanking>> GetQualRankingsForEvent(Data.Models.Event evt)
throw new NotImplementedException();
}

public async Task<string?> CheckHealth()
{
var resp = await PerformRequest(BuildGetRequest($"status"));

if (resp.IsSuccessStatusCode) return null;

return await resp.Content.ReadAsStringAsync();
}

private static string GetDistrictKey(Season season, string districtName)
{
return char.IsDigit(districtName[0]) ? districtName : $"{season.StartTime.Year}{districtName}";
Expand Down
17 changes: 17 additions & 0 deletions FiMAdminApi/Clients/ClientHealthCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using FiMAdminApi.Data.Enums;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace FiMAdminApi.Clients;

public class ClientHealthCheck(IServiceProvider services, DataSources source) : IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = new())
{
var dataClient = services.GetKeyedService<IDataClient>(source);
if (dataClient is null) return HealthCheckResult.Degraded("Unable to create instance of client");

var result = await dataClient.CheckHealth();
return result == null ? HealthCheckResult.Healthy() : HealthCheckResult.Degraded(result);
}
}
12 changes: 12 additions & 0 deletions FiMAdminApi/Clients/ClientsStartupExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FiMAdminApi.Data.Enums;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace FiMAdminApi.Clients;

Expand All @@ -17,4 +18,15 @@ public static void AddClients(this IServiceCollection services)
services.AddKeyedScoped<IDataClient, FtcEventsDataClient>(DataSources.FtcEvents);
services.AddScoped<BlueAllianceWriteClient>();
}

public static IHealthChecksBuilder AddClientHealthChecks(this IHealthChecksBuilder builder)
{
foreach (var source in Enum.GetValues<DataSources>())
{
builder.AddTypeActivatedCheck<ClientHealthCheck>(source.ToString(), HealthStatus.Degraded,
new[] { "DataClient" }, source);
}

return builder;
}
}
9 changes: 9 additions & 0 deletions FiMAdminApi/Clients/FrcEventsDataClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ public async Task<List<QualRanking>> GetQualRankingsForEvent(Data.Models.Event e
}).ToList();
}

public async Task<string?> CheckHealth()
{
var resp = await PerformRequest(BuildGetRequest($""));

if (resp.IsSuccessStatusCode) return null;

return await resp.Content.ReadAsStringAsync();
}

private async Task<IEnumerable<Event>> GetAndParseEvents(Season season, string? eventCode = null, string? districtCode = null)
{
var queryParams = new Dictionary<string, string>();
Expand Down
9 changes: 9 additions & 0 deletions FiMAdminApi/Clients/FtcEventsDataClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ public Task<List<QualRanking>> GetQualRankingsForEvent(Data.Models.Event evt)
{
throw new NotImplementedException();
}

public async Task<string?> CheckHealth()
{
var resp = await PerformRequest(BuildGetRequest($""));

if (resp.IsSuccessStatusCode) return null;

return await resp.Content.ReadAsStringAsync();
}

private static string GetSeason(Season season)
{
Expand Down
1 change: 1 addition & 0 deletions FiMAdminApi/Clients/IDataClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ public interface IDataClient
public Task<List<ScheduledMatch>> GetQualScheduleForEvent(Data.Models.Event evt);
public Task<List<MatchResult>> GetQualResultsForEvent(Data.Models.Event evt);
public Task<List<QualRanking>> GetQualRankingsForEvent(Data.Models.Event evt);
public Task<string?> CheckHealth();
}
10 changes: 7 additions & 3 deletions FiMAdminApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
builder.Services.AddDataProtection().PersistKeysToFileSystem(dirInfo);
}

builder.Services.AddHealthChecks().AddNpgSql(builder.Configuration.GetConnectionString("fimDbConnection") ??
throw new Exception("DB Connection string was null"), name: "Database");
builder.Services.AddHealthChecks()
.AddNpgSql(builder.Configuration.GetConnectionString("fimDbConnection") ??
throw new Exception("DB Connection string was null"), name: "Database")
.AddClientHealthChecks();

var key = builder.Configuration["Supabase:ServiceKey"];
var supabaseUrl = builder.Configuration["Supabase:BaseUrl"];
Expand Down Expand Up @@ -105,7 +107,9 @@
app.UseOutputCache();
app.UseApiConfiguration();

app.UseHttpsRedirection();
if (!bool.TryParse(app.Configuration["RUNNING_IN_CONTAINER"], out var inContainer) ||
!inContainer)
app.UseHttpsRedirection();
app.UseCors();

app.UseApiDocumentation();
Expand Down

0 comments on commit ee6b8d3

Please sign in to comment.