Beispiel #1
0
        void HandleMessageFailedMaxNumberOfTimes(ReceivedTransportMessage receivedTransportMessage, string errorDetail)
        {
            var transportMessageToSend = receivedTransportMessage.ToForwardableMessage();

            log.Warn("Message {0} is forwarded to error queue", transportMessageToSend.Label);

            transportMessageToSend.Headers[Headers.SourceQueue]  = receiveMessages.InputQueueAddress;
            transportMessageToSend.Headers[Headers.ErrorMessage] = errorDetail;
            transportMessageToSend.Headers[Headers.Bounced]      = "";

            try
            {
                using (var txc = ManagedTransactionContext.Get())
                {
                    sendMessages.Send(errorTracker.ErrorQueueAddress, transportMessageToSend, txc.Context);
                }
            }
            catch (Exception e)
            {
                log.Error(e, "An error occurred while attempting to move message with id {0} to the error queue '{1}'",
                          receivedTransportMessage.Id, errorTracker.ErrorQueueAddress);

                // what to do? we need to throw again, or the message will not be rolled back and will thus be lost
                // - but we want to avoid thrashing, so we just log the badness and relax a little bit - that's
                // probably the best we can do
                Thread.Sleep(TimeSpan.FromSeconds(1));

                throw;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Sends the message currently being handled to the specified endpoint, preserving all
        /// of the transport level headers.
        /// </summary>
        public void ForwardCurrentMessage(string destinationEndpoint)
        {
            using (var transactionContext = ManagedTransactionContext.Get())
            {
                var messageContext = MessageContext.GetCurrent();

                var currentMessage = messageContext.CurrentMessage;
                var headers        = messageContext.Headers.Clone();

                var message = new Message
                {
                    Headers  = headers,
                    Messages = new[] { currentMessage }
                };

                rebusBus.InternalSend(new List <string> {
                    destinationEndpoint
                }, message, transactionContext.Context);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Core send method. This should be the only place where calls to the bus'
        /// <see cref="ISendMessages"/> instance gets called, except for when moving
        /// messages to the error queue. This method will bundle the specified batch
        /// of messages inside one single transport message, which it will send.
        /// </summary>
        internal void InternalSend(List <string> destinations, List <object> messages, bool published = false)
        {
            if (!started)
            {
                throw new InvalidOperationException(
                          string.Format(
                              @"Cannot send messages with a bus that has not been started!

Or actually, you _could_ - but it would most likely be an error if you were
using a bus without starting it... if you mean only to SEND messages, never
RECEIVE anything, then you're not looking for an unstarted bus, you're looking
for the ONE-WAY CLIENT MODE of the bus, which is what you get if
you omit the inputQueue, errorQueue and workers attributes of the Rebus XML
element and use e.g. .Transport(t => t.UseMsmqInOneWayClientMode())"));
            }

            using (var txc = ManagedTransactionContext.Get())
            {
                foreach (var destination in destinations)
                {
                    messages.ForEach(m => events.RaiseMessageSent(this, destination, m));
                }

                var messageToSend = new Message {
                    Messages = messages.Select(MutateOutgoing).ToArray(),
                };
                var headers = MergeHeaders(messageToSend);

                // if a return address has not been explicitly set, set ourselves as the recipient of replies if we can
                if (!headers.ContainsKey(Headers.ReturnAddress))
                {
                    if (!configureAdditionalBehavior.OneWayClientMode)
                    {
                        headers[Headers.ReturnAddress] = GetInputQueueAddress();
                    }
                }

                if (MessageContext.HasCurrent)
                {
                    var messageContext = MessageContext.GetCurrent();

                    // if we're currently handling a message with a correlation ID, make sure it flows...
                    if (!headers.ContainsKey(Headers.CorrelationId))
                    {
                        if (messageContext.Headers.ContainsKey(Headers.CorrelationId))
                        {
                            headers[Headers.CorrelationId] = messageContext.Headers[Headers.CorrelationId].ToString();
                        }
                    }

                    // if we're currently handling a message with a user name, make sure it flows...
                    if (!headers.ContainsKey(Headers.UserName))
                    {
                        if (messageContext.Headers.ContainsKey(Headers.UserName))
                        {
                            headers[Headers.UserName] = messageContext.Headers[Headers.UserName].ToString();
                        }
                    }
                }

                // if, at this point, there's no correlation ID in a header, just provide one
                if (!headers.ContainsKey(Headers.CorrelationId))
                {
                    headers[Headers.CorrelationId] = Guid.NewGuid().ToString();
                }

                // if, at this point, there's no rebus message ID in a header, just provide one
                if (!headers.ContainsKey(Headers.MessageId))
                {
                    headers[Headers.MessageId] = Guid.NewGuid().ToString();
                }

                messageToSend.Headers = headers;
                InternalSend(destinations, messageToSend, txc.Context, published);
            }
        }