public void ReceiveMessages(Func <IssueCreatedEventArgs, CancellationToken, Task> issueCreatedHandler       = null,
                                    Func <NewIssueCreatedEventArgs, CancellationToken, Task> newissueCreatedHandler = null,
                                    MessageHandlerOptions options = null)
        {
            var messageHandlerOptions = options ?? new MessageHandlerOptions(OnDefaultError);

            _messageReceiver.RegisterMessageHandler(async(msg, token) =>
            {
                _logger.Information("Received service bus message {MessageId}: {Label}", msg.Id.ToString(), msg.Label);


                switch (msg.Label)
                {
                case IssueMessageSender.ISSUE_CREATED:
                    {
                        if (issueCreatedHandler != null)
                        {
                            _logger.Information("ISSUE_CREATED");
                            await ReceiveIssueCreated(msg, token, issueCreatedHandler);
                        }
                        else
                        {
                            await _messageReceiver.CompleteAsync(msg.LockToken);
                        }
                        break;
                    }

                default:
                    {
                        await _messageReceiver.DeadLetterAsync(msg.LockToken, $"Unknown message type: { msg.Label }");
                        break;
                    }
                }
            }, messageHandlerOptions);
        }
示例#2
0
        internal async Task OnMessageAsyncUnregisterHandlerShortTimeoutTestCase(
            IMessageSender messageSender,
            IMessageReceiver messageReceiver,
            int maxConcurrentCalls,
            bool autoComplete,
            int messageCount)
        {
            var count = 0;
            await TestUtility.SendMessagesAsync(messageSender, messageCount);

            messageReceiver.RegisterMessageHandler(
                async(message, token) =>
            {
                TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}");
                await Task.Delay(TimeSpan.FromSeconds(8));
                if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete)
                {
                    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
                }
                Interlocked.Increment(ref count);
            },
                new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete
            });

            await Task.Delay(TimeSpan.FromSeconds(2));

            await messageReceiver.UnregisterMessageHandlerAsync(TimeSpan.FromSeconds(2));

            Assert.True(count == 0);
        }
示例#3
0
        static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive, ILogger tw)
        {
            // Receive the message
            IList <Message> receiveList = await messageReceiver.ReceiveAsync(numberOfMessagesToReceive);

            foreach (Message msg in receiveList)
            {
                tw.LogInformation($"Received message: SequenceNumber:{msg.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(msg.Body)}");
                await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken);
            }
        }
示例#4
0
 static async Task ProcessMessagesAsyncDead(Message receivedMessage, CancellationToken token)
 {
     try
     {
         ProcessMessage(receivedMessage, "dead-letter");
         await subscriptionDeadLetter.CompleteAsync(receivedMessage.SystemProperties.LockToken);
     }
     catch (Exception)
     {
         await subscriptionDeadLetter.AbandonAsync(receivedMessage.SystemProperties.LockToken);
     }
 }
        protected override void ReceiveEvent(IMessageReceiver client, BrokeredMessage message)
#endif
        {
            try
            {
                Logger.LogDebug(string.Format("An event message arrived with the id '{0}'.", message.MessageId));
                string messageBody = message.GetBodyAsString();
                IEvent <TAuthenticationToken> @event = MessageSerialiser.DeserialiseEvent(messageBody);

                CorrelationIdHelper.SetCorrelationId(@event.CorrelationId);
                Logger.LogInfo(string.Format("An event message arrived with the id '{0}' was of type {1}.", message.MessageId, @event.GetType().FullName));

                Type eventType = @event.GetType();

                string targetQueueName = eventType.FullName;

                try
                {
                    object rsn = eventType.GetProperty("Rsn").GetValue(@event, null);
                    targetQueueName = string.Format("{0}.{1}", targetQueueName, rsn);
                }
                catch
                {
                    Logger.LogDebug(string.Format("An event message arrived with the id '{0}' was of type {1} but with no Rsn property.", message.MessageId, eventType));
                    // Do nothing if there is no rsn. Just use @event type name
                }

                CreateQueueAndAttachListenerIfNotExist(targetQueueName);
                EnqueueEvent(targetQueueName, @event);

                // remove the original message from the incoming queue
#if NET452
                message.Complete();
#endif
#if NETSTANDARD2_0
                client.CompleteAsync(message.SystemProperties.LockToken).Wait(1500);
#endif

                Logger.LogDebug(string.Format("An event message arrived and was processed with the id '{0}'.", message.MessageId));
            }
            catch (Exception exception)
            {
                // Indicates a problem, unlock message in queue
                Logger.LogError(string.Format("An event message arrived with the id '{0}' but failed to be process.", message.MessageId), exception: exception);
#if NET452
                message.Abandon();
#endif
#if NETSTANDARD2_0
                client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500);
#endif
            }
        }
