Exemplo n.º 1
0
        public void Receive <T>(
            QueueClient client,
            Func <T, CancellationToken, Task <MessageProcessResponse> > onProcess,
            Action <ExceptionReceivedEventArgs> onError,
            Action <Exception> onProcessingError,
            Action onWait)
            where T : InstanceMessage
        {
            var options = new MessageHandlerOptions(e =>
            {
                onError(e);
                return(Task.CompletedTask);
            })
            {
                // Maximum number of Concurrent calls to the callback `ProcessMessagesAsync`, set to 1 for simplicity.
                // Set it according to how many messages the application wants to process in parallel.
                MaxConcurrentCalls = 1,

                // Indicates whether MessagePump should automatically complete the messages after returning from User Callback.
                // False below indicates the Complete will be handled by the User Callback as in `ProcessMessagesAsync` below.
                AutoComplete = false,

                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };

            client.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    // Get message
                    var data = Encoding.UTF8.GetString(message.Body);
                    T item   = JsonConvert.DeserializeObject <T>(data);

                    // Process message
                    var result = await onProcess(item, token);

                    if (result == MessageProcessResponse.Complete)
                    {
                        await client.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Abandon)
                    {
                        await client.AbandonAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Dead)
                    {
                        await client.DeadLetterAsync(message.SystemProperties.LockToken);
                    }

                    // Wait for next message
                    onWait();
                }
                catch (Exception ex)
                {
                    await client.DeadLetterAsync(message.SystemProperties.LockToken);
                    onProcessingError(ex);
                }
            }, options);
        }
Exemplo n.º 2
0
        private async Task ProcessMessageAsync(Message message, CancellationToken token)
        {
            try
            {
                T   item   = JsonConvert.DeserializeObject <T>(Encoding.UTF8.GetString(message.Body));
                var result = _processData.Process(item);

                if (result == MessageResponseEnum.Complete)
                {
                    await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
                }
                else
                if (result == MessageResponseEnum.Abandon)
                {
                    await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
                }
                else
                if (result == MessageResponseEnum.Dead)
                {
                    await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Message handler encountered an exception");
                await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
            }
        }
Exemplo n.º 3
0
        public void Receive(
            Func <T, MessageProcessResponse> onProcess,
            Action <Exception> onError,
            Action onWait)
        {
            var options = new MessageHandlerOptions(e =>
            {
                onError(e.Exception);
                return(Task.CompletedTask);
            })
            {
                AutoComplete         = false,
                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };
            var connectionString = "Endpoint=sb://chamaqueue.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=q1MKPN84/guik0UAoa4e83W6eg8z6162yFToJiKKuU4=";
            var queueName        = "SignUpQueue";

            QueueClient client = new QueueClient(connectionString, queueName, ReceiveMode.ReceiveAndDelete);

            client.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    // Get message
                    var data = Encoding.UTF8.GetString(message.Body);
                    T item   = JsonConvert.DeserializeObject <T>(data);

                    // Process message
                    var result = onProcess(item);

                    if (result == MessageProcessResponse.Complete)
                    {
                        await client.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Abandon)
                    {
                        await client.AbandonAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Dead)
                    {
                        await client.DeadLetterAsync(message.SystemProperties.LockToken);
                    }

                    // Wait for next message
                    onWait();
                }
                catch (Exception ex)
                {
                    await client.DeadLetterAsync(message.SystemProperties.LockToken);
                    onError(ex);
                }
            }, options);
        }
Exemplo n.º 4
0
        public void Receive(
            Func <Message <T>, MessageProcessingStatus> onProcess,
            Action <Exception> onError,
            Action onWait)
        {
            var options = new MessageHandlerOptions(e =>
            {
                onError(e.Exception);
                return(Task.CompletedTask);
            })
            {
                AutoComplete         = false,
                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };

            queueClient.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    // Get message
                    var data  = Encoding.UTF8.GetString(message.Body);
                    T payload = JsonConvert.DeserializeObject <T>(data);
                    var id    = message.MessageId;

                    // Process message
                    var result = onProcess(new Message <T> {
                        Id = id, Payload = payload
                    });

                    if (result == MessageProcessingStatus.Complete)
                    {
                        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessingStatus.Abandon)
                    {
                        await queueClient.AbandonAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessingStatus.Dead)
                    {
                        await queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                    }

                    // Wait for next message
                    onWait();
                }
                catch (Exception ex)
                {
                    await queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                    onError(ex);
                }
            }, options);
        }
