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 }
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)); }
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); }
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); } }
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>())); }
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 }