示例#6
0
        static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive)
        {
            while (numberOfMessagesToReceive-- > 0)
            {
                // Receive the message
                Message message = await messageReceiver.ReceiveAsync();

                // Process the message
                Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");

                // Complete the message so that it is not received again.
                // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default).
                await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
            }
        }
示例#7
0
 async Task CompleteMessageIfNeededAsync(Message message)
 {
     try
     {
         if (_messageReceiver.ReceiveMode == ReceiveMode.PeekLock &&
             _registerHandlerOptions.AutoComplete)
         {
             await _messageReceiver.CompleteAsync(new[] { message.SystemProperties.LockToken }).ConfigureAwait(false);
         }
     }
     catch (Exception exception)
     {
         await RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Complete).ConfigureAwait(false);
     }
 }
        private static async Task HandleMessage(Message message, CancellationToken token)
        {
            try
            {
                bool isDeadLetterMessage = message.UserProperties.Keys.FirstOrDefault(k => k.Equals("DeadLetterReason")) != null;

                bool hasSessionId = !string.IsNullOrEmpty(message.SessionId);

                Console.WriteLine("Message Received!");

                var smsMessage = JsonConvert.DeserializeObject <SmsMessage>(Encoding.UTF8.GetString(message.Body));

                Console.WriteLine("Content: " + smsMessage.Content);
                Console.WriteLine("Destination: " + smsMessage.Destination);

                Console.WriteLine("Is DLQ: " + isDeadLetterMessage);

                // Writing messages with not null sessionId's to session disabled queues is not forbidden.
                // In fact, if you write messages with sessionId to a queue where sessions are disabled,
                // you will still get messages FIFO.
                Console.WriteLine("Has session ID: " + hasSessionId);

                if (hasSessionId)
                {
                    Console.WriteLine("Session ID: " + message.SessionId);
                }

                // Complete the message so that it is not received again.
                // This can be done only if the queue Client is created in ReceiveMode.PeekLock mode (which is the default).
                if (isDeadLetterMessage)
                {
                    await _dlqReceiver.CompleteAsync(message.SystemProperties.LockToken);
                }
                else
                {
                    await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
                }

                Console.WriteLine("***********************\n");
            }
            catch
            {
                Console.WriteLine("Received exception while handling the message, abandoning...");

                await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
            }
        }
示例#9
0
        private async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            T payload = null;

            if (message.Body[0] == charAt)
            {
                payload = OneSolution.ServiceBus.XmlMessageExtention.ParseXmlMessage <T>(message);
            }
            else
            {
                payload = JsonSerializer.Deserialize <T>(Encoding.UTF8.GetString(message.Body));
            }
            var lockToken = message.SystemProperties.LockToken;
            await processor.ProcessMessagesAsync(payload, lockToken, token).ConfigureAwait(false);

            await receiver.CompleteAsync(lockToken).ConfigureAwait(false);
        }
