65 lines
2.6 KiB
C#
65 lines
2.6 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
public sealed class GatewayHeartbeatService : BackgroundService
|
|
{
|
|
private readonly IServiceScopeFactory _scopes;
|
|
private readonly IHttpClientFactory _http;
|
|
private readonly CentralReachabilityService _reachability;
|
|
private readonly GatewayOptions _gateway;
|
|
private readonly IConfiguration _config;
|
|
private readonly ILogger<GatewayHeartbeatService> _logger;
|
|
|
|
public GatewayHeartbeatService(
|
|
IServiceScopeFactory scopes,
|
|
IHttpClientFactory http,
|
|
CentralReachabilityService reachability,
|
|
IOptions<GatewayOptions> gateway,
|
|
IConfiguration config,
|
|
ILogger<GatewayHeartbeatService> logger)
|
|
{
|
|
_scopes = scopes;
|
|
_http = http;
|
|
_reachability = reachability;
|
|
_gateway = gateway.Value;
|
|
_config = config;
|
|
_logger = logger;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken ct)
|
|
{
|
|
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(_gateway.HeartbeatIntervalSeconds));
|
|
while (await timer.WaitForNextTickAsync(ct))
|
|
await SendHeartbeatAsync(ct);
|
|
}
|
|
|
|
private async Task SendHeartbeatAsync(CancellationToken ct)
|
|
{
|
|
await using var scope = _scopes.CreateAsyncScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
|
var bufferDepth = await db.BufferedSyncItems.CountAsync(b => !b.Synced, ct);
|
|
|
|
var status = _reachability.IsCentralReachable ? "ONLINE" : "DEGRADED";
|
|
var req = new GatewayHeartbeatRequest(status, bufferDepth, DateTimeOffset.UtcNow);
|
|
|
|
try
|
|
{
|
|
var client = _http.CreateClient("central");
|
|
client.BaseAddress = new Uri(
|
|
scope.ServiceProvider.GetRequiredService<IOptions<CentralApiOptions>>().Value.BaseUrl);
|
|
client.DefaultRequestHeaders.Remove("X-Api-Key");
|
|
client.DefaultRequestHeaders.Remove("X-Gateway-Id");
|
|
client.DefaultRequestHeaders.Add("X-Api-Key", _config["ApiKey:Gateway"]);
|
|
client.DefaultRequestHeaders.Add("X-Gateway-Id", _gateway.GatewayId.ToString());
|
|
|
|
var resp = await client.PatchAsJsonAsync(
|
|
$"/api/v1/gateways/{_gateway.GatewayId}/heartbeat", req, ct);
|
|
if (!resp.IsSuccessStatusCode)
|
|
_logger.LogWarning("Heartbeat failed: {Status}", resp.StatusCode);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Heartbeat to central failed — gateway continues in DEGRADED mode");
|
|
}
|
|
}
|
|
} |