using Grpc.Core; using MxGateway.Contracts.Proto; namespace MxGateway.Client; /// /// gRPC implementation of IMxGatewayClientTransport. /// internal sealed class GrpcMxGatewayClientTransport( MxGatewayClientOptions options, MxAccessGateway.MxAccessGatewayClient rawClient) : IMxGatewayClientTransport { /// /// Gets the gateway client options. /// public MxGatewayClientOptions Options { get; } = options; /// /// Gets the underlying gRPC client. /// public MxAccessGateway.MxAccessGatewayClient RawClient { get; } = rawClient; /// MxAccessGateway.MxAccessGatewayClient? IMxGatewayClientTransport.RawClient => RawClient; /// public async Task OpenSessionAsync( OpenSessionRequest request, CallOptions callOptions) { try { return await RawClient.OpenSessionAsync(request, callOptions) .ResponseAsync .ConfigureAwait(false); } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, callOptions.CancellationToken); } } /// public async Task CloseSessionAsync( CloseSessionRequest request, CallOptions callOptions) { try { return await RawClient.CloseSessionAsync(request, callOptions) .ResponseAsync .ConfigureAwait(false); } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, callOptions.CancellationToken); } } /// public async Task InvokeAsync( MxCommandRequest request, CallOptions callOptions) { try { return await RawClient.InvokeAsync(request, callOptions) .ResponseAsync .ConfigureAwait(false); } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, callOptions.CancellationToken); } } /// public async IAsyncEnumerable StreamEventsAsync( StreamEventsRequest request, CallOptions callOptions, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) { CancellationToken effectiveCancellationToken = cancellationToken.CanBeCanceled ? cancellationToken : callOptions.CancellationToken; using AsyncServerStreamingCall call = RawClient.StreamEvents(request, callOptions); IAsyncStreamReader responseStream = call.ResponseStream; while (true) { MxEvent? gatewayEvent; try { if (!await responseStream.MoveNext(effectiveCancellationToken).ConfigureAwait(false)) { break; } gatewayEvent = responseStream.Current; } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, effectiveCancellationToken); } yield return gatewayEvent; } } /// IAsyncEnumerable IMxGatewayClientTransport.StreamEventsAsync( StreamEventsRequest request, CallOptions callOptions) { return StreamEventsAsync(request, callOptions); } /// public async Task AcknowledgeAlarmAsync( AcknowledgeAlarmRequest request, CallOptions callOptions) { try { return await RawClient.AcknowledgeAlarmAsync(request, callOptions) .ResponseAsync .ConfigureAwait(false); } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, callOptions.CancellationToken); } } /// public async IAsyncEnumerable StreamAlarmsAsync( StreamAlarmsRequest request, CallOptions callOptions, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) { CancellationToken effectiveCancellationToken = cancellationToken.CanBeCanceled ? cancellationToken : callOptions.CancellationToken; using AsyncServerStreamingCall call = RawClient.StreamAlarms(request, callOptions); IAsyncStreamReader responseStream = call.ResponseStream; while (true) { AlarmFeedMessage? message; try { if (!await responseStream.MoveNext(effectiveCancellationToken).ConfigureAwait(false)) { break; } message = responseStream.Current; } catch (RpcException exception) { throw RpcExceptionMapper.Map(exception, effectiveCancellationToken); } yield return message; } } /// IAsyncEnumerable IMxGatewayClientTransport.StreamAlarmsAsync( StreamAlarmsRequest request, CallOptions callOptions) { return StreamAlarmsAsync(request, callOptions); } }