Esempio n. 1
0
        public void WhenMessageFails_OnMessageFault_IsCalled()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <ConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerSettings
            {
                Instances      = 1,
                Topic          = "topic1",
                ConsumerMode   = ConsumerMode.Subscriber,
                ConsumerType   = typeof(IConsumer <SomeMessage>),
                MessageType    = typeof(SomeMessage),
                OnMessageFault = onMessageFaultMock.Object
            };

            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Object, x => new byte[0]);

            var message = new SomeMessage();

            _serializerMock.Setup(x => x.Deserialize(typeof(SomeMessage), It.IsAny <byte[]>())).Returns(message);

            var ex = new Exception("Something went bad");

            _consumerMock.Setup(x => x.OnHandle(message, consumerSettings.Topic)).Returns(Task.FromException <SomeResponse>(ex));

            // act
            p.Submit(message);
            var commitedMsg = p.Commit(message);

            // assert
            commitedMsg.Should().BeSameAs(message);                                             // it should commit the failed message
            _consumerMock.Verify(x => x.OnHandle(message, consumerSettings.Topic), Times.Once); // handler called once

            onMessageFaultMock.Verify(x => x(consumerSettings, message, ex), Times.Once);       // callback called once
        }
Esempio n. 2
0
        public void WhenRequestExpired_OnMessageExpired_IsCalled()
        {
            // arrange

            var onMessageExpiredMock = new Mock <Action <ConsumerSettings, object> >();
            var consumerSettings     = new ConsumerSettings
            {
                Instances        = 1,
                Topic            = "topic1",
                ConsumerMode     = ConsumerMode.RequestResponse,
                ConsumerType     = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType      = typeof(SomeRequest),
                OnMessageExpired = onMessageExpiredMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Object, x => new byte[0]);

            var            request = new SomeRequest();
            string         requestId;
            string         replyTo;
            DateTimeOffset?expires = _currentTime.AddSeconds(-10);

            _busMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestId, out replyTo, out expires)).Returns(request);

            // act
            p.Submit(request);
            var commitedMsg = p.Commit(request);

            // assert
            commitedMsg.Should().BeSameAs(request);                                                           // it should commit the request message
            _handlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called

            onMessageExpiredMock.Verify(x => x(consumerSettings, request), Times.Once);                       // callback called once
        }
Esempio n. 3
0
        public void WhenMessageFailsThenOnMessageFaultIsCalled()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <AbstractConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerSettings
            {
                Instances      = 1,
                Topic          = "topic1",
                ConsumerMode   = ConsumerMode.Consumer,
                ConsumerType   = typeof(IConsumer <SomeMessage>),
                MessageType    = typeof(SomeMessage),
                OnMessageFault = onMessageFaultMock.Object
            };

            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var message = new SomeMessage();

            _busMock.SerializerMock.Setup(x => x.Deserialize(typeof(SomeMessage), It.IsAny <byte[]>())).Returns(message);

            var ex = new Exception("Something went bad");

            _busMock.ConsumerMock.Setup(x => x.OnHandle(message, consumerSettings.Topic))
            .Returns(Task.FromException <SomeResponse>(ex));

            // act
            p.ProcessMessage(message).Wait();

            // assert
            _busMock.ConsumerMock.Verify(x => x.OnHandle(message, consumerSettings.Topic),
                                         Times.Once);                                     // handler called once

            onMessageFaultMock.Verify(x => x(consumerSettings, message, ex), Times.Once); // callback called once
        }
Esempio n. 4
0
        public void WhenRequestExpiredThenOnMessageExpiredIsCalled()
        {
            // arrange

            var onMessageExpiredMock = new Mock <Action <AbstractConsumerSettings, object> >();
            var consumerSettings     = new ConsumerSettings
            {
                Instances        = 1,
                Topic            = "topic1",
                ConsumerMode     = ConsumerMode.RequestResponse,
                ConsumerType     = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType      = typeof(SomeRequest),
                OnMessageExpired = onMessageExpiredMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();

            requestMessage.SetHeader(ReqRespMessageHeaders.Expires, _busMock.CurrentTime.AddSeconds(-10));

            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage))
            .Returns(request);

            // act
            p.ProcessMessage(request).Wait();

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called

            onMessageExpiredMock.Verify(x => x(consumerSettings, request), Times.Once);                               // callback called once
        }
