///<summary> /// actual response handling including the response handler wrapper for sync or async callback ///</summary> private async Task ResponseHandlerCallback <T, TResult>(ResponseSocket socket, ResponseHandler <T, TResult> handler, CancellationToken token) where T : class, new() where TResult : class { if (!respondingIsActive || token.IsCancellationRequested) { Dispose(); _configuration.Logger.Log(new InfoLogMsg("Task was cancelled by cancellationRequest")); return; } try { Message <TResult> response = null; try { // block on this thread for incoming requests of the type T (Request) NetMQMessage incomingRequest = socket.ReceiveMultipartMessage(); _configuration.Logger.Log(new DebugLogMsg($"handling response for [Request:{typeof(T)}] and [Response:{typeof(TResult)}]")); var actualRequestResult = incomingRequest.ParseRqRepMessage <T>(_configuration); TResult result = await handler.HandleAsync(actualRequestResult); response = new RequestReplyMessage <TResult>(_configuration, result, actualRequestResult.IsSuccess); _configuration.Logger.Log(new DebugLogMsg($"sending response for [Request:{typeof(T)}] and [Response:{typeof(TResult)}]")); } catch (System.Exception ex) { // failure to parse or any other exception leads to a non successful response, which then in turn can be handled on the request side _configuration.Logger.Log(new ErrorLogMsg($"Responding to [Request:{typeof(T)}] with [Response:{typeof(TResult)}] did fail: " + ex.Message)); var msgParts = new [] { ex.GetType().Name, ex.Message, ex.StackTrace }; var msg = Environment.NewLine + string.Join(Environment.NewLine, msgParts); response = RequestReplyMessage <TResult> .FromError(_configuration, msg); } // try send response with timeout bool noTimeout = socket.TrySendMultipartMessage(_configuration.TimeOut, response); if (!noTimeout) { _configuration.Logger.Log(new ErrorLogMsg($"Responding to [Request:{typeof(T)}] with [Response:{typeof(TResult)}] timed-out after {_configuration.TimeOut}")); } } catch (NetMQ.TerminatingException terminating) { _configuration.Logger.Log(new ErrorLogMsg($"repsonseHandler failed with terminating exception: [{terminating.Message}]")); Dispose(); } }
private async Task <XtResult <TResult> > DoRequestAsync <T, TResult>(T request) where T : class, new() where TResult : class { const string operation = "request"; _configuration.Logger.Log(new DebugLogMsg($"Send Request<{typeof(T)}, {typeof(TResult)}> to Address - {_configuration.Address()}")); using var rqSocket = new RequestSocket(); rqSocket.Connect(_configuration.Address()); var message = new RequestReplyMessage <T>(_configuration, request); return(await Task.Run(() => { // the request to be send with timeout bool rqDidNotTimeOut = rqSocket.TrySendMultipartMessage(_configuration.TimeOut, message); if (!rqDidNotTimeOut) { return XtResult <TResult> .Failed(new TimeoutException($"Request<{typeof(T)}, {typeof(TResult)}> timed out"), operation); } _configuration.Logger.Log(new DebugLogMsg($"successfully sent [Request:{typeof(T)}] and waiting for response [Response:{typeof(TResult)}]")); // wait for the response with timeout var response = new NetMQMessage(); bool noTimeOut = rqSocket.TryReceiveMultipartMessage(_configuration.TimeOut, ref response, expectedFrameCount: 3); if (!noTimeOut) { return XtResult <TResult> .Failed(new TimeoutException($"Request<{typeof(T)}, {typeof(TResult)}> timed out"), operation); } _configuration.Logger.Log(new DebugLogMsg($"received Response [Response:{typeof(TResult)}]")); // parse the response and return the result var xtResult = response.ParseRqRepMessage <TResult>(_configuration); return xtResult.IsSuccess ? XtResult <TResult> .Success(xtResult.GetResult(), operation) : XtResult <TResult> .Failed(xtResult.Exception, operation); })); }