using System.Net.Http.Json;
using DataTransfer.Client.Shared;
namespace DataTransfer.Client.Services;
/// Periodically fetches the load of the relay server; shared by all components of the page.
public sealed class ServerStatusMonitor(HttpClient http, ILogger logger) : IDisposable
{
private static readonly TimeSpan PollInterval = TimeSpan.FromSeconds(5);
private readonly CancellationTokenSource _stopping = new();
private Task? _polling;
public event Action? Changed;
/// The latest status, or null while it is unknown.
public ServerStatus? Current { get; private set; }
public void EnsureStarted() => _polling ??= PollAsync(_stopping.Token);
public async Task RefreshAsync(CancellationToken cancellationToken = default)
{
ServerStatus? status;
try
{
status = await http.GetFromJsonAsync(TransferProtocol.StatusPath.TrimStart('/'), cancellationToken);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
return;
}
catch (Exception ex)
{
logger.LogDebug(ex, "Fetching the server status failed");
status = null;
}
if (status != Current)
{
Current = status;
Changed?.Invoke();
}
}
public void Dispose()
{
_stopping.Cancel();
_stopping.Dispose();
}
private async Task PollAsync(CancellationToken cancellationToken)
{
using var timer = new PeriodicTimer(PollInterval);
try
{
do
{
await RefreshAsync(cancellationToken);
} while (await timer.WaitForNextTickAsync(cancellationToken));
}
catch (OperationCanceledException) { }
}
}