Esempio n. 1
0
        protected virtual async Task <TResponseMessage> SendInternal <TResponseMessage>(IRequestMessage <TResponseMessage> request, TimeSpan?timeout, string name, CancellationToken cancellationToken)
        {
            AssertActive();
            AssertRequestResponseConfigured();

            // check if the cancellation was already requested
            cancellationToken.ThrowIfCancellationRequested();

            var requestType      = request.GetType();
            var producerSettings = GetProducerSettings(requestType);

            if (name == null)
            {
                name = GetDefaultName(requestType, producerSettings);
            }

            if (timeout == null)
            {
                timeout = GetDefaultRequestTimeout(requestType, producerSettings);
            }

            var created = CurrentTime;
            var expires = created.Add(timeout.Value);

            // generate the request guid
            var requestId      = GenerateRequestId();
            var requestMessage = new MessageWithHeaders();

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.Expires, expires);

            // record the request state
            var requestState = new PendingRequestState(requestId, request, requestType, typeof(TResponseMessage), created, expires, cancellationToken);

            PendingRequestStore.Add(requestState);

            if (Log.IsTraceEnabled)
            {
                Log.TraceFormat(CultureInfo.InvariantCulture, "Added to PendingRequests, total is {0}", PendingRequestStore.GetCount());
            }

            try
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, "Sending request message {0} to name {1} with reply to {2}", requestState, name, Settings.RequestResponse.Topic);
                await ProduceRequest(request, requestMessage, name, producerSettings).ConfigureAwait(false);
            }
            catch (PublishMessageBusException e)
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, "Publishing of request message failed", e);
                // remove from registry
                PendingRequestStore.Remove(requestId);
                throw;
            }

            // convert Task<object> to Task<TResponseMessage>
            var responseUntyped = await requestState.TaskCompletionSource.Task.ConfigureAwait(true);

            return((TResponseMessage)responseUntyped);
        }
Esempio n. 2
0
        /// <summary>
        /// Should be invoked by the concrete bus implementation whenever there is a message arrived on the reply to topic name.
        /// </summary>
        /// <param name="reponse"></param>
        /// <param name="name"></param>
        /// <param name="requestId"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public virtual Task <Exception> OnResponseArrived(byte[] responsePayload, string name, string requestId, string errorMessage, object response = null)
        {
            var requestState = PendingRequestStore.GetById(requestId);

            if (requestState == null)
            {
                _logger.LogDebug("The response message for request id {0} arriving on name {1} will be disregarded. Either the request had already expired, had been cancelled or it was already handled (this response message is a duplicate).", requestId, name);

                // ToDo: add and API hook to these kind of situation
                return(Task.FromResult <Exception>(null));
            }

            try
            {
                if (_logger.IsEnabled(LogLevel.Debug))
                {
                    var tookTimespan = CurrentTime.Subtract(requestState.Created);
                    _logger.LogDebug("Response arrived for {0} on name {1} (time: {2} ms)", requestState, name, tookTimespan);
                }

                if (errorMessage != null)
                {
                    // error response arrived
                    _logger.LogDebug("Response arrived for {0} on name {1} with error: {2}", requestState, name, errorMessage);

                    var e = new RequestHandlerFaultedMessageBusException(errorMessage);
                    requestState.TaskCompletionSource.TrySetException(e);
                }
                else
                {
                    // response arrived
                    try
                    {
                        // deserialize the response message
                        response = responsePayload != null?DeserializeResponse(requestState.ResponseType, responsePayload) : response;

                        // resolve the response
                        requestState.TaskCompletionSource.TrySetResult(response);
                    }
                    catch (Exception e)
                    {
                        _logger.LogDebug("Could not deserialize the response message for {0} arriving on name {1}: {2}", requestState, name, e);
                        requestState.TaskCompletionSource.TrySetException(e);
                    }
                }
            }
            finally
            {
                // remove the request from the queue
                PendingRequestStore.Remove(requestId);
            }
            return(Task.FromResult <Exception>(null));
        }
Esempio n. 3
0
        /// <summary>
        /// Should be invoked by the concrete bus implementation whenever there is a message arrived on the reply to topic name.
        /// </summary>
        /// <param name="payload"></param>
        /// <param name="name"></param>
        /// <param name="requestId"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public virtual Task OnResponseArrived(byte[] payload, string name, string requestId, string errorMessage)
        {
            var requestState = PendingRequestStore.GetById(requestId);

            if (requestState == null)
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, "The response message for request id {0} arriving on name {1} will be disregarded. Either the request had already expired, had been cancelled or it was already handled (this response message is a duplicate).", requestId, name);

                // ToDo: add and API hook to these kind of situation
                return(Task.CompletedTask);
            }

            try
            {
                if (Log.IsDebugEnabled)
                {
                    var tookTimespan = CurrentTime.Subtract(requestState.Created);
                    Log.DebugFormat(CultureInfo.InvariantCulture, "Response arrived for {0} on name {1} (time: {2} ms)", requestState, name, tookTimespan);
                }

                if (errorMessage != null)
                {
                    // error response arrived
                    Log.DebugFormat(CultureInfo.InvariantCulture, "Response arrived for {0} on name {1} with error: {2}", requestState, name, errorMessage);

                    var e = new RequestHandlerFaultedMessageBusException(errorMessage);
                    requestState.TaskCompletionSource.TrySetException(e);
                }
                else
                {
                    // response arrived
                    try
                    {
                        // deserialize the response message
                        var response = Settings.Serializer.Deserialize(requestState.ResponseType, payload);

                        // resolve the response
                        requestState.TaskCompletionSource.TrySetResult(response);
                    }
                    catch (Exception e)
                    {
                        Log.DebugFormat(CultureInfo.InvariantCulture, "Could not deserialize the response message for {0} arriving on name {1}: {2}", requestState, name, e);
                        requestState.TaskCompletionSource.TrySetException(e);
                    }
                }
            }
            finally
            {
                // remove the request from the queue
                PendingRequestStore.Remove(requestId);
            }
            return(Task.CompletedTask);
        }