Esempio n. 1
0
        public static async Task <TChRspEnvelope> HandleChannelRequest <TReq, TRsp, TChReq, TChRsp, TChRspEnvelope>(
            Container container,
            IMapper mapper,
            ServerCallContext ctx,
            string serverId,
            CqrsInfo info,
            TChReq chReq,
            CancellationToken cancellationToken = default)
        {
            GrpcResponseEnvelope <TRsp> rsp = null;
            Exception exception             = null;

            // get logger
            var logger = (container.TryGetInstance(typeof(ILoggerFactory)) as ILoggerFactory)?.CreateLogger("CqrsGrpcServer");

            // get aspect
            var aspect = container.TryGetInstance(typeof(IGrpcServerAspect)) as IGrpcServerAspect;

            // call recieved
            aspect?.OnCallRecieved(ctx);

            // name
            var name = chReq?.GetType()?.Name ?? "Unknown";

            var watch = Stopwatch.StartNew();

            try
            {
                // before execution
                logger?.LogDebug("Request {requestName} started on server {serverId}.", name, serverId);
                var req = mapper.Map <TReq>(chReq);
                aspect?.BeforeExecution(req);

                // execution function
                Func <Task <GrpcResponseEnvelope <TRsp> > > execFnc = () =>
                {
                    var processor = container.GetInstance <IGrpcCqrsServerProcessor>();
                    return(Task.Run(async() => await processor.ProcessRequestAsync <TReq, TRsp>(req, info, cancellationToken)));
                };

                // execute
                rsp = await(aspect != null ? aspect.ExecuteAsync(container, execFnc) : execFnc.Invoke());

                // execution completed
                var chRsp = mapper.Map <TChRspEnvelope>(rsp);
                watch.Stop();
                logger?.LogInformation("Request {requestName} completed on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds);
                return(chRsp);
            }
            catch (ValidationErrorResponseException e)
            {
                exception = e;
                watch.Stop();
                logger.LogInformation("Request {requestName} validation error on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds);

                rsp = new GrpcResponseEnvelope <TRsp>
                {
                    IsValidationError = true,
                    ValidationError   = e.Response
                };
                var chRsp = mapper.Map <TChRspEnvelope>(rsp);
                return(chRsp);
            }
            catch (Exception e)
            {
                exception = e;
                watch.Stop();
                logger.LogError(e, "Request {requestName} failed on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds);

                rsp = new GrpcResponseEnvelope <TRsp>
                {
                    IsExecutionError = true,
                    ErrorMessage     = e.Message
                };
                var chRsp = mapper.Map <TChRspEnvelope>(rsp);
                return(chRsp);
            }
            finally
            {
                aspect?.AfterExecution(rsp, exception);
            }
        }
Esempio n. 2
0
        private async Task <GrpcResponseEnvelope <TResponse> > CallUnaryMethodAsync <TRequest, TResponse, TChRequest, TChResponse, TChResponseEnvelope>(TRequest req, CancellationToken ct)
            where TRequest : class
            where TChRequest : class
            where TChResponseEnvelope : class
        {
            GrpcResponseEnvelope <TResponse> rsp = null;
            Exception exception = null;
            var       reqName   = req.GetType().Name;

            var watch = Stopwatch.StartNew();

            try
            {
                _logger?.LogDebug("Request {requestName} started on client {clientId} for host {host}.", reqName, Id, Host);
                var chReq = _mapper.Map <TChRequest>(req);
                _clientAspect?.BeforeExecution(req);
                var chRsp = await CallUnaryMethodChannelAsync <TChRequest, TChResponseEnvelope>(chReq, ct);

                rsp = _mapper.Map <GrpcResponseEnvelope <TResponse> >(chRsp);
                watch.Stop();

                // execution error
                if (rsp.IsExecutionError)
                {
                    _logger?.LogError("Request {requestName} failed on client {clientId} with host {host} execution error. Call duration was {durationMs}ms.", reqName, Id, Host, watch.ElapsedMilliseconds);
                    throw new GrpcClientExecutionException($"Execution error: {rsp.ErrorMessage}");
                }

                // data validation error
                if (rsp.IsValidationError)
                {
                    _logger?.LogInformation("Request {requestName} completed on client {clientId} with host {host} validation error. Call duration was {durationMs}ms.", reqName, Id, Host, watch.ElapsedMilliseconds);
                    throw new ValidationErrorResponseException(rsp.ValidationError);
                }

                // no error
                return(rsp);
            }
            catch (ValidationErrorResponseException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                exception = e;
                watch.Stop();
                _logger?.LogError(e, "Request {requestName} failed on client {clientId} for host {host}. Call duration was {durationMs}ms.", reqName, Id, Host, watch.ElapsedMilliseconds);

                // do not handle exceptions
                if (!_configuration.HandleExceptions)
                {
                    throw;
                }

                // handled exception
                rsp = new GrpcResponseEnvelope <TResponse>
                {
                    IsExecutionError = true,
                    ErrorMessage     = e.Message
                };
                return(rsp);
            } finally
            {
                _clientAspect?.AfterExecution(rsp, exception);
            }
        }