Exemplo n.º 5
0
        public void Receive(
            Func <T, bool> onProcess,
            Action <Exception> onError,
            Action onWait)
        {
            var options = new MessageHandlerOptions(e =>
            {
                onError(e.Exception);
                return(Task.CompletedTask);
            })
            {
                AutoComplete         = false,
                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };

            client.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    // Get message
                    var data = Encoding.UTF8.GetString(message.Body);
                    T item   = JsonConvert.DeserializeObject <T>(data);

                    // Process message
                    var result = onProcess(item);

                    if (result)
                    {
                        await client.CompleteAsync(
                            message.SystemProperties.LockToken);
                    }
                    else
                    {
                        await client.DeadLetterAsync(
                            message.SystemProperties.LockToken);
                    }

                    // Wait for next message
                    onWait();
                }
                catch (Exception ex)
                {
                    await client.DeadLetterAsync(
                        message.SystemProperties.LockToken);
                    onError(ex);
                }
            }, options);
        }
Exemplo n.º 6
0
        private ValueTask <T> TryDeserialize(Message message)
        {
            try
            {
                return(new ValueTask <T>(MessagePackSerializer.Deserialize <T>(message.Body)));
            }
            catch (Exception e)
            {
                return(new ValueTask <T>(HandleException(e, message)));
            }

            async Task <T> HandleException(Exception e, Message m)
            {
                _logger.LogError(e, $"Error parsing {typeof(T).Name} from '{_queueName}'.");
                if (message.SystemProperties.DeliveryCount < 4)
                {
                    await _client.AbandonAsync(message.SystemProperties.LockToken);
                }
                else
                {
                    await _client.DeadLetterAsync(message.SystemProperties.LockToken, "Cannot parse.");
                }

                return(default(T));
            }
        }
        public async Task Receive(Func <T, Task> onProcess)
        {
            var options = new MessageHandlerOptions(e =>
            {
                return(Task.CompletedTask);
            })
            {
                AutoComplete         = false,
                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };

            _client.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    T msg = JsonConvert.DeserializeObject <T>(Encoding.UTF8.GetString(message.Body));
                    await _client.CompleteAsync(message.SystemProperties.LockToken);

                    await onProcess(msg);
                }
                catch (Exception ex)
                {
                    await _client.DeadLetterAsync(message.SystemProperties.LockToken);
                }
            }, options);

            await Task.CompletedTask;
        }
