Esempio n. 1
0
        protected byte[] Serialize(MessageWithHeaders message)
        {
            // calculate bytes needed

            // 1 byte header count
            var n = 1;

            foreach (var header in message.Headers)
            {
                // 2 byte for key length
                n += StringLengthFieldSize + _encoding.GetByteCount(header.Key);
                // 2 byte for value length
                n += StringLengthFieldSize + _encoding.GetByteCount(header.Value);
            }
            n += message.Payload?.Length ?? 0;

            // allocate bytes
            var payload = new byte[n];

            // write bytes
            var i = 0;

            payload[i++] = (byte)message.Headers.Count;

            foreach (var header in message.Headers)
            {
                i += WriteString(payload, i, header.Key);
                i += WriteString(payload, i, header.Value);
            }

            message.Payload?.CopyTo(payload, i);

            return(payload);
        }
Esempio n. 2
0
        protected MessageWithHeaders Deserialize(byte[] payload)
        {
            var message = new MessageWithHeaders();

            var i           = 0;
            var headerCount = payload[i++];

            for (var headerIndex = 0; headerIndex < headerCount; headerIndex++)
            {
                string key, value;

                i += ReadString(payload, i, out key);
                i += ReadString(payload, i, out value);

                message.Headers.Add(key, value);
            }

            var payloadSize = payload.Length - i;

            if (payloadSize > 0)
            {
                message.Payload = new byte[payload.Length - i];
                Array.Copy(payload, i, message.Payload, 0, message.Payload.Length);
            }
            return(message);
        }
Esempio n. 3
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. 4
0
        public virtual byte[] SerializeResponse(Type responseType, object response, MessageWithHeaders responseMessage)
        {
            var responsePayload = response != null?Settings.Serializer.Serialize(responseType, response) : null;

            // create the response wrapper message
            responseMessage.Payload = responsePayload;
            return(Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), responseMessage));
        }
Esempio n. 5
0
        public virtual byte[] SerializeRequest(Type requestType, object request, MessageWithHeaders requestMessage, ProducerSettings producerSettings)
        {
            var requestPayload = SerializeMessage(requestType, request);

            // create the request wrapper message
            requestMessage.Payload = requestPayload;
            return(Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), requestMessage));
        }
Esempio n. 6
0
        public virtual Task ProduceResponse(object request, MessageWithHeaders requestMessage, object response, MessageWithHeaders responseMessage, ConsumerSettings consumerSettings)
        {
            var replyTo = requestMessage.Headers[ReqRespMessageHeaders.ReplyTo];

            var responseMessagePayload = SerializeResponse(consumerSettings.ResponseType, response, responseMessage);

            return(ProduceToTransport(consumerSettings.ResponseType, response, replyTo, responseMessagePayload));
        }
Esempio n. 7
0
        public virtual Task ProduceRequest(object request, MessageWithHeaders requestMessage, string name, ProducerSettings producerSettings)
        {
            var requestType = request.GetType();

            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, Settings.RequestResponse.Topic);
            var requestMessagePayload = SerializeRequest(requestType, request, requestMessage, producerSettings);

            return(ProduceToTransport(requestType, request, name, requestMessagePayload));
        }
        private async Task ProduceResponse(MessageWithHeaders requestMessage, string requestId, object message, object response, string responseError)
        {
            // send the response (or error response)
            _logger.LogDebug("Serializing the response {0} of type {1} for RequestId: {2}...", response, _consumerSettings.ResponseType, requestId);

            var responseMessage = new MessageWithHeaders();

            responseMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            responseMessage.SetHeader(ReqRespMessageHeaders.Error, responseError);

            await _messageBus.ProduceResponse(message, requestMessage, response, responseMessage, _consumerSettings).ConfigureAwait(false);
        }
Esempio n. 9
0
        public virtual byte[] SerializeResponse(Type responseType, object response, MessageWithHeaders responseMessage)
        {
            if (responseMessage == null)
            {
                throw new ArgumentNullException(nameof(responseMessage));
            }

            var responsePayload = response != null?Settings.Serializer.Serialize(responseType, response) : null;

            // create the response wrapper message
            responseMessage.Payload = responsePayload;
            return(Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), responseMessage));
        }
Esempio n. 10
0
        public virtual byte[] SerializeRequest(Type requestType, object request, MessageWithHeaders requestMessage, ProducerSettings producerSettings)
        {
            if (requestMessage == null)
            {
                throw new ArgumentNullException(nameof(requestMessage));
            }

            var requestPayload = SerializeMessage(requestType, request);

            // create the request wrapper message
            requestMessage.Payload = requestPayload;
            return(Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), requestMessage));
        }
Esempio n. 11
0
        public virtual Task ProduceResponse(object request, MessageWithHeaders requestMessage, object response, MessageWithHeaders responseMessage, ConsumerSettings consumerSettings)
        {
            if (requestMessage == null)
            {
                throw new ArgumentNullException(nameof(requestMessage));
            }
            if (consumerSettings == null)
            {
                throw new ArgumentNullException(nameof(consumerSettings));
            }

            var replyTo = requestMessage.Headers[ReqRespMessageHeaders.ReplyTo];

            var responseMessagePayload = SerializeResponse(consumerSettings.ResponseType, response, responseMessage);

            return(ProduceToTransport(consumerSettings.ResponseType, response, replyTo, responseMessagePayload));
        }
