Beispiel #1
0
        private async Task EnsureSend(BrokeredMessage message, string path)
        {
            Trace();
            while (true)
            {
                try
                {
                    //first check if sender exists but for a different destination
                    if (_sender != null && !_sender.Path.Equals(path))
                    {
                        try
                        {
                            _sender.Close();
                        }
                        catch (Exception e)
                        {
                            Error(e.ToString(), nameof(EnsureSend));
                            _sender.Abort();
                            Info("Called sender abort", nameof(EnsureSend));
                        }
                        finally
                        {
                            _sender = null;
                        }
                    }
                    //second check if sender is null or closed
                    if (_sender == null || _sender.IsClosed)
                    {
                        Trace("Creating sender", nameof(EnsureSend));
                        _sender = MessagingFactory.CreateMessageSender(path);
                    }

                    Trace("Trying to send now");
                    //try to send the message and break from the endless loop
                    await _sender.SendAsync(message);

                    break;
                }
                catch (Exception e)
                {
                    //kill the messenger if it acted up.
                    Error($"There was an exception while trying to send a message: {e.ToString()}");
                    _sender.Abort();
                    Info("Called sender abort", nameof(EnsureSend));
                    _sender = null;
                }
            }
        }
        /// <summary>
        /// This method can be used to send multiple messages to a queue or a topic.
        /// </summary>
        /// <param name="messageSender">A MessageSender object used to send messages.</param>
        /// <param name="messageTemplateEnumerable">A collection of message templates to use to clone messages from.</param>
        /// <param name="getMessageNumber">This function returns the message number.</param>
        /// <param name="messageCount">The total number of messages to send.</param>
        /// <param name="taskId">The sender task id.</param>
        /// <param name="updateMessageId">Indicates whether to use a unique id for each message.</param>
        /// <param name="addMessageNumber">Indicates whether to add a message number property.</param>
        /// <param name="oneSessionPerTask">Indicates whether to use a different session for each sender task.</param>
        /// <param name="logging">Indicates whether to enable logging of message content and properties.</param>
        /// <param name="verbose">Indicates whether to enable verbose logging.</param>
        /// <param name="statistics">Indicates whether to enable sender statistics.</param>
        /// <param name="messageInspector">A BrokeredMessage inspector object.</param>
        /// <param name="updateStatistics">When statistics = true, this delegate is invoked to update statistics.</param>
        /// <param name="sendBatch">Indicates whether to use SendBatch.</param>
        /// <param name="isBinary">Indicates if the body is binary or not.</param>
        /// <param name="senderThinkTime">Indicates whether to use think time.</param>
        /// <param name="thinkTime">Indicates the value of the sender think time.</param>
        /// <param name="batchSize">Indicates the batch size.</param>
        /// <param name="bodyType">Contains the body type.</param>
        /// <param name="cancellationTokenSource">The cancellation token.</param>
        /// <param name="traceMessage">A trace message.</param>
        /// <returns>True if the method completed without exceptions, false otherwise.</returns>
        public bool SendMessages(MessageSender messageSender,
                                 IEnumerable<BrokeredMessage> messageTemplateEnumerable,
                                 Func<long> getMessageNumber,
                                 long messageCount,
                                 int taskId,
                                 bool updateMessageId,
                                 bool addMessageNumber,
                                 bool oneSessionPerTask,
                                 bool logging,
                                 bool verbose,
                                 bool statistics,
                                 bool sendBatch,
                                 bool isBinary,
                                 int batchSize,
                                 bool senderThinkTime,
                                 int thinkTime,
                                 BodyType bodyType,
                                 IBrokeredMessageInspector messageInspector,
                                 UpdateStatisticsDelegate updateStatistics,
                                 CancellationTokenSource cancellationTokenSource,
                                 out string traceMessage)
        {
            if (messageSender == null)
            {
                throw new ArgumentNullException(MessageSenderCannotBeNull);
            }

            if (messageTemplateEnumerable == null)
            {
                throw new ArgumentNullException(BrokeredMessageCannotBeNull);
            }

            if (cancellationTokenSource == null)
            {
                throw new ArgumentNullException(CancellationTokenSourceCannotBeNull);
            }

            var messageTemplateCircularList = new CircularList<BrokeredMessage>(messageTemplateEnumerable);

            long messagesSent = 0;
            long totalElapsedTime = 0;
            long minimumSendTime = long.MaxValue;
            long maximumSendTime = 0;
            bool ok = true;
            string exceptionMessage = null;
            var wcfUri = IsCloudNamespace ?
                         new Uri(namespaceUri, messageSender.Path) :
                         new UriBuilder
                         {
                             Host = namespaceUri.Host,
                             Path = string.Format("{0}/{1}", namespaceUri.AbsolutePath, messageSender.Path),
                             Scheme = "sb"
                         }.Uri;
            try
            {
                long messageNumber;
                if (sendBatch && batchSize > 1)
                {
                    var more = true;
                    while (!cancellationTokenSource.Token.IsCancellationRequested && more)
                    {
                        var messageList = new List<BrokeredMessage>();
                        var messageNumberList = new List<long>();
                        while (!cancellationTokenSource.Token.IsCancellationRequested &&
                               messageNumberList.Count < batchSize && more)
                        {
                            messageNumber = getMessageNumber();
                            if (messageNumber < messageCount)
                            {
                                messageNumberList.Add(messageNumber);
                            }
                            else
                            {
                                more = false;
                            }
                        }
                        if (messageNumberList.Count > 0)
                        {
                            long elapsedMilliseconds = 0;
                            RetryHelper.RetryAction(() =>
                            {
                                var useWcf = bodyType == BodyType.Wcf;
                                for (var i = 0; i < messageNumberList.Count; i++)
                                {
                                    messageList.Add(useWcf?
                                                    CreateMessageForWcfReceiver(
                                                        messageTemplateCircularList.Next,
                                                        taskId,
                                                        updateMessageId,
                                                        oneSessionPerTask,
                                                        wcfUri) :
                                                    CreateMessageForApiReceiver(
                                                        messageTemplateCircularList.Next,
                                                        taskId,
                                                        updateMessageId,
                                                        oneSessionPerTask,
                                                        isBinary,
                                                        bodyType,
                                                        messageInspector));
                                    if (addMessageNumber)
                                    {
                                        messageList[i].Properties[MessageNumber] = messageNumberList[i];
                                    }
                                }
                                if (messageNumberList.Count > 0)
                                {
                                    SendBatch(messageSender,
                                              messageList,
                                              taskId,
                                              isBinary,
                                              useWcf,
                                              logging,
                                              verbose,
                                              out elapsedMilliseconds);
                                }
                            },
                            writeToLog);
                            messagesSent += messageList.Count;
                            if (elapsedMilliseconds > maximumSendTime)
                            {
                                maximumSendTime = elapsedMilliseconds;
                            }
                            if (elapsedMilliseconds < minimumSendTime)
                            {
                                minimumSendTime = elapsedMilliseconds;
                            }
                            totalElapsedTime += elapsedMilliseconds;
                            if (statistics)
                            {
                                updateStatistics(messageList.Count, elapsedMilliseconds, DirectionType.Send);
                            }
                        }
                        if (senderThinkTime)
                        {
                            WriteToLog(string.Format(SleepingFor, thinkTime));
                            Thread.Sleep(thinkTime);
                        }
                    }
                }
                else
                {
                    while ((messageNumber = getMessageNumber()) < messageCount &&
                       !cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        long elapsedMilliseconds = 0;
                        RetryHelper.RetryAction(() =>
                        {
                            var useWcf = bodyType == BodyType.Wcf;
                            var outboundMessage = useWcf
                                                      ? CreateMessageForWcfReceiver(
                                                          messageTemplateCircularList.Next,
                                                          taskId,
                                                          updateMessageId,
                                                          oneSessionPerTask,
                                                          wcfUri)
                                                      : CreateMessageForApiReceiver(
                                                          messageTemplateCircularList.Next,
                                                          taskId,
                                                          updateMessageId,
                                                          oneSessionPerTask,
                                                          isBinary,
                                                          bodyType,
                                                          messageInspector);
                            if (addMessageNumber)
                            {
                                // ReSharper disable AccessToModifiedClosure
                                outboundMessage.Properties[MessageNumber] = messageNumber;
                                // ReSharper restore AccessToModifiedClosure
                            }


                            SendMessage(messageSender,
                                        outboundMessage,
                                        taskId,
                                        isBinary,
                                        useWcf,
                                        logging,
                                        verbose,
                                        out elapsedMilliseconds);
                        },
                        writeToLog);
                        messagesSent++;
                        if (elapsedMilliseconds > maximumSendTime)
                        {
                            maximumSendTime = elapsedMilliseconds;
                        }
                        if (elapsedMilliseconds < minimumSendTime)
                        {
                            minimumSendTime = elapsedMilliseconds;
                        }
                        totalElapsedTime += elapsedMilliseconds;
                        if (statistics)
                        {
                            updateStatistics(1, elapsedMilliseconds, DirectionType.Send);
                        }
                        if (senderThinkTime)
                        {
                            WriteToLog(string.Format(SleepingFor, thinkTime));
                            Thread.Sleep(thinkTime);
                        }
                    }
                }
            }
            catch (ServerBusyException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (MessageLockLostException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationObjectAbortedException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationObjectFaultedException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (TimeoutException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (Exception ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            var averageSendTime = messagesSent > 0 ? totalElapsedTime / messagesSent : maximumSendTime;
            // ReSharper disable RedundantCast
            var messagesPerSecond = totalElapsedTime > 0 ? (double)(messagesSent * 1000) / (double)totalElapsedTime : 0;
            // ReSharper restore RedundantCast
            var builder = new StringBuilder();
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatisticsHeader,
                                             taskId));
            if (!string.IsNullOrWhiteSpace(exceptionMessage))
            {
                builder.AppendLine(exceptionMessage);
            }
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine1,
                                             messagesSent,
                                             messagesPerSecond,
                                             totalElapsedTime));
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine2,
                                             averageSendTime,
                                             minimumSendTime == long.MaxValue ? 0 : minimumSendTime,
                                             maximumSendTime));
            traceMessage = builder.ToString();
            return ok;
        }
        /// <summary>
        /// This method can be used to send multiple messages to a queue or a topic.
        /// </summary>
        /// <param name="messageSender">A MessageSender object used to send messages.</param>
        /// <param name="messageTemplate">The message template to use to clone messages from.</param>
        /// <param name="getMessageNumber">This function returns the message number.</param>
        /// <param name="messageCount">The total number of messages to send.</param>
        /// <param name="messageText">The message text.</param>
        /// <param name="taskId">The sender task id.</param>
        /// <param name="updateMessageId">Indicates whether to use a unique id for each message.</param>
        /// <param name="addMessageNumber">Indicates whether to add a message number property.</param>
        /// <param name="oneSessionPerTask">Indicates whether to use a different session for each sender task.</param>
        /// <param name="logging">Indicates whether to enable logging of message content and properties.</param>
        /// <param name="verbose">Indicates whether to enable verbose logging.</param>
        /// <param name="statistics">Indicates whether to enable sender statistics.</param>
        /// <param name="updateStatistics">When statistics = true, this delegate is invoked to update statistics.</param>
        /// <param name="bodyType">Contains the body type.</param>
        /// <param name="cancellationTokenSource">The cancellation token.</param>
        /// <param name="traceMessage">A trace message.</param>
        /// <returns>True if the method completed without exceptions, false otherwise.</returns>
        public bool SendMessages(MessageSender messageSender,
                                 BrokeredMessage messageTemplate,
                                 Func<long> getMessageNumber,
                                 long messageCount,
                                 string messageText,
                                 int taskId,
                                 bool updateMessageId,
                                 bool addMessageNumber,
                                 bool oneSessionPerTask,
                                 bool logging,
                                 bool verbose,
                                 bool statistics,
                                 BodyType bodyType,
                                 UpdateStatisticsDelegate updateStatistics,
                                 CancellationTokenSource cancellationTokenSource,
                                 out string traceMessage)
        {
            if (messageSender == null)
            {
                throw new ArgumentNullException(MessageSenderCannotBeNull);
            }

            if (messageTemplate == null)
            {
                throw new ArgumentNullException(BrokeredMessageCannotBeNull);
            }

            if (cancellationTokenSource == null)
            {
                throw new ArgumentNullException(CancellationTokenSourceCannotBeNull);
            }

            long messagesSent = 0;
            long totalElapsedTime = 0;
            long minimumSendTime = long.MaxValue;
            long maximumSendTime = 0;
            bool ok = true;
            string exceptionMessage = null;

            try
            {
                long messageNumber;
                while ((messageNumber = getMessageNumber()) < messageCount &&
                       !cancellationTokenSource.Token.IsCancellationRequested)
                {
                    long elapsedMilliseconds = 0;
                    RetryHelper.RetryAction(() =>
                                                {
                                                    var useWcf = bodyType == BodyType.Wcf;
                                                    var outboundMessage = useWcf
                                                                              ? CreateMessageForWcfReceiver(
                                                                                  messageTemplate,
                                                                                  taskId,
                                                                                  updateMessageId,
                                                                                  oneSessionPerTask,
                                                                                  messageText,
                                                                                  messageSender.Path)
                                                                              : CreateMessageForApiReceiver(
                                                                                  messageTemplate,
                                                                                  taskId,
                                                                                  updateMessageId,
                                                                                  oneSessionPerTask,
                                                                                  messageText,
                                                                                  bodyType);
                                                    if (addMessageNumber)
                                                    {
                                                        outboundMessage.Properties[MessageNumber] = messageNumber;
                                                    }

                                                    
                                                    SendMessage(messageSender,
                                                                outboundMessage,
                                                                messageText,
                                                                taskId,
                                                                useWcf,
                                                                logging,
                                                                verbose,
                                                                out elapsedMilliseconds);
                                                }, 
                                                writeToLog);
                    messagesSent++;
                    if (elapsedMilliseconds > maximumSendTime)
                    {
                        maximumSendTime = elapsedMilliseconds;
                    }
                    if (elapsedMilliseconds < minimumSendTime)
                    {
                        minimumSendTime = elapsedMilliseconds;
                    }
                    totalElapsedTime += elapsedMilliseconds;
                    if (statistics)
                    {
                        updateStatistics(elapsedMilliseconds, DirectionType.Send);
                    }
                }
            }
            catch (ServerBusyException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (MessageLockLostException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationObjectAbortedException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationObjectFaultedException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (CommunicationException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (TimeoutException ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            catch (Exception ex)
            {
                messageSender.Abort();
                exceptionMessage = string.Format(ExceptionOccurred, ex.Message);
                ok = false;
            }
            var averageSendTime = messagesSent > 0 ? totalElapsedTime / messagesSent : maximumSendTime;
            var messagesPerSecond = totalElapsedTime > 0 ? (double)(messagesSent * 1000) / (double)totalElapsedTime : 0;
            var builder = new StringBuilder();
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatisticsHeader,
                                             taskId));
            if (!string.IsNullOrEmpty(exceptionMessage))
            {
                builder.AppendLine(exceptionMessage);
            }
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine1,
                                             messagesSent,
                                             messagesPerSecond,
                                             totalElapsedTime));
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine2,
                                             averageSendTime,
                                             minimumSendTime == long.MaxValue ? 0 : minimumSendTime,
                                             maximumSendTime));
            traceMessage = builder.ToString();
            return ok;
        }