Exemplo n.º 8
0
        private async Task ProcessMessages(Message message, CancellationToken token)
        {
            try
            {
                var packet = message.GetBody <GamePacket>(new DataContractSerializer(typeof(GamePacket)));

                if (packet == null)
                {
                    OnListenerError?.Invoke(this,
                                            new GamePacketErrorArgs {
                        Message = "Message body was not serialized as a GamePacket."
                    });
                    await _client.DeadLetterAsync(message.SystemProperties.LockToken,
                                                  "Message body was not serialized as a GamePacket.");
                }
                else
                {
                    if (HandleGamePacket(packet))
                    {
                        OnGamePacketCompleted?.Invoke(this, new GamePacketArgs {
                            GamePacket = packet
                        });
                        await _client.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else
                    {
                        OnListenerError?.Invoke(this,
                                                new GamePacketErrorArgs
                        {
                            GameEvent = packet,
                            Message   = "Message was not handled completely."
                        });

                        await _client.DeadLetterAsync(message.SystemProperties.LockToken,
                                                      "Message was not handled completely.");
                    }
                }
            }
            catch (Exception e)
            {
                OnListenerError?.Invoke(this, new GamePacketErrorArgs
                {
                    Exception = e,
                    Message   = "GamePacketReceiver failed to ProcessMessage"
                });
            }
        }
Exemplo n.º 9
0
        public void Receive(Func <T, MessageProcessResponse> onProcess, Action <Exception> onError, Action onWait)
        {
            var options = new MessageHandlerOptions(e =>
            {
                onError(e.Exception);
                return(Task.CompletedTask);
            })
            {
                AutoComplete = false
            };

            _queueClient.RegisterMessageHandler(
                async(message, token) =>
            {
                try
                {
                    var data = Encoding.UTF8.GetString(message.Body);
                    T item   = JsonConvert.DeserializeObject <T>(data);

                    var result = onProcess(item);

                    switch (result)
                    {
                    case MessageProcessResponse.Complete:
                        await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
                        break;

                    case MessageProcessResponse.Abandon:
                        await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
                        break;

                    case MessageProcessResponse.Dead:
                        await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                        break;
                    }

                    //waiting for next message
                    onWait();
                }
                catch (Exception e)
                {
                    await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                    onError(e);
                }
            }, options);
        }
        public async Task GetQueueRuntimeInfoTest()
        {
            var queueName = Guid.NewGuid().ToString("D").Substring(0, 8);

            try
            {
                // Fixing Created Time
                var qd = await client.CreateQueueAsync(queueName);

                // Changing Last Updated Time
                qd.AutoDeleteOnIdle = TimeSpan.FromMinutes(100);
                var updatedQ = await client.UpdateQueueAsync(qd);

                // Populating 1 active message, 1 dead letter message and 1 scheduled message
                // Changing Last Accessed Time
                var qClient = new QueueClient(this.ConnectionString, queueName);
                await qClient.SendAsync(new Message()
                {
                    MessageId = "1"
                });

                await qClient.SendAsync(new Message()
                {
                    MessageId = "2"
                });

                await qClient.SendAsync(new Message()
                {
                    MessageId = "3", ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddDays(1)
                });

                var msg = await qClient.InnerReceiver.ReceiveAsync();

                await qClient.DeadLetterAsync(msg.SystemProperties.LockToken);

                var runtimeInfo = await client.GetQueueRuntimeInfoAsync(queueName);

                Assert.Equal(queueName, runtimeInfo.Path);
                Assert.True(runtimeInfo.CreatedAt < runtimeInfo.UpdatedAt);
                Assert.True(runtimeInfo.UpdatedAt < runtimeInfo.AccessedAt);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.ActiveMessageCount);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.DeadLetterMessageCount);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.ScheduledMessageCount);
                Assert.Equal(3, runtimeInfo.MessageCount);
                Assert.True(runtimeInfo.SizeInBytes > 0);

                await client.DeleteQueueAsync(queueName);

                await qClient.CloseAsync();
            }
            catch
            {
                await SafeDeleteQueue(queueName);

                throw;
            }
        }
Exemplo n.º 11
0
        public void Receive(Func <Student, MessageProcessResponse> onProcess,
                            Action <Exception> onError,
                            Action onWait)
        {
            var options = new MessageHandlerOptions(e => {
                LogError(e.Exception);
                return(Task.CompletedTask);
            })
            {
                AutoComplete         = false,
                MaxAutoRenewDuration = TimeSpan.FromMinutes(1)
            };

            _queueClient.RegisterMessageHandler(
                async(message, token) => {
                try {
                    var data = Encoding.UTF8.GetString(message.Body);

                    Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{data}");
                    var student = JsonConvert.DeserializeObject <Student>(data);

                    var result = onProcess(student);

                    if (result == MessageProcessResponse.Complete)
                    {
                        await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Abandon)
                    {
                        await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
                    }
                    else if (result == MessageProcessResponse.Dead)
                    {
                        await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                    }

                    onWait();
                } catch (Exception ex) {
                    _logger.Error($"Error: {ex.Message}");
                    await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
                    onError(ex);
                }
            }, options);
        }
