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); }
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); }
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); }
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)); }
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)); }
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)); }
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); }
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)); }
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)); }
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)); }
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); }
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)); }
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); }
public virtual object DeserializeRequest(Type requestType, byte[] requestMessagePayload, out MessageWithHeaders requestMessage) { requestMessage = (MessageWithHeaders)Settings.MessageWithHeadersSerializer.Deserialize(typeof(MessageWithHeaders), requestMessagePayload); return(DeserializeMessage(requestType, requestMessage.Payload)); }
public abstract Task ProduceToTransport(Type messageType, object message, string name, byte[] messagePayload, MessageWithHeaders messageWithHeaders = null);