108 lines
3.9 KiB
C#
108 lines
3.9 KiB
C#
using DigitalData.Auth.Abstractions;
|
|
using Microsoft.AspNetCore.SignalR.Client;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace DigitalData.Auth.Client;
|
|
|
|
public class AuthClient : IAuthClient, IHostedService
|
|
{
|
|
private readonly HubConnection _connection;
|
|
|
|
private readonly ILogger<AuthClient>? _logger;
|
|
|
|
private readonly ClientParams _params;
|
|
|
|
public AuthClient(IOptions<ClientParams> paramsOptions, HubConnectionBuilder connectionBuilder, ILogger<AuthClient>? logger = null)
|
|
{
|
|
_params = paramsOptions.Value;
|
|
|
|
var cnnBuilder = connectionBuilder.WithUrl(_params.Url);
|
|
|
|
// set RetryPolicy if it exists
|
|
if (_params.RetryPolicy is not null)
|
|
cnnBuilder = cnnBuilder.WithAutomaticReconnect(_params.RetryPolicy);
|
|
|
|
_connection = cnnBuilder.Build();
|
|
|
|
_connection.On<string, string, string>(nameof(ReceivePublicKeyAsync), ReceivePublicKeyAsync);
|
|
|
|
_connection.Reconnected += async cnnId =>
|
|
{
|
|
_logger?.LogInformation("Auth-client reconnected. Number of connection attempts {nOfAttempts}.", _nOfAttempts);
|
|
await GetAllPublicKeysAsync();
|
|
_nOfAttempts = 0;
|
|
};
|
|
|
|
_connection.Reconnecting += (ex) =>
|
|
{
|
|
logger?.LogError(ex, "Auth-client disconnected. Attempt to reconnect every {time} seconds.", _params.RetryDelay!.Value.TotalSeconds);
|
|
_nOfAttempts += 1;
|
|
return Task.CompletedTask;
|
|
};
|
|
|
|
_logger = logger;
|
|
}
|
|
|
|
public bool IsConnected { get; private set; } = false;
|
|
|
|
public IEnumerable<ClientPublicKey> PublicKeys => _params.PublicKeys;
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
while(!await TryStartConnectionAsync(cancellationToken))
|
|
{
|
|
if (_params.RetryDelay is not null)
|
|
await Task.Delay(_params.RetryDelay.Value.Milliseconds, cancellationToken);
|
|
else
|
|
return;
|
|
}
|
|
|
|
IsConnected = true;
|
|
await GetAllPublicKeysAsync();
|
|
}
|
|
|
|
private int _nOfAttempts = 0;
|
|
|
|
private async Task<bool> TryStartConnectionAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
_nOfAttempts += 1;
|
|
await _connection.StartAsync(cancellationToken);
|
|
_logger?.LogInformation("Auth-client connection successful. Number of connection attempts {nOfAttempts}.", _nOfAttempts);
|
|
_nOfAttempts = 0;
|
|
return true;
|
|
}
|
|
catch(HttpRequestException ex)
|
|
{
|
|
if(_nOfAttempts < 2)
|
|
{
|
|
if (_params.RetryDelay is null)
|
|
_logger?.LogError(ex, "Auth-client connection failed. {message}", ex.Message);
|
|
else
|
|
_logger?.LogError(ex, "Auth-client connection failed and will be retried every {time} seconds. The status of being successful can be followed from the information logs.\n{message}", _params.RetryDelay.Value.TotalSeconds, ex.Message);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
await _connection.StopAsync(cancellationToken);
|
|
IsConnected = false;
|
|
}
|
|
|
|
public Task ReceivePublicKeyAsync(string issuer, string audience, string message) => Task.Run(() => _params.TriggerOnPublicReceivedEvent(this, issuer, audience, message, _logger));
|
|
|
|
public Task SendPublicKeyAsync(string issuer, string audience, string message) => _connection.InvokeAsync(nameof(SendPublicKeyAsync), issuer, audience, message);
|
|
|
|
public Task GetPublicKeyAsync(string issuer, string audience) => _connection.InvokeAsync(nameof(GetPublicKeyAsync), issuer, audience);
|
|
|
|
public async Task GetAllPublicKeysAsync()
|
|
{
|
|
foreach (var publicKey in PublicKeys)
|
|
await GetPublicKeyAsync(publicKey.Issuer, publicKey.Audience);
|
|
}
|
|
} |