Exemplo n.º 12
0
        public async Task <Tuple <bool, string> > ProcessQueueMessage(Message message, CancellationToken token)
        {
            bool   success = true;
            string result  = "";

            if (message != null)
            {
                try
                {
                    var body = message.GetBody <string>();

                    if (!String.IsNullOrWhiteSpace(body))
                    {
                        NotificationItem ni = null;
                        try
                        {
                            ni = ObjectSerialization.Deserialize <NotificationItem>(body);
                        }
                        catch (Exception ex)
                        {
                            success = false;
                            result  = "Unable to parse message body Exception: " + ex.ToString();
                            //message.DeadLetter();
                            await _client.DeadLetterAsync(message.SystemProperties.LockToken);
                        }

                        await ProcessNotificationItem(ni, message.MessageId, body);
                    }
                    else
                    {
                        success = false;
                        result  = "Message body is null or empty";
                    }

                    try
                    {
                        //message.Complete();
                        await _client.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    catch (MessageLockLostException)
                    {
                    }
                }
                catch (Exception ex)
                {
                    success = false;
                    result  = ex.ToString();

                    Logging.LogException(ex);
                    //message.Abandon();
                    await _client.AbandonAsync(message.SystemProperties.LockToken);
                }
            }

            return(new Tuple <bool, string>(success, result));
        }
Exemplo n.º 13
0
        public async Task <Tuple <bool, string> > ProcessQueueMessage(Message message, CancellationToken token)
        {
            bool   success = true;
            string result  = "";

            if (message != null)
            {
                try
                {
                    var body = message.GetBody <string>();

                    if (!String.IsNullOrWhiteSpace(body))
                    {
                        DistributionListQueueItem dlqi = null;
                        try
                        {
                            dlqi = ObjectSerialization.Deserialize <DistributionListQueueItem>(body);
                        }
                        catch (Exception ex)
                        {
                            success = false;
                            result  = "Unable to parse message body Exception: " + ex.ToString();
                            //message.Complete();
                            await _client.CompleteAsync(message.SystemProperties.LockToken);
                        }

                        await ProcessDistributionListQueueItem(dlqi);
                    }

                    try
                    {
                        if (success)
                        {
                            await _client.CompleteAsync(message.SystemProperties.LockToken);
                        }
                        //message.Complete();
                    }
                    catch (MessageLockLostException)
                    {
                    }
                }
                catch (Exception ex)
                {
                    result = ex.ToString();
                    Logging.LogException(ex);
                    //message.Abandon();
                    await _client.DeadLetterAsync(message.SystemProperties.LockToken);
                }
            }

            return(new Tuple <bool, string>(success, result));
        }
Exemplo n.º 14
0
        /// <summary>
        /// Process the queue defined on the Azure
        /// </summary>
        /// <returns>The task of Process Queue</returns>
        public void ProcessQueue()
        {
            try
            {
                foreach (var queue in _queues)
                {
                    MethodInfo  method       = GetMethod(queue);
                    string      queueName    = queue.Value.QueueName;
                    ReceiveMode receiveMode  = (queue.Value.DeleteAfterRead) ? ReceiveMode.ReceiveAndDelete : ReceiveMode.PeekLock;
                    int         takeQuantity = queue.Value.TakeQuantity;

                    //Register Trace on the telemetry
                    QueueClient queueReceiver = new QueueClient(GetConnection(queue), queueName, receiveMode);

                    //Register the method to process receive message
                    //The RegisterMessageHandler is validate for all register exist on the queue, without need loop for items
                    queueReceiver.RegisterMessageHandler(
                        async(message, token) =>
                    {
                        try
                        {
                            InvokeProcess(method, message.Body);
                            await queueReceiver.CompleteAsync(message.SystemProperties.LockToken);
                        }
                        catch (Exception exRegister)
                        {
                            Exception moreInfo = new Exception($"Exception reading message from queue {queueName}. See inner exception for details. Message={exRegister.Message}", exRegister);
                            //Use the class instead of interface because tracking exceptions directly is not supposed to be done outside AMAW (i.e. by the business code)
                            Workbench.Instance.Telemetry.TrackException(moreInfo);

                            //If there is a error , set DeadLetter on register
                            if (queueReceiver.ReceiveMode == ReceiveMode.PeekLock)
                            {
                                //This operation is only allowed  PeekLock
                                await queueReceiver.DeadLetterAsync(message.SystemProperties.LockToken,
                                                                    $"{exRegister.Message}\n {exRegister.InnerException?.Message}", $"{exRegister.StackTrace}");
                            }
                        }
                    },
                        new MessageHandlerOptions(ExceptionReceivedHandler)
                    {
                        MaxConcurrentCalls = takeQuantity, AutoComplete = false
                    });
                }
            }
            catch (Exception exception)
            {
                Exception moreInfo = new Exception($"Error setting up queue consumption from service bus. See inner exception for details. Message={exception.Message}", exception);
                //Use the class instead of interface because tracking exceptions directly is not supposed to be done outside AMAW (i.e. by the business code)
                Workbench.Instance.Telemetry.TrackException(moreInfo);
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Calls .DeadLetter explicitly
        /// </summary>
        public async Task DeadLetterAsync(QueueMessage message, string reason, string errorDescription, CancellationToken cancellationToken)
        {
            if (!_peekLock)
            {
                return;
            }

            if (!_messageIdToBrokeredMessage.TryRemove(message.Id, out Message bm))
            {
                return;
            }

            await _client.DeadLetterAsync(bm.MessageId);
        }
Exemplo n.º 16
0
        async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            if (message.ContentType.Equals("text/plain", StringComparison.InvariantCultureIgnoreCase))
            {
                // 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 queueClient is created in ReceiveMode.PeekLock mode (which is default).
                if (!token.IsCancellationRequested)
                {
                    await queueClient.CompleteAsync(message.SystemProperties.LockToken);
                }
            }
            else
            {
                await queueClient.DeadLetterAsync(message.SystemProperties.LockToken);
            }
        }
Exemplo n.º 17
0
        private static async Task MessageHandler(Message message, CancellationToken cancellationToken)
        {
            string messageText = Encoding.UTF8.GetString(message.Body);

            Console.Write($"[DeliveryCount: {message.SystemProperties.DeliveryCount}]");
            if (messageText.Contains("abandon", StringComparison.InvariantCultureIgnoreCase))
            {
                Console.WriteLine(" - Message abandoned");
                await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
            }
            else if (messageText.Contains("deadletter", StringComparison.InvariantCultureIgnoreCase))
            {
                Console.WriteLine(" - Message cannot be processed");
                await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken, "Poison Message", $"System cannot process the specified message: `{messageText}`");
            }
            else
            {
                Console.WriteLine($" - {messageText}");
                await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
            }
        }
Exemplo n.º 18
0
        public async Task <Order> GetNextOrderAsync()
        {
            Order order  = null;
            var   client = new QueueClient(OrderQueueCnBuilder);

            client.RegisterMessageHandler(async(msg, token) =>
            {
                Message message = msg;

                if (message != null)
                {
                    string body = Encoding.UTF8.GetString(message.Body);

                    if (body != null)
                    {
                        order = JsonSerializer.Deserialize <Order>(body);
                    }

                    if (order == null)
                    {
                        await client.DeadLetterAsync(msg.SystemProperties.LockToken);
                    }
                    else
                    {
                        await client.CompleteAsync(msg.SystemProperties.LockToken);
                    }
                }
            }, new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete       = false
            });

            await client.UnregisterMessageHandlerAsync(TimeSpan.FromMilliseconds(2000));

            await client.CloseAsync();

            return(order);
        }