示例#10
0
        internal static async Task <Message> GetDeferredMessageAsync(this IMessageReceiver messageReceiver, Message message)
        {
            if (!message.TryGetDeferredSequenceNumber(out var sequenceNumber))
            {
                return(message);
            }

            using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                await messageReceiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false);

                message = await messageReceiver.ReceiveDeferredMessageAsync(sequenceNumber)
                          .ConfigureAwait(false);

                scope.Complete();
            }

            return(message);
        }
        /// <summary>
        /// Processes an incoming message.
        /// </summary>
        /// <param name="receiver"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task ProcessMessageForClient(IMessageReceiver receiver, Message message)
        {
            SampleMessage messageData = null;

            try
            {
                messageData = DeserializeMessage(message);
            }
            catch (Exception ex)
            {
                //this is an issue, we received data that cannot be interpreted as MessageData.
                await MessageProcessingFailed(message, ex).ConfigureAwait(false);

                //move to dlc
                if (message.SystemProperties.IsReceived)
                {
                    await receiver.DeadLetterAsync(message.SystemProperties.LockToken, "Message cannot be deserialized into MessageData.").ConfigureAwait(false);
                }
            }

            try
            {
                //if messageData is null, this means message is not supposed to be handled
                if (messageData != null)
                {
                    await ProcessMessage(receiver, message, messageData)
                    .ConfigureAwait(false);
                }
                else
                {
                    //unable to process, and not interested
                    await receiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false);
                }
            }
            catch (MessageLockLostException ex)
            {
                _logger?.LogWarning(ex, "Message lock was lost for message {MessageId}", message.MessageId);
            }
            catch (Exception ex)
            {
                await MessageProcessingFailed(message, ex).ConfigureAwait(false);
            }
        }
示例#12
0
        private async Task HandleMessage(Message message, CancellationToken cancellationToken)
        {
            //Console.WriteLine($"Handled message id {message.MessageId}, diagnostic id {message.UserProperties["Diagnostic-Id"]}, enclosed type {message.UserProperties["EnclosedType"]}");
            try
            {
                await messageHandler.HandleMessage(message, cancellationToken);

                await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> abandonReasons = new Dictionary <string, object>
                {
                    { "Exception.Message", ex.Message },
                    { "Exception.StackTrace", ex.ToString() }
                };
                await messageReceiver.AbandonAsync(message.SystemProperties.LockToken, abandonReasons);
            }
        }
        private async Task _handleMessage(RecoverabilityContext context, CancellationToken cancellationToken)
        {
            bool isHandled = false;

            try
            {
                context = await _recoverability.OnPreHandle(context);

                if (context.SkipMessage)
                {
                    return;
                }

                await _handleMessageFunc(
                    new TransportMessage(context.Message.Label, context.Message.Body, _metaDataMapper.ExtractMetaData(context.Message)),
                    _endpoint
                    );

                isHandled = true;
            }
            catch (NonTransientException nte)
            {
                _logger.LogError(nte, "AzureServiceBusMessagePump encountered a NonTransient Exception handling a message. Sending to DLQ. Endpoint: {EndpointName}", context.Endpoint.Name);
                await _receiver.DeadLetterAsync(context.Message.SystemProperties.LockToken);
            }
            catch (Exception exc)
            {
                //backoff retry
                _logger.LogError(exc, "AzureServiceBusMessagePump encountered an exception handling a message. Attempting to recover. Endpoint: {EndpointName}. Label: {messageLabel}", context.Endpoint.Name, context.Message?.Label);
                await _recoverability.Recover(context);
            }

            //if an exception occurs completing the message then it will stay on the queue and be handled again
            //we don't want to trigger recoverability/retry
            if (isHandled)
            {
                await _completeImmediateRetryPolicy.ExecuteAsync(() =>
                                                                 _receiver.CompleteAsync(context.Message.SystemProperties.LockToken)
                                                                 );

                await _recoverability.OnPostHandle(context);
            }
        }