Esempio n. 12
0
        public virtual byte[] SerializeResponse(Type responseType, object response, string requestId, string error)
        {
            var responsePayload = error == null?Settings.Serializer.Serialize(responseType, response) : null;

            // create the response wrapper message
            var responseMessage = new MessageWithHeaders(responsePayload);

            responseMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            if (error != null)
            {
                responseMessage.SetHeader(ReqRespMessageHeaders.Error, error);
            }

            var responseMessagePayload = Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), responseMessage);

            return(responseMessagePayload);
        }
Esempio n. 13
0
        public virtual Task ProduceRequest(object request, MessageWithHeaders requestMessage, string name, ProducerSettings producerSettings)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (requestMessage == null)
            {
                throw new ArgumentNullException(nameof(requestMessage));
            }

            var requestType = request.GetType();

            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, Settings.RequestResponse.Topic);
            var requestMessagePayload = SerializeRequest(requestType, request, requestMessage, producerSettings);

            return(ProduceToTransport(requestType, request, name, requestMessagePayload, requestMessage));
        }
Esempio n. 14
0
        public virtual byte[] SerializeRequest(Type requestType, object request, string requestId, string replyTo, DateTimeOffset?expires)
        {
            var requestPayload = Settings.Serializer.Serialize(requestType, request);

            // create the request wrapper message
            var requestMessage = new MessageWithHeaders(requestPayload);

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            if (expires.HasValue)
            {
                requestMessage.SetHeader(ReqRespMessageHeaders.Expires, expires.Value);
            }

            var requestMessagePayload = Settings.MessageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), requestMessage);

            return(requestMessagePayload);
        }
        protected void DeserializeMessage(TMessage msg, out MessageWithHeaders requestMessage, out string requestId, out DateTimeOffset?expires, out object message)
        {
            var msgPayload = _messagePayloadProvider(msg);

            requestMessage = null;
            requestId      = null;
            expires        = null;

            _logger.LogDebug("Deserializing message...");

            message = _consumerSettings.IsRequestMessage
                ? _messageBus.DeserializeRequest(_consumerSettings.MessageType, msgPayload, out requestMessage)
                : _messageBus.Settings.Serializer.Deserialize(_consumerSettings.MessageType, msgPayload);

            if (requestMessage != null)
            {
                requestMessage.TryGetHeader(ReqRespMessageHeaders.RequestId, out requestId);
                requestMessage.TryGetHeader(ReqRespMessageHeaders.Expires, out expires);
            }
        }
        public virtual async Task ProcessMessage(TMessage msg)
        {
            var msgPayload = _messagePayloadProvider(msg);

            MessageWithHeaders requestMessage = null;
            string             requestId      = null;
            DateTimeOffset?    expires        = null;

            _log.Debug("Deserializing message...");
            var message = _consumerSettings.IsRequestMessage
                ? _messageBus.DeserializeRequest(_consumerSettings.MessageType, msgPayload, out requestMessage)
                : _messageBus.Settings.Serializer.Deserialize(_consumerSettings.MessageType, msgPayload);

            if (requestMessage != null)
            {
                requestMessage.TryGetHeader(ReqRespMessageHeaders.RequestId, out requestId);
                requestMessage.TryGetHeader(ReqRespMessageHeaders.Expires, out expires);
            }

            // Verify if the request/message is already expired
            if (expires.HasValue)
            {
                var currentTime = _messageBus.CurrentTime;
                if (currentTime > expires.Value)
                {
                    _log.WarnFormat(CultureInfo.InvariantCulture, "The message arrived too late and is already expired (expires {0}, current {1})", expires.Value, currentTime);

                    try
                    {
                        // Execute the event hook
                        (_consumerSettings.OnMessageExpired ?? _messageBus.Settings.OnMessageExpired)?.Invoke(_consumerSettings, message);
                    }
                    catch (Exception eh)
                    {
                        // When the hook itself error out, catch the exception
                        _log.ErrorFormat(CultureInfo.InvariantCulture, "{0} method failed", eh, nameof(IConsumerEvents.OnMessageExpired));
                    }

                    // Do not process the expired message
                    return;
                }
            }

            object response      = null;
            string responseError = null;

            var consumerInstance = await _instancesQueue.ReceiveAsync(_messageBus.CancellationToken).ConfigureAwait(false);

            try
            {
                if (_consumerWithContext && _consumerContextInitializer != null)
                {
                    var consumerContext = new ConsumerContext();
                    _consumerContextInitializer(msg, consumerContext);

                    var consumerWithContext = (IConsumerContextAware)consumerInstance;
                    consumerWithContext.Context.Value = consumerContext;
                }

                // the consumer just subscribes to the message
                var task = _consumerRuntimeInfo.OnHandle(consumerInstance, message);
                await task.ConfigureAwait(false);

                if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                {
                    // the consumer handles the request (and replies)
                    response = _consumerRuntimeInfo.GetResponseValue(task);
                }
            }
            catch (Exception e)
            {
                if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                {
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "Handler execution failed", e);
                    // Save the exception
                    responseError = e.ToString();
                }
                else
                {
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "Consumer execution failed", e);
                }

                try
                {
                    // Execute the event hook
                    (_consumerSettings.OnMessageFault ?? _messageBus.Settings.OnMessageFault)?.Invoke(_consumerSettings, message, e);
                }
                catch (Exception eh)
                {
                    // When the hook itself error out, catch the exception
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "{0} method failed", eh, nameof(IConsumerEvents.OnMessageFault));
                }
            }
            finally
            {
                await _instancesQueue.SendAsync(consumerInstance).ConfigureAwait(false);
            }

            if (response != null || responseError != null)
            {
                // send the response (or error response)
                _log.DebugFormat(CultureInfo.InvariantCulture, "Serializing the response {0} of type {1} for RequestId: {2}...", response, _consumerSettings.ResponseType, requestId);

                var responseMessage = new MessageWithHeaders();
                responseMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
                responseMessage.SetHeader(ReqRespMessageHeaders.Error, responseError);

                await _messageBus.ProduceResponse(message, requestMessage, response, responseMessage, _consumerSettings).ConfigureAwait(false);
            }
        }
        public virtual async Task <Exception> ProcessMessage(TMessage msg)
        {
            Exception exceptionResult = null;

            try
            {
                DeserializeMessage(msg, out var requestMessage, out var requestId, out var expires, out var message);

                // Verify if the request/message is already expired
                if (expires != null)
                {
                    var currentTime = _messageBus.CurrentTime;
                    if (currentTime > expires.Value)
                    {
                        _logger.LogWarning("The message arrived too late and is already expired (expires {0}, current {1})", expires.Value, currentTime);

                        try
                        {
                            // Execute the event hook
                            _consumerSettings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, msg);
                            _messageBus.Settings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, msg);
                        }
                        catch (Exception eh)
                        {
                            MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageExpired));
                        }

                        // Do not process the expired message
                        return(null);
                    }
                }

                object response      = null;
                string responseError = null;

                var consumerInstance = await _instancesQueue.ReceiveAsync(_messageBus.CancellationToken).ConfigureAwait(false);

                try
                {
                    if (_consumerWithContext && _consumerContextInitializer != null)
                    {
                        var consumerContext = new ConsumerContext();
                        _consumerContextInitializer(msg, consumerContext);

                        var consumerWithContext = (IConsumerContextAware)consumerInstance;
                        consumerWithContext.Context.Value = consumerContext;
                    }

                    try
                    {
                        // Execute the event hook
                        _consumerSettings.OnMessageArrived?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, msg);
                        _messageBus.Settings.OnMessageArrived?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, msg);
                    }
                    catch (Exception eh)
                    {
                        MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageArrived));
                    }

                    // the consumer just subscribes to the message
                    var task = _consumerSettings.ConsumerMethod(consumerInstance, message, _consumerSettings.Topic);
                    await task.ConfigureAwait(false);

                    if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                    {
                        // the consumer handles the request (and replies)
                        response = _consumerSettings.ConsumerMethodResult(task);
                    }
                }
                catch (Exception e)
                {
                    if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                    {
                        _logger.LogError(e, "Handler execution failed");
                        // Save the exception
                        responseError = e.ToString();
                    }
                    else
                    {
                        _logger.LogError(e, "Consumer execution failed");
                    }

                    try
                    {
                        // Execute the event hook
                        _consumerSettings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, msg);
                        _messageBus.Settings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, msg);
                    }
                    catch (Exception eh)
                    {
                        MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageFault));
                    }

                    exceptionResult = e;
                }
                finally
                {
                    await _instancesQueue.SendAsync(consumerInstance).ConfigureAwait(false);
                }

                if (response != null || responseError != null)
                {
                    // send the response (or error response)
                    _logger.LogDebug("Serializing the response {0} of type {1} for RequestId: {2}...", response, _consumerSettings.ResponseType, requestId);

                    var responseMessage = new MessageWithHeaders();
                    responseMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
                    responseMessage.SetHeader(ReqRespMessageHeaders.Error, responseError);

                    await _messageBus.ProduceResponse(message, requestMessage, response, responseMessage, _consumerSettings).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Processing of the message {0} of type {1} failed", msg, _consumerSettings.MessageType);
                exceptionResult = e;
            }
            return(exceptionResult);
        }
Esempio n. 18
0
 public virtual object DeserializeRequest(Type requestType, byte[] requestMessagePayload, out MessageWithHeaders requestMessage)
 {
     requestMessage = (MessageWithHeaders)Settings.MessageWithHeadersSerializer.Deserialize(typeof(MessageWithHeaders), requestMessagePayload);
     return(DeserializeMessage(requestType, requestMessage.Payload));
 }
Esempio n. 19
0
 public abstract Task ProduceToTransport(Type messageType, object message, string name, byte[] messagePayload, MessageWithHeaders messageWithHeaders = null);