144 lines
4.1 KiB
C#
144 lines
4.1 KiB
C#
using Grpc.Core;
|
|
using Grpc.Net.Client;
|
|
using MxGateway.Contracts.Proto;
|
|
|
|
namespace MxGateway.Client;
|
|
|
|
/// <summary>
|
|
/// Provides the .NET client entry point for the public MXAccess Gateway gRPC API.
|
|
/// </summary>
|
|
public sealed class MxGatewayClient : IAsyncDisposable
|
|
{
|
|
private readonly GrpcChannel _channel;
|
|
private readonly IMxGatewayClientTransport _transport;
|
|
private bool _disposed;
|
|
|
|
internal MxGatewayClient(
|
|
MxGatewayClientOptions options,
|
|
IMxGatewayClientTransport transport)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(options);
|
|
options.Validate();
|
|
|
|
Options = options;
|
|
_transport = transport ?? throw new ArgumentNullException(nameof(transport));
|
|
_channel = null!;
|
|
}
|
|
|
|
private MxGatewayClient(
|
|
GrpcChannel channel,
|
|
IMxGatewayClientTransport transport)
|
|
{
|
|
_channel = channel;
|
|
_transport = transport;
|
|
Options = transport.Options;
|
|
}
|
|
|
|
public MxGatewayClientOptions Options { get; }
|
|
|
|
public MxAccessGateway.MxAccessGatewayClient RawClient =>
|
|
_transport.RawClient
|
|
?? throw new InvalidOperationException("The raw generated gRPC client is not available for this client instance.");
|
|
|
|
public static MxGatewayClient Create(MxGatewayClientOptions options)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(options);
|
|
options.Validate();
|
|
|
|
var channel = GrpcChannel.ForAddress(
|
|
options.Endpoint,
|
|
new GrpcChannelOptions
|
|
{
|
|
LoggerFactory = options.LoggerFactory,
|
|
});
|
|
|
|
return new MxGatewayClient(
|
|
channel,
|
|
new GrpcMxGatewayClientTransport(
|
|
options,
|
|
new MxAccessGateway.MxAccessGatewayClient(channel)));
|
|
}
|
|
|
|
public async Task<MxGatewaySession> OpenSessionAsync(
|
|
OpenSessionRequest? request = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
OpenSessionReply reply = await OpenSessionRawAsync(
|
|
request ?? new OpenSessionRequest(),
|
|
cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
return new MxGatewaySession(this, reply);
|
|
}
|
|
|
|
public Task<OpenSessionReply> OpenSessionRawAsync(
|
|
OpenSessionRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
ThrowIfDisposed();
|
|
|
|
return _transport.OpenSessionAsync(request, CreateCallOptions(cancellationToken));
|
|
}
|
|
|
|
public Task<CloseSessionReply> CloseSessionRawAsync(
|
|
CloseSessionRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
ThrowIfDisposed();
|
|
|
|
return _transport.CloseSessionAsync(request, CreateCallOptions(cancellationToken));
|
|
}
|
|
|
|
public Task<MxCommandReply> InvokeAsync(
|
|
MxCommandRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
ThrowIfDisposed();
|
|
|
|
return _transport.InvokeAsync(request, CreateCallOptions(cancellationToken));
|
|
}
|
|
|
|
public IAsyncEnumerable<MxEvent> StreamEventsAsync(
|
|
StreamEventsRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
ThrowIfDisposed();
|
|
|
|
return _transport.StreamEventsAsync(request, CreateCallOptions(cancellationToken));
|
|
}
|
|
|
|
public ValueTask DisposeAsync()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return ValueTask.CompletedTask;
|
|
}
|
|
|
|
_disposed = true;
|
|
_channel?.Dispose();
|
|
return ValueTask.CompletedTask;
|
|
}
|
|
|
|
internal CallOptions CreateCallOptions(CancellationToken cancellationToken)
|
|
{
|
|
Metadata headers = new()
|
|
{
|
|
{ "authorization", $"Bearer {Options.ApiKey}" },
|
|
};
|
|
|
|
return new CallOptions(
|
|
headers,
|
|
DateTime.UtcNow.Add(Options.DefaultCallTimeout),
|
|
cancellationToken);
|
|
}
|
|
|
|
private void ThrowIfDisposed()
|
|
{
|
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
|
}
|
|
}
|