public void When_MessageFails_Then_OnMessageFaultIsCalled()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerBuilder <SomeMessage>(new MessageBusSettings()).Topic("topic1").WithConsumer <IConsumer <SomeMessage> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageFault = onMessageFaultMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <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(_busMock.Bus, consumerSettings, message, ex), Times.Once); // callback called once
        }
        public void When_MessageArrives_Then_OnMessageArrivedIsCalled()
        {
            // arrange
            var onMessageArrivedMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object, string> >();

            var topic = "topic1";

            _busMock.Bus.Settings.OnMessageArrived = onMessageArrivedMock.Object;

            var consumerSettings = new ConsumerBuilder <SomeMessage>(_busMock.Bus.Settings).Topic(topic).WithConsumer <IConsumer <SomeMessage> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageArrived = onMessageArrivedMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <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);

            _busMock.ConsumerMock.Setup(x => x.OnHandle(message, consumerSettings.Topic))
            .Returns(Task.CompletedTask);

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

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

            onMessageArrivedMock.Verify(x => x(_busMock.Bus, consumerSettings, message, topic), Times.Exactly(2)); // callback called once for consumer and bus level
        }
        public void When_RequestExpired_Then_OnMessageExpiredIsCalled()
        {
            // arrange
            var onMessageExpiredMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object> >();
            var consumerSettings     = new HandlerBuilder <SomeRequest, SomeResponse>(new MessageBusSettings()).Topic(null).WithHandler <IRequestHandler <SomeRequest, SomeResponse> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageExpired = onMessageExpiredMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <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(_busMock.Bus, consumerSettings, request), Times.Once);                 // callback called once
        }
Ejemplo n.º 4
0
        public async Task When_MessageArrives_And_MessageScopeEnabled_Then_ScopeIsCreated_InstanceIsRetrivedFromScope_ConsumeMethodExecuted()
        {
            // arrange
            var topic = "topic1";

            var consumerSettings = new ConsumerBuilder <SomeMessage>(_busMock.Bus.Settings).Topic(topic).WithConsumer <IConsumer <SomeMessage> >().Instances(1).PerMessageScopeEnabled(true).ConsumerSettings;

            _busMock.BusMock.Setup(x => x.IsMessageScopeEnabled(consumerSettings)).Returns(true);

            var p = new ConsumerInstancePoolMessageProcessor <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);

            _busMock.ConsumerMock.Setup(x => x.OnHandle(message, consumerSettings.Topic)).Returns(Task.CompletedTask);

            Mock <IDependencyResolver> childScopeMock = null;

            _busMock.OnChildDependencyResolverCreated = mock =>
            {
                childScopeMock = mock;
            };

            // act
            await p.ProcessMessage(message);

            // assert
            _busMock.ConsumerMock.Verify(x => x.OnHandle(message, consumerSettings.Topic), Times.Once); // handler called once
            _busMock.DependencyResolverMock.Verify(x => x.CreateScope(), Times.Once);
            _busMock.ChildDependencyResolverMocks.Count.Should().Be(0);                                 // it has been disposed
            childScopeMock.Should().NotBeNull();
            childScopeMock.Verify(x => x.Resolve(typeof(IConsumer <SomeMessage>)), Times.Once);
        }
 public PartitionConsumerForConsumers(EventHubMessageBus messageBus, ConsumerSettings consumerSettings)
     : base(messageBus)
 {
     _logger       = messageBus.LoggerFactory.CreateLogger <PartitionConsumerForConsumers>();
     _instancePool = new ConsumerInstancePoolMessageProcessor <EventData>(consumerSettings, messageBus, e => e.Body.Array);
     _queueWorker  = new MessageQueueWorker <EventData>(_instancePool, new CheckpointTrigger(consumerSettings), messageBus.LoggerFactory);
 }
        public void WhenNewInstanceThenResolvesNInstancesOfConsumer()
        {
            // arrange
            var consumerSettings = new ConsumerBuilder <SomeMessage>(new MessageBusSettings()).Topic(null).WithConsumer <IConsumer <SomeMessage> >().Instances(2).ConsumerSettings;

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

            // assert
            _busMock.DependencyResolverMock.Verify(x => x.Resolve(typeof(IConsumer <SomeMessage>)), Times.Exactly(consumerSettings.Instances));
        }
Ejemplo n.º 7
0
        public void When_NewInstance_Then_DoesNotResolveHandlerInstances()
        {
            // arrange
            var consumerSettings = new HandlerBuilder <SomeRequest, SomeResponse>(new MessageBusSettings()).Topic(null).WithHandler <IRequestHandler <SomeRequest, SomeResponse> >().Instances(2).ConsumerSettings;

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

            // assert
            _busMock.DependencyResolverMock.Verify(x => x.Resolve(typeof(IRequestHandler <SomeRequest, SomeResponse>)), Times.Never);
        }
Ejemplo n.º 8
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 ConsumerInstancePoolMessageProcessor <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);
            }
        }
Ejemplo n.º 9
0
        protected void CreateConsumers()
        {
            var subscriber = Connection.GetSubscriber();

            _logger.LogInformation("Creating consumers");
            foreach (var consumerSettings in Settings.Consumers)
            {
                _logger.LogInformation("Creating consumer for {0}", consumerSettings.FormatIf(_logger.IsEnabled(LogLevel.Information)));
                var messageProcessor = new ConsumerInstancePoolMessageProcessor <byte[]>(consumerSettings, this, m => m);
                AddConsumer(consumerSettings, subscriber, messageProcessor);
            }

            if (Settings.RequestResponse != null)
            {
                _logger.LogInformation("Creating response consumer for {0}", Settings.RequestResponse.FormatIf(_logger.IsEnabled(LogLevel.Information)));
                var messageProcessor = new ResponseMessageProcessor <byte[]>(Settings.RequestResponse, this, m => m);
                AddConsumer(Settings.RequestResponse, subscriber, messageProcessor);
            }
        }
        public void WhenRequestFailsThenOnMessageFaultIsCalledAndErrorResponseIsSent()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object, Exception> >();
            var consumerSettings   = new HandlerBuilder <SomeRequest, SomeResponse>(new MessageBusSettings()).Topic(null).WithHandler <IRequestHandler <SomeRequest, SomeResponse> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageFault = onMessageFaultMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <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(_busMock.Bus, 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>()));
        }
Ejemplo n.º 11
0
        protected override void Build()
        {
            base.Build();

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

            _producerByQueue = new SafeDictionaryWrapper <string, IQueueClient>(queue =>
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, "Creating {0} for name {1}", nameof(IQueueClient), queue);
                return(ProviderSettings.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 ConfigurationMessageBusException($"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 ConfigurationMessageBusException($"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);
                }
            }

            byte[] getPayload(Message m) => m.Body;
            void initConsumerContext(Message m, ConsumerContext ctx) => ctx.SetTransportMessage(m);

            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 ConsumerInstancePoolMessageProcessor <Message>(consumerSettings, this, getPayload, initConsumerContext);
                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, getPayload);
                AddConsumer(Settings.RequestResponse, messageProcessor);
            }
        }
        public void WhenNInstancesConfiguredThenExactlyNConsumerInstancesAreWorking()
        {
            const int consumerTime      = 500;
            const int consumerInstances = 8;
            const int messageCount      = 500;

            // arrange
            var consumerSettings = new ConsumerBuilder <SomeMessage>(new MessageBusSettings()).Topic(null).WithConsumer <IConsumer <SomeMessage> >().Instances(consumerInstances).ConsumerSettings;

            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 ConsumerInstancePoolMessageProcessor <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
        }