Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/backend/Modules/Common/ExternalData/Status/Endpoint.cs
T

45 lines
2.8 KiB
C#

using Dapper;
using FastEndpoints;
using Npgsql;
using Kbx.Shared.ExternalData.Generated;
using Kbx.Shared.Runtime;
namespace Kbx.Modules.Common.ExternalData.Status;
public sealed record Row(string DatasetId,string ProviderId,string SourceLabel,string State,long CacheEntries,DateTimeOffset? LastReceivedAt,DateTimeOffset? OldestFreshUntil,long StaleEntries,long UnavailableEntries);
public sealed record Response(IReadOnlyList<Row> Items);
file sealed record DbRow(string DatasetId,string ProviderId,string State,long CacheEntries,DateTimeOffset? LastReceivedAt,DateTimeOffset? OldestFreshUntil,long StaleEntries,long UnavailableEntries);
public sealed class Endpoint(NpgsqlDataSource dataSource):EndpointWithoutRequest<Response>
{
public override void Configure(){Get("/api/kbx/external-data/status");Permissions("common.external-data.read");}
public override async Task HandleAsync(CancellationToken ct)
{
const string sql="""
select dataset_id as DatasetId, provider_id as ProviderId,
case
when bool_or(fresh_until is not null and now() <= fresh_until) then 'fresh'
when bool_or(usable_until is not null and now() <= usable_until) then 'stale'
when bool_or(state='unavailable') then 'unavailable'
else 'expired'
end as State,
count(*) as CacheEntries,
max(received_at) as LastReceivedAt,
min(fresh_until) as OldestFreshUntil,
count(*) filter(where fresh_until is not null and now()>fresh_until and usable_until is not null and now()<=usable_until) as StaleEntries,
count(*) filter(where state='unavailable') as UnavailableEntries
from kbx.external_data_cache
where tenant_id=@TenantId
group by dataset_id,provider_id
""";
await using var connection=await dataSource.OpenConnectionAsync(ct);
var db=(await connection.QueryAsync<DbRow>(new CommandDefinition(sql,new{TenantId=RuntimeIdentity.TenantId(User)},cancellationToken:ct))).ToDictionary(x=>x.DatasetId,StringComparer.Ordinal);
var rows=KbxExternalDataCatalog.All.Values.OrderBy(x=>x.Id,StringComparer.Ordinal).Select(dataset=>{
if(db.TryGetValue(dataset.Id,out var current))return new Row(dataset.Id,dataset.ProviderId,dataset.SourceLabel,current.State,current.CacheEntries,current.LastReceivedAt,current.OldestFreshUntil,current.StaleEntries,current.UnavailableEntries);
var state=dataset.FreshnessMode=="provider-defined" && dataset.FreshForSeconds is null ? "unavailable" : "expired";
return new Row(dataset.Id,dataset.ProviderId,dataset.SourceLabel,state,0,null,null,0,state=="unavailable"?1:0);
}).ToArray();
await Send.OkAsync(new Response(rows),ct);
}
}