示例#14
0
        internal async Task OnMessageAsyncTestCase(
            IMessageSender messageSender,
            IMessageReceiver messageReceiver,
            int maxConcurrentCalls,
            bool autoComplete,
            int messageCount)
        {
            int count = 0;
            await TestUtility.SendMessagesAsync(messageSender, messageCount);

            messageReceiver.RegisterMessageHandler(
                async(message, token) =>
            {
                TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}");
                count++;
                if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete)
                {
                    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
                }
            },
                new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete
            });

            // Wait for the OnMessage Tasks to finish
            Stopwatch stopwatch = Stopwatch.StartNew();

            while (stopwatch.Elapsed.TotalSeconds <= 60)
            {
                if (count == messageCount)
                {
                    TestUtility.Log($"All '{messageCount}' messages Received.");
                    break;
                }
                else
                {
                    await Task.Delay(TimeSpan.FromSeconds(5));
                }
            }
            Assert.True(count == messageCount);
        }
        public async Task <bool> ResubmitDeadLetterMessageAsync(string messageId, string serviceBusQueue, long sequenceNumber)
        {
            bool             IsSuccess       = false;
            IMessageReceiver messageReceiver = _messageReceiverFactory.Create(serviceBusQueue, ReceiveMode.PeekLock, true);
            Message          deadLetter      = await messageReceiver.PeekBySequenceNumberAsync(sequenceNumber);

            if (deadLetter != null)
            {
                var newMessage = _messageReader.ReadMessage(Encoding.UTF8.GetString(deadLetter.Body));

                //Check that the messageId matches the one that we want to re-enqueue
                if (newMessage.MessageId.Equals(messageId))
                {
                    try
                    {
                        //Attempt to send the message back onto the queue
                        // never re-queue a message with a duplicate id - it will fail to save to message archive
                        newMessage.MessageId = Guid.NewGuid().ToString();
                        await _messageSender.SendMessage(newMessage);
                    }
                    catch (Exception ex)
                    {
                        _log.LogError(ex, "ResubmitDeadLetterMessageAsync Exception");
                        throw new ServiceBusReaderException("ResubmitDeadLetterMessageAsync", ex);
                    }
                    finally
                    {
                        //Delete message after resubmitting
                        var msg = await messageReceiver.ReceiveAsync();

                        await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken);

                        IsSuccess = true;
                    }
                }
            }

            await messageReceiver.CloseAsync();

            return(IsSuccess);
        }
示例#16
0
        public async Task ReceiveMessageAsync(IMessageReceiver receiver, Message message, CancellationToken cancellationToken)
        {
            Exception receiveEx = null;

            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                Console.WriteLine("Received MessageId=[{0}] MessageBody=[{1}]", message.MessageId, Encoding.UTF8.GetString(message.Body));
                await receiver.CompleteAsync(message.SystemProperties.LockToken);
            }
            catch (Exception ex)
            {
                receiveEx = ex;
                Console.WriteLine("Exception ocurred during ReceiveMessageAsync() Message=[{0}]", ex.Message);
            }

            if (receiveEx != null)
            {
                await receiver.AbandonAsync(message.SystemProperties.LockToken);
            }
        }
示例#17
0
        protected async Task <bool> HandleMessageOutcome(
            Message message,
            MessageHandlingResult result)
        {
            var isSuccessful       = result.Result == MessageHandlingResult.HandlingResult.Completed;
            var shouldAutoComplete = _endpointHandlingConfig.AutoComplete || _receiver.IsClosedOrClosing;

            if (shouldAutoComplete)
            {
                return(isSuccessful);
            }

            try
            {
                switch (result.Result)
                {
                case MessageHandlingResult.HandlingResult.Completed:
                    await _receiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false);

                    break;

                case MessageHandlingResult.HandlingResult.DeadLettered:
                case MessageHandlingResult.HandlingResult.UnrecognisedMessageType:
                    await _receiver.DeadLetterAsync(message.SystemProperties.LockToken, result.AdditionalProperties).ConfigureAwait(false);

                    break;

                case MessageHandlingResult.HandlingResult.Abandoned:
                    await _receiver.AbandonAsync(message.SystemProperties.LockToken, result.AdditionalProperties).ConfigureAwait(false);

                    break;
                }
            }
            catch (MessageLockLostException ex)
            {
                _logger.LogError(LogEventIds.ListenerException, ex, $"MessageLockLostException in {_name}>");
            }
            return(isSuccessful);
        }