Exemplo n.º 19
0
        public Task Subscribe(IMessageSubscriber handler, string queue)
        {
            _Client = new QueueClient(_ConnectionString, queue, ReceiveMode.PeekLock);

            var messageHandlerOptions = new MessageHandlerOptions((e) => { return(Task.Delay(100)); })
            {
                AutoComplete       = false,
                MaxConcurrentCalls = 1
            };

            _Client.RegisterMessageHandler(async(busMessage, concurrentToken) =>
            {
                var token = busMessage.SystemProperties.LockToken;
                try
                {
                    var body = busMessage.Body;
                    if (handler != null)
                    {
                        var message = JsonConvert.DeserializeObject <BusMessage>(Encoding.UTF8.GetString(body));

                        await handler.Handle(message);
                    }

                    await _Client.CompleteAsync(token);
                }
                catch (CommandException)
                {
                    await _Client.DeadLetterAsync(token);
                }
                catch
                {
                    await _Client.AbandonAsync(token);
                }
            }, messageHandlerOptions);

            return(Task.CompletedTask);
        }
Exemplo n.º 20
0
 public Task DeadLetterAsync(string lockToken)
 {
     return(queueClient.DeadLetterAsync(lockToken));
 }
Exemplo n.º 21
0
        public async Task GetQueueRuntimeInfoTest()
        {
            var queueName = Guid.NewGuid().ToString("D").Substring(0, 8);
            var client    = new ManagementClient(new ServiceBusConnectionStringBuilder(TestUtility.NamespaceConnectionString));
            var qClient   = new QueueClient(TestUtility.NamespaceConnectionString, queueName);

            try
            {
                // Fixing Created Time
                var qd = await client.CreateQueueAsync(queueName);

                // Changing Last Updated Time
                qd.AutoDeleteOnIdle = TimeSpan.FromMinutes(100);
                var updatedQ = await client.UpdateQueueAsync(qd);

                // Populating 1 active message, 1 dead letter message and 1 scheduled message
                // Changing Last Accessed Time

                await qClient.SendAsync(new Message()
                {
                    MessageId = "1"
                });

                await qClient.SendAsync(new Message()
                {
                    MessageId = "2"
                });

                await qClient.SendAsync(new Message()
                {
                    MessageId = "3", ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddDays(1)
                });

                var msg = await qClient.InnerReceiver.ReceiveAsync();

                await qClient.DeadLetterAsync(msg.SystemProperties.LockToken);

                var runtimeInfos = await client.GetQueuesRuntimeInfoAsync();

                Assert.True(runtimeInfos.Count > 0);
                var runtimeInfo = runtimeInfos.FirstOrDefault(e => e.Path.Equals(queueName, StringComparison.OrdinalIgnoreCase));

                Assert.NotNull(runtimeInfo);

                Assert.Equal(queueName, runtimeInfo.Path);
                Assert.True(runtimeInfo.CreatedAt < runtimeInfo.UpdatedAt);
                Assert.True(runtimeInfo.UpdatedAt < runtimeInfo.AccessedAt);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.ActiveMessageCount);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.DeadLetterMessageCount);
                Assert.Equal(1, runtimeInfo.MessageCountDetails.ScheduledMessageCount);
                Assert.Equal(3, runtimeInfo.MessageCount);
                Assert.True(runtimeInfo.SizeInBytes > 0);

                var singleRuntimeInfo = await client.GetQueueRuntimeInfoAsync(runtimeInfo.Path);

                Assert.Equal(runtimeInfo.AccessedAt, singleRuntimeInfo.AccessedAt);
                Assert.Equal(runtimeInfo.CreatedAt, singleRuntimeInfo.CreatedAt);
                Assert.Equal(runtimeInfo.UpdatedAt, singleRuntimeInfo.UpdatedAt);
                Assert.Equal(runtimeInfo.MessageCount, singleRuntimeInfo.MessageCount);
                Assert.Equal(runtimeInfo.MessageCountDetails.ActiveMessageCount, singleRuntimeInfo.MessageCountDetails.ActiveMessageCount);
                Assert.Equal(runtimeInfo.MessageCountDetails.DeadLetterMessageCount, singleRuntimeInfo.MessageCountDetails.DeadLetterMessageCount);
                Assert.Equal(runtimeInfo.MessageCountDetails.ScheduledMessageCount, singleRuntimeInfo.MessageCountDetails.ScheduledMessageCount);
                Assert.Equal(runtimeInfo.SizeInBytes, singleRuntimeInfo.SizeInBytes);

                await client.DeleteQueueAsync(queueName);
            }
            catch
            {
                await SafeDeleteQueue(client, queueName);

                throw;
            }
            finally
            {
                await qClient.CloseAsync();

                await client.CloseAsync();
            }
        }