Esempio n. 5
0
        public void AfterCreation_ResolvesNInstancesOfHandler()
        {
            // arrange
            var consumerSettings = new ConsumerSettings
            {
                Instances    = 2,
                ConsumerMode = ConsumerMode.RequestResponse,
                ConsumerType = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType  = typeof(SomeRequest)
            };

            // act
            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Object, x => new byte[0]);

            // assert
            _dependencyResolverMock.Verify(x => x.Resolve(typeof(IRequestHandler <SomeRequest, SomeResponse>)), Times.Exactly(consumerSettings.Instances));
        }
Esempio n. 6
0
        public void WhenNewInstanceThenResolvesNInstancesOfConsumer()
        {
            // arrange
            var consumerSettings = new ConsumerSettings
            {
                Instances    = 2,
                ConsumerMode = ConsumerMode.Consumer,
                ConsumerType = typeof(IConsumer <SomeMessage>),
                MessageType  = typeof(SomeMessage)
            };

            // act
            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            // assert
            _busMock.DependencyResolverMock.Verify(x => x.Resolve(typeof(IConsumer <SomeMessage>)), Times.Exactly(consumerSettings.Instances));
        }
Esempio n. 7
0
        public void AfterCreation_ResolvesNInstancesOfConsumer()
        {
            // arrange
            var consumerSettings = new ConsumerSettings
            {
                Instances    = 2,
                ConsumerMode = ConsumerMode.Subscriber,
                ConsumerType = typeof(IConsumer <SomeMessage>),
                MessageType  = typeof(SomeMessage)
            };

            // act
            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Object, x => new byte[0]);

            // assert
            _busMock.DependencyResolverMock.Verify(x => x.Resolve(typeof(IConsumer <SomeMessage>)), Times.Exactly(consumerSettings.Instances));
        }
Esempio n. 8
0
        public void WhenRequestFailsThenOnMessageFaultIsCalledAndErrorResponseIsSent()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <AbstractConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerSettings
            {
                Instances      = 1,
                Topic          = "topic1",
                ConsumerMode   = ConsumerMode.RequestResponse,
                ConsumerType   = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType    = typeof(SomeRequest),
                OnMessageFault = onMessageFaultMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();
            var replyTo        = "reply-topic";
            var requestId      = "request-id";

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage))
            .Returns(request);

            var ex = new Exception("Something went bad");

            _busMock.HandlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic))
            .Returns(Task.FromException <SomeResponse>(ex));

            // act
            p.ProcessMessage(request).Wait();

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic),
                                        Times.Once); // handler called once

            onMessageFaultMock.Verify(
                x => x(consumerSettings, request, ex), Times.Once); // callback called once
            _busMock.BusMock.Verify(
                x => x.ProduceResponse(request, requestMessage, It.IsAny <SomeResponse>(), It.Is <MessageWithHeaders>(m => m.Headers[ReqRespMessageHeaders.RequestId] == requestId), It.IsAny <ConsumerSettings>()));
        }
Esempio n. 9
0
        protected void CreateConsumers()
        {
            var subscriber = Connection.GetSubscriber();

            Log.Info("Creating consumers");
            foreach (var consumerSettings in Settings.Consumers)
            {
                Log.InfoFormat(CultureInfo.InvariantCulture, "Creating consumer for {0}", consumerSettings.FormatIf(Log.IsInfoEnabled));
                var messageProcessor = new ConsumerInstancePool <byte[]>(consumerSettings, this, m => m);
                AddConsumer(consumerSettings, subscriber, messageProcessor);
            }

            if (Settings.RequestResponse != null)
            {
                Log.InfoFormat(CultureInfo.InvariantCulture, "Creating response consumer for {0}", Settings.RequestResponse.FormatIf(Log.IsInfoEnabled));
                var messageProcessor = new ResponseMessageProcessor <byte[]>(Settings.RequestResponse, this, m => m);
                AddConsumer(Settings.RequestResponse, subscriber, messageProcessor);
            }
        }