示例#18
0
        static async Task ProcessDeadLetterQueueMessagesAsync(Message message, CancellationToken token)
        {
            // Process the message
            // This could include retries or logging for further troubleshooting
            Console.WriteLine($"Received DLQ message: SequenceNumber:{message.SystemProperties} Body:{Encoding.UTF8.GetString(message.Body)}");

            if (message.UserProperties.ContainsKey("DeadLetterReason"))
            {
                Console.WriteLine("\t DeadLetterReason: {0}", message.UserProperties["DeadLetterReason"]);
            }
            if (message.UserProperties.ContainsKey("DeadLetterErrorDescription"))
            {
                Console.WriteLine("\t DeadLetterErrorDescription: {0}", message.UserProperties["DeadLetterErrorDescription"]);
            }

            // Complete the message so that it is not received again.
            // This can be done only if the deadLetterReceiver is created in ReceiveMode.PeekLock mode (which is default).
            await deadLetterReceiver.CompleteAsync(message.SystemProperties.LockToken);

            // Note: Use the cancellationToken passed as necessary to determine if the deadLetterReceiver has already been closed.
            // If deadLetterReceiver has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
            // to avoid unnecessary exceptions.
        }
        /// <summary>
        /// Handles one message.
        /// </summary>
        /// <param name="receiver"></param>
        /// <param name="serviceBusMessage"></param>
        /// <param name="messageData"></param>
        /// <returns></returns>
        private async Task ProcessMessage(IMessageReceiver receiver, Message serviceBusMessage, SampleMessage messageData)
        {
            //TODO: de-duplicate messages

            ImmutableList <SampleMessage> value;

            if (_cache.TryGetValue("CacheKey", out var val))
            {
                value = (ImmutableList <SampleMessage>)val;
            }
            else
            {
                value = ImmutableList <SampleMessage> .Empty;
            }

            messageData.Receiver = receiver == _primaryMessageReceiver ? "PrimaryReceiver" : "SecondaryReceiver";
            value = value.Add(messageData);
            _cache.Set("CacheKey", value);


            _logger.LogInformation("Received message with body: {MessageData}", messageData);
            await receiver.CompleteAsync(serviceBusMessage.SystemProperties.LockToken).ConfigureAwait(false);
        }
示例#20
0
        private async Task <IList <QueueMessage> > ProcessMessagesInTransaction(string queueName, int quantity)
        {
            IEnumerable <QueueMessage> formattedMessages = new List <QueueMessage>();
            var messages = await _messageReceiver.ReceiveAsync(quantity, TimeSpan.FromSeconds(60));

            try
            {
                if (messages == null)
                {
                    return(null);
                }

                formattedMessages = messages.Select(message => message.Convert(_userService.GetUserId(), queueName));

                await AddMessagesToDatabase(formattedMessages);

                await _messageReceiver.CompleteAsync(messages.Select(message => message.GetLockToken()));
            }
            catch (CosmosBatchInsertException ex)
            {
                await HandleBatchCreationFailure(formattedMessages, ex.StatusCode);

                _logger.LogError("Failed to create messages with error: {0}, exception: {1}", ex.StatusCode.ToString(),
                                 ex.ToString());
            }
            catch (Exception ex)
            {
                _logger.LogError("Failed to receive messages: {0}", ex.ToString());

                foreach (var message in formattedMessages)
                {
                    await _messageReceiver.AbandonAsync(message.OriginalMessage.GetLockToken());
                }
            }

            return(formattedMessages.ToList());
        }
        static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive, TraceWriter tw)
        {
            //while (numberOfMessagesToReceive-- > 0)
            //{
            // Receive the message
            IList <Message> receiveList = await messageReceiver.ReceiveAsync(numberOfMessagesToReceive);

            foreach (Message msg in receiveList)
            {
                MemoryStream stream            = new MemoryStream(msg.Body);
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TheMsgBody));
                var body = (TheMsgBody)ser.ReadObject(stream);

                Message NewMessage = new Message();
                NewMessage.Body      = msg.Body;
                NewMessage.MessageId = msg.MessageId;

                // Process the message
                if (body.SalesValue > 9999)
                {
                    tw.Info("AWESOME - Big sales incoming!");
                }
                else
                {
                    tw.Info($"Regular sales incoming...");
                }

                NewMessage.UserProperties.Add("SalesValue", body.SalesValue);
                await messageSender.SendAsync(NewMessage);

                await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken);
            }

            // Complete the message so that it is not received again.
            // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default).
            //}
        }
示例#22
0
 public async Task Complete(string lockToken)
 {
     await _messageReceiver.CompleteAsync(lockToken).ConfigureAwait(false);
 }
