public async Task CreatePublishAndConsume()
        {
            var connectionFactory = CreateConnectionFactory();

            using (var queueClient = new RabbitMQClient(connectionFactory))
            {
                var queueName = $"IntegratedTestQueue_{Guid.NewGuid()}";

                await queueClient.EnsureQueueExistsAsync(queueName, autoDelete : true);

                await queueClient.PublishAsync("", queueName, "TestValue123");

                var receivedMessage = "";

                var worker = await SimpleProcessingWorker <string> .CreateAndStartAsync(queueClient, queueName,
                                                                                        message => DoSomething(message, out receivedMessage), CancellationToken.None);

                const int timeLimit = 10000;

                var elapsedTime = 0;

                while (receivedMessage == "" && elapsedTime < timeLimit)
                {
                    await Task.Delay(100);

                    elapsedTime += 100;
                }

                worker.Stop();

                receivedMessage.ShouldBe("TestValue123");
            }
        }
        public async Task CreatePriorityPublishAndConsume()
        {
            var connectionFactory = CreateConnectionFactory();

            using (var queueClient = new RabbitMQClient(connectionFactory))
            {
                var queueName = $"IntegratedTestQueue_{Guid.NewGuid()}";

                await queueClient.EnsureQueueExistsAsync(queueName, autoDelete : true, arguments : new Dictionary <string, object> {
                    { "x-max-priority", 1 }
                });

                await queueClient.PublishAsync("", queueName, "TestValue123", 0);

                await queueClient.PublishAsync("", queueName, "TestValue456", 1);

                await queueClient.PublishAsync("", queueName, "TestValue789", 1);

                await queueClient.PublishAsync("", queueName, "TestValue321", 0);

                var receivedMessages = new List <string>();

                var worker = await SimpleProcessingWorker <string> .CreateAndStartAsync(queueClient, queueName,
                                                                                        message =>
                {
                    DoSomething(message, out var receivedMessage);

                    receivedMessages.Add(receivedMessage);
                }, CancellationToken.None);

                const int timeLimit = 10000;

                var elapsedTime = 0;

                while (receivedMessages.Count < 4 && elapsedTime < timeLimit)
                {
                    await Task.Delay(100);

                    elapsedTime += 100;
                }

                worker.Stop();

                receivedMessages.Count.ShouldBe(4);
                receivedMessages[0].ShouldBe("TestValue456");
                receivedMessages[1].ShouldBe("TestValue789");
                receivedMessages[2].ShouldBe("TestValue123");
                receivedMessages[3].ShouldBe("TestValue321");
            }
        }
        public async Task ConsumerScaling()
        {
            var connectionFactory = CreateConnectionFactory();

            int messageAmount = 300000;

            var messages = GenerateMessages(messageAmount);

            using (var queueClient = new RabbitMQClient(connectionFactory))
            {
                var queueName = $"IntegratedTestQueue_{Guid.NewGuid()}";

                await queueClient.EnsureQueueExistsAsync(queueName);

                await queueClient.BatchPublishAsync("", queueName, messages);

                var worker = await SimpleProcessingWorker <string> .CreateAndStartAsync(queueClient, queueName,
                                                                                        async message => await Task.Delay(20), CancellationToken.None, new ConsumerCountManager(4, 50, 1000, 2000));

                const int timeLimit = 60000;

                var elapsedTime = 0;

                while (elapsedTime < timeLimit)
                {
                    await Task.Delay(100);

                    elapsedTime += 100;

                    if (elapsedTime % 1000 == 0 && messageAmount < 70000)
                    {
                        messages = GenerateMessages(10000);
                        await queueClient.BatchPublishAsync("", queueName, messages);

                        messageAmount += 1000;
                    }
                }

                worker.Stop();

                await queueClient.QueueDeleteAsync(queueName);
            }
        }
        public async Task CreateBatchPublishAndBatchConsumePartialNack()
        {
            var connectionFactory = CreateConnectionFactory();

            const int messageAmount = 200000;

            var messages = GenerateMessages(messageAmount);

            using (var queueClient = new RabbitMQClient(connectionFactory))
            {
                var queueName = $"IntegratedTestQueue_{Guid.NewGuid()}";

                await queueClient.EnsureQueueExistsAsync(queueName);

                await queueClient.BatchPublishAsync("", queueName, messages);

                var receivedMessages = new ConcurrentBag <string>();

                var worker = await SimpleProcessingWorker <string> .CreateAndStartAsync(queueClient, queueName,
                                                                                        batch => BatchDoSomethingOrFail(batch, receivedMessages), 200, CancellationToken.None, new ConsumerCountManager(1, 1));

                const int timeLimit = 90000;

                var elapsedTime = 0;

                while (receivedMessages.Count < messageAmount && elapsedTime < timeLimit)
                {
                    await Task.Delay(100);

                    elapsedTime += 100;
                }

                worker.Stop();

                await queueClient.QueueDeleteAsync(queueName);

                receivedMessages.Count.ShouldBe(messages.Count);
                receivedMessages.ShouldBeSubsetOf(messages);
            }
        }