63 lines
No EOL
1.9 KiB
C#
63 lines
No EOL
1.9 KiB
C#
using System.Net.Http.Json;
|
|
using DataTransfer.Client.Shared;
|
|
|
|
namespace DataTransfer.Client.Services;
|
|
|
|
/// <summary>Periodically fetches the load of the relay server; shared by all components of the page.</summary>
|
|
public sealed class ServerStatusMonitor(HttpClient http, ILogger<ServerStatusMonitor> logger) : IDisposable
|
|
{
|
|
private static readonly TimeSpan PollInterval = TimeSpan.FromSeconds(5);
|
|
|
|
private readonly CancellationTokenSource _stopping = new();
|
|
private Task? _polling;
|
|
|
|
public event Action? Changed;
|
|
|
|
/// <summary>The latest status, or <c>null</c> while it is unknown.</summary>
|
|
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<ServerStatus>(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) { }
|
|
}
|
|
} |