示例#23
0
        /// <summary>
        /// dispatch message by its label
        /// </summary>
        /// <param name="message"></param>
        /// <param name="receiver"></param>
        /// <returns></returns>
        private async Task DispatchMessage(Message message, IMessageReceiver receiver)
        {
            if (message.Label == null || !setting.messageHandlers.ContainsKey(message.Label))
            {
                // don't have to wait the call
                /*await*/
                receiver.AbandonAsync(message.SystemProperties.LockToken);
                return;
            }

            var handlers = setting.messageHandlers[message.Label];

            if (handlers.Count == 0)
            {
                // don't have to wait the call
                /*await*/
                receiver.CompleteAsync(message.SystemProperties.LockToken);
                return;
            }

            try
            {
                var hId  = -1;
                var pack = new HandlerPack();
                pack.stationId = stationId;
                pack.receiver  = receiver;
                pack.message   = message;
                pack.terminate = () =>
                {
                    hId = handlers.Count;
                };
                pack.next = async() =>
                {
                    hId++;
                    if (hId < handlers.Count)
                    {
                        var handler = handlers[hId];
                        await handler.Invoke(pack);
                    }
                };

                // start handler function chain
                while (hId < handlers.Count)
                {
                    try
                    {
                        await pack.next();
                    }
                    catch (System.Exception e)
                    {
                        Console.WriteLine("============");
                        Console.WriteLine(e.ToString());

                        receiver.DeadLetterAsync(message.SystemProperties.LockToken);
                        break;
                    }
                }
                return;
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            // for any uncatched exception
            try
            {
                receiver.AbandonAsync(message.SystemProperties.LockToken);
            }
            catch (System.Exception e)
            {
                throw;
            }
        }
        internal void StartMessageBatchReceiver(CancellationToken cancellationToken)
        {
            SessionClient    sessionClient = null;
            IMessageReceiver receiver      = null;

            if (_isSessionsEnabled)
            {
                sessionClient = _sessionClient.Value;
            }
            else
            {
                receiver = Receiver;
            }

            Task.Run(async() =>
            {
                while (true)
                {
                    try
                    {
                        if (!_started || cancellationToken.IsCancellationRequested)
                        {
                            _logger.LogInformation("Message processing has been stopped or cancelled");
                            return;
                        }

                        if (_isSessionsEnabled && (receiver == null || receiver.IsClosedOrClosing))
                        {
                            try
                            {
                                receiver = await sessionClient.AcceptMessageSessionAsync();
                                receiver.PrefetchCount = _serviceBusOptions.PrefetchCount;
                            }
                            catch (ServiceBusTimeoutException)
                            {
                                // it's expected if the entity is empty, try next time
                                continue;
                            }
                        }

                        IList <Message> messages = await receiver.ReceiveAsync(_serviceBusOptions.BatchOptions.MaxMessageCount, _serviceBusOptions.BatchOptions.OperationTimeout);

                        if (messages != null)
                        {
                            Message[] messagesArray      = messages.ToArray();
                            ServiceBusTriggerInput input = ServiceBusTriggerInput.CreateBatch(messagesArray);
                            input.MessageReceiver        = receiver;

                            FunctionResult result = await _triggerExecutor.TryExecuteAsync(input.GetTriggerFunctionData(), cancellationToken);

                            if (cancellationToken.IsCancellationRequested)
                            {
                                return;
                            }

                            // Complete batch of messages only if the execution was successful
                            if (_serviceBusOptions.BatchOptions.AutoComplete && _started)
                            {
                                if (result.Succeeded)
                                {
                                    await receiver.CompleteAsync(messagesArray.Select(x => x.SystemProperties.LockToken));
                                }
                                else
                                {
                                    List <Task> abandonTasks = new List <Task>();
                                    foreach (var lockTocken in messagesArray.Select(x => x.SystemProperties.LockToken))
                                    {
                                        abandonTasks.Add(receiver.AbandonAsync(lockTocken));
                                    }
                                    await Task.WhenAll(abandonTasks);
                                }
                            }
                        }
                        else
                        {
                            // Close the session and release the session lock after draining all messages for the accepted session.
                            if (_isSessionsEnabled)
                            {
                                await receiver.CloseAsync();
                            }
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // Ignore as we are stopping the host
                    }
                    catch (Exception ex)
                    {
                        // Log another exception
                        _logger.LogError($"An unhandled exception occurred in the message batch receive loop", ex);

                        if (_isSessionsEnabled && receiver != null)
                        {
                            // Attempt to close the session and release session lock to accept a new session on the next loop iteration
                            try
                            {
                                await receiver.CloseAsync();
                            }
                            catch
                            {
                                // Best effort
                                receiver = null;
                            }
                        }
                    }
                }
            }, cancellationToken);
        }
示例#25
0
        internal void StartMessageBatchReceiver(CancellationToken cancellationToken)
        {
            SessionClient    sessionClient = null;
            IMessageReceiver receiver      = null;

            if (_isSessionsEnabled)
            {
                sessionClient = _messagingProvider.CreateSessionClient(_entityPath, _serviceBusAccount.ConnectionString);
            }
            else
            {
                receiver = Receiver;
            }

            Task.Run(async() =>
            {
                while (true)
                {
                    try
                    {
                        if (!_started || cancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        if (_isSessionsEnabled)
                        {
                            try
                            {
                                receiver = await sessionClient.AcceptMessageSessionAsync();
                            }
                            catch (ServiceBusTimeoutException)
                            {
                                // it's expected if the entity is empty, try next time
                                continue;
                            }
                        }

                        IList <Message> messages = await receiver.ReceiveAsync(_serviceBusOptions.BatchOptions.MaxMessageCount, _serviceBusOptions.BatchOptions.OperationTimeout);

                        if (messages != null)
                        {
                            Message[] messagesArray      = messages.ToArray();
                            ServiceBusTriggerInput input = ServiceBusTriggerInput.CreateBatch(messagesArray);
                            input.MessageReceiver        = receiver;

                            FunctionResult result = await _triggerExecutor.TryExecuteAsync(input.GetTriggerFunctionData(), cancellationToken);

                            if (cancellationToken.IsCancellationRequested)
                            {
                                return;
                            }

                            // Complete batch of messages only if the execution was successful
                            if (_serviceBusOptions.BatchOptions.AutoComplete && _started)
                            {
                                if (result.Succeeded)
                                {
                                    await receiver.CompleteAsync(messagesArray.Select(x => x.SystemProperties.LockToken));
                                }
                                else
                                {
                                    // Delivery count is not incremented if
                                    // Session is accepted, the messages within the session are not completed (even if they are locked), and the session is closed
                                    // https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sessions#impact-of-delivery-count
                                    if (_isSessionsEnabled)
                                    {
                                        List <Task> abandonTasks = new List <Task>();
                                        foreach (var lockTocken in messagesArray.Select(x => x.SystemProperties.LockToken))
                                        {
                                            abandonTasks.Add(receiver.AbandonAsync(lockTocken));
                                        }
                                        await Task.WhenAll(abandonTasks);
                                    }
                                }
                            }

                            // Close the session and release the session lock
                            if (_isSessionsEnabled)
                            {
                                await receiver.CloseAsync();
                            }
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // Ignore as we are stopping the host
                    }
                    catch (Exception ex)
                    {
                        // Log another exception
                        _logger.LogError($"An unhandled exception occurred in the message batch receive loop: {ex.ToString()}");
                    }
                }
            }, cancellationToken);
        }
示例#26
0
        public void Start(QueueReaderSettings config, ActiveQueueContext context)
        {
            _receiver = new MessageReceiver(
                new ServiceBusConnection(config.ConnectionString),
                config.QueueName,
                prefetchCount: PrefetchCount
                );

            _receiverTokenSource = new CancellationTokenSource();
            var completeTime = DateTime.UtcNow;

            _receiverTask = Task.Run(async() => {
                while (!_receiverTokenSource.IsCancellationRequested)
                {
                    var receiveTime = DateTime.UtcNow;
                    context.OnMeasure("AzureCTime", (receiveTime - completeTime).TotalMilliseconds);
                    IList <Message> messages;
                    try
                    {
                        messages = await _receiver.ReceiveAsync(MaxMessageCount);
                        if (messages == null || messages.Count == 0)
                        {
                            continue;
                        }
                    }
                    catch (Exception ex)
                    {
                        context.OnError($"AzureActiveQueue - exception received: {ex}");
                        try
                        {
                            await Task.Delay(TimeoutOnException, _receiverTokenSource.Token);
                        }
                        catch (OperationCanceledException)
                        {
                            // ignore
                        }
                        continue;
                    }

                    var processTime = DateTime.UtcNow;
                    context.OnMeasure("AzureRTime", (processTime - receiveTime).TotalMilliseconds);
                    context.OnMeasure("AzureBSize", messages.Count);

                    var lockTokens           = messages.Select(x => x.SystemProperties.LockToken);
                    var completeMessagesTask = _receiver.CompleteAsync(lockTokens);

                    foreach (var message in messages)
                    {
                        Event msg = null;
                        try
                        {
                            msg = Event.Parser.ParseFrom(message.Body);
                        }
                        catch (Exception)
                        {
                            // ToDo: remove temporal fallback
                            try
                            {
                                var buf = message.GetBody <byte[]>();
                                msg     = Event.Parser.ParseFrom(buf);
                            }
                            catch (Exception ex)
                            {
                                context.OnError($"AzureActiveQueue - not able to handle message: {ex}");
                            }

                            if (msg != null)
                            {
                                var curDate = DateTime.UtcNow;
                                var name    = $"{msg.Source}::{msg.Instance}";
                                if (!_fallbacks.TryGetValue(name, out var date) || (curDate - date).TotalMinutes > 30)
                                {
                                    context.OnVerbose($"[AzureActiveQueue] {name} used obsolete xml serialized Event");
                                    _fallbacks[name] = curDate;
                                }
                            }
                        }

                        if (msg != null)
                        {
                            context.OnReceivedMessage(msg);
                        }
                    }

                    completeTime = DateTime.UtcNow;
                    context.OnMeasure("AzurePTime", (completeTime - processTime).TotalMilliseconds);

                    try
                    {
                        await completeMessagesTask;
                    }
                    catch (Exception ex)
                    {
                        context.OnError($"Failed to complete messages: {ex}");
                    }
                }
            });
        }
        internal async Task OnMessageAsyncUnregisterHandlerShortTimeoutTestCase(
            IMessageSender messageSender,
            IMessageReceiver messageReceiver,
            int maxConcurrentCalls,
            bool autoComplete,
            int messageCount)
        {
            var count = 0;
            await TestUtility.SendMessagesAsync(messageSender, messageCount);

            messageReceiver.RegisterMessageHandler(
                async(message, token) =>
            {
                TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}");
                await Task.Delay(TimeSpan.FromSeconds(8));
                if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete)
                {
                    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
                }
                Interlocked.Increment(ref count);
            },
                new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete
            });

            await messageReceiver.UnregisterMessageHandlerAsync(TimeSpan.FromSeconds(2));

            Assert.True(count == 0);

            // Reregister won't have any problems
            count = 0;
            var remainingMessageCount = messageCount - maxConcurrentCalls;

            messageReceiver.RegisterMessageHandler(
                async(message, token) =>
            {
                TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}");
                if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete)
                {
                    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
                }
                Interlocked.Increment(ref count);
            },
                new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete
            });

            var stopwatch = Stopwatch.StartNew();

            while (stopwatch.Elapsed.TotalSeconds <= 60)
            {
                if (count == remainingMessageCount)
                {
                    TestUtility.Log($"All '{remainingMessageCount}' messages Received.");
                    break;
                }
                await Task.Delay(TimeSpan.FromSeconds(5));
            }
            Assert.True(count == remainingMessageCount);
        }
示例#28
0
 public void Complete(string lockToken)
 {
     _messageReceiver.CompleteAsync(lockToken).Wait();
 }
示例#29
0
        internal static async Task CompleteMessagesAsync(IMessageReceiver messageReceiver, IList <Message> messages)
        {
            await messageReceiver.CompleteAsync(messages.Select(message => message.SystemProperties.LockToken));

            Log($"Completed {messages.Count} messages");
        }
 public override Task CompleteAsync(
     IQueueMessage message,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     return(_messageReceiver.CompleteAsync(message.LeaseId));
 }