예제 #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
        }
예제 #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
        }
예제 #3
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));
        }
예제 #4
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
        }