Esempio n. 10
0
        public void WhenRequestFails_OnMessageFault_IsCalled_And_ErrorResponse_IsSent()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <ConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerSettings
            {
                Instances      = 1,
                Topic          = "topic1",
                ConsumerMode   = ConsumerMode.RequestResponse,
                ConsumerType   = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType    = typeof(SomeRequest),
                OnMessageFault = onMessageFaultMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Object, x => new byte[0]);

            var            request = new SomeRequest();
            string         requestId;
            string         replyTo = "reply-topic";
            DateTimeOffset?expires;

            _busMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestId, out replyTo, out expires)).Returns(request);

            var ex = new Exception("Something went bad");

            _handlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic)).Returns(Task.FromException <SomeResponse>(ex));

            // act
            p.Submit(request);
            var commitedMsg = p.Commit(request);

            // assert
            commitedMsg.Should().BeSameAs(request);                                            // it should commit the failed request message
            _handlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic), Times.Once); // handler called once

            onMessageFaultMock.Verify(x => x(consumerSettings, request, ex), Times.Once);      // callback called once
            _busMock.Verify(x => x.Publish(typeof(SomeResponse), It.IsAny <byte[]>(), replyTo));
        }
        public ServiceBusMessageBus(MessageBusSettings settings, ServiceBusMessageBusSettings serviceBusSettings) : base(settings)
        {
            ServiceBusSettings = serviceBusSettings;

            _producerByTopic = new SafeDictionaryWrapper <string, ITopicClient>(topic =>
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, $"Creating {nameof(ITopicClient)} for name {0}", topic);
                return(ServiceBusSettings.TopicClientFactory(topic));
            });

            _producerByQueue = new SafeDictionaryWrapper <string, IQueueClient>(queue =>
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, $"Creating {nameof(IQueueClient)} for name {0}", queue);
                return(ServiceBusSettings.QueueClientFactory(queue));
            });

            foreach (var producerSettings in settings.Producers)
            {
                var      producerKind = producerSettings.GetKind();
                PathKind existingKind;

                var topic = producerSettings.DefaultTopic;
                if (topic != null)
                {
                    if (_kindByTopic.TryGetValue(topic, out existingKind))
                    {
                        if (existingKind != producerKind)
                        {
                            throw new InvalidConfigurationMessageBusException($"The same name '{topic}' was used for queue and topic. You cannot share one name for a topic and queue. Please fix your configuration.");
                        }
                    }
                    else
                    {
                        _kindByTopic.Add(topic, producerKind);
                    }
                }

                if (_kindByMessageType.TryGetValue(producerSettings.MessageType, out existingKind))
                {
                    if (existingKind != producerKind)
                    {
                        throw new InvalidConfigurationMessageBusException($"The same message type '{producerSettings.MessageType}' was used for queue and topic. You cannot share one message type for a topic and queue. Please fix your configuration.");
                    }
                }
                else
                {
                    _kindByMessageType.Add(producerSettings.MessageType, producerKind);
                }
            }

            Log.Info("Creating consumers");
            foreach (var consumerSettings in settings.Consumers)
            {
                Log.InfoFormat(CultureInfo.InvariantCulture, "Creating consumer for {0}", consumerSettings.FormatIf(Log.IsInfoEnabled));

                var messageProcessor = new ConsumerInstancePool <Message>(consumerSettings, this, m => m.Body);
                AddConsumer(consumerSettings, messageProcessor);
            }

            if (settings.RequestResponse != null)
            {
                Log.InfoFormat(CultureInfo.InvariantCulture, "Creating response consumer for {0}", settings.RequestResponse.FormatIf(Log.IsInfoEnabled));

                var messageProcessor = new ResponseMessageProcessor <Message>(settings.RequestResponse, this, m => m.Body);
                AddConsumer(settings.RequestResponse, messageProcessor);
            }
        }
Esempio n. 12
0
        public void Ensure_ExactlyNConsumerInstancesAreWorking()
        {
            const int consumerTime      = 500;
            const int consumerInstances = 8;
            const int messageCount      = 500;

            // arrange
            var consumerSettings = new ConsumerSettings
            {
                Instances    = consumerInstances,
                ConsumerMode = ConsumerMode.Subscriber,
                ConsumerType = typeof(IConsumer <SomeMessage>),
                MessageType  = typeof(SomeMessage)
            };

            var activeInstances       = 0;
            var processedMessageCount = 0;

            var maxInstances     = 0;
            var maxInstancesLock = new object();

            _consumerMock.Setup(x => x.OnHandle(It.IsAny <SomeMessage>(), It.IsAny <string>()))
            .Returns((SomeMessage msg, string topic) =>
            {
                Interlocked.Increment(ref activeInstances);
                lock (maxInstancesLock)
                {
                    // capture maximum active
                    maxInstances = Math.Max(maxInstances, activeInstances);
                }
                return(Task
                       .Delay(consumerTime)
                       .ContinueWith(t =>
                {
                    Interlocked.Decrement(ref activeInstances);
                    Interlocked.Increment(ref processedMessageCount);
                }));
            });

            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Object, x => new byte[0]);

            // act
            var         time    = Stopwatch.StartNew();
            SomeMessage lastMsg = null;

            for (var i = 0; i < messageCount; i++)
            {
                lastMsg = new SomeMessage();
                p.Submit(lastMsg);
            }
            var commitedMsg = p.Commit(lastMsg);

            time.Stop();

            // assert
            var minPossibleTime = messageCount * consumerTime / consumerSettings.Instances;
            var maxPossibleTime = messageCount * consumerTime;

            processedMessageCount.ShouldBeEquivalentTo(messageCount);
            commitedMsg.Should().BeSameAs(lastMsg); // no errors occured
            maxInstances.ShouldBeEquivalentTo(consumerSettings.Instances);
            // max concurrent consumers should reach number of desired instances
            time.ElapsedMilliseconds.Should().BeInRange(minPossibleTime, maxPossibleTime);

            var percent = Math.Round(100f * (time.ElapsedMilliseconds - minPossibleTime) / (maxPossibleTime - minPossibleTime), 2);

            Log.InfoFormat("The execution time was {0}% away from the best possible time", percent); // smallest number is better
        }
Esempio n. 13
0
        public void WhenNInstancesConfiguredThenExactlyNConsumerInstancesAreWorking()
        {
            const int consumerTime      = 500;
            const int consumerInstances = 8;
            const int messageCount      = 500;

            // arrange
            var consumerSettings = new ConsumerSettings
            {
                Instances    = consumerInstances,
                ConsumerMode = ConsumerMode.Consumer,
                ConsumerType = typeof(IConsumer <SomeMessage>),
                MessageType  = typeof(SomeMessage)
            };

            var activeInstances       = 0;
            var processedMessageCount = 0;

            var maxInstances     = 0;
            var maxInstancesLock = new object();

            _busMock.ConsumerMock.Setup(x => x.OnHandle(It.IsAny <SomeMessage>(), It.IsAny <string>()))
            .Returns((SomeMessage msg, string topic) =>
            {
                Interlocked.Increment(ref activeInstances);
                lock (maxInstancesLock)
                {
                    // capture maximum active
                    maxInstances = Math.Max(maxInstances, activeInstances);
                }

                return(Task
                       .Delay(consumerTime)
                       .ContinueWith(t =>
                {
                    Interlocked.Decrement(ref activeInstances);
                    Interlocked.Increment(ref processedMessageCount);
                }, TaskScheduler.Current));
            });

            var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            // act
            var time  = Stopwatch.StartNew();
            var tasks = new Task[messageCount];

            for (var i = 0; i < messageCount; i++)
            {
                tasks[i] = p.ProcessMessage(new SomeMessage());
            }

            Task.WaitAll(tasks);

            time.Stop();

            // assert
            var minPossibleTime = messageCount * consumerTime / consumerSettings.Instances;
            var maxPossibleTime = messageCount * consumerTime;

            processedMessageCount.Should().Be(messageCount);
            maxInstances.Should().Be(consumerSettings.Instances);
            // max concurrent consumers should reach number of desired instances
            time.ElapsedMilliseconds.Should().BeInRange(minPossibleTime, maxPossibleTime);

            var percent = Math.Round(100f * (time.ElapsedMilliseconds - minPossibleTime) / (maxPossibleTime - minPossibleTime), 2);

            Log.InfoFormat(CultureInfo.InvariantCulture, "The execution time was {0}% away from the best possible time", percent); // smallest number is better
        }