protected async Task StartPump(Func <MessageContext, Task> onMessage, Func <ErrorContext, Task <ErrorHandleResult> > onError, TransportTransactionMode transactionMode, Action <string, Exception> onCriticalError = null)
        {
            InputQueueName = GetTestName() + transactionMode;
            ErrorQueueName = $"{InputQueueName}.error";

            transportSettings.Set("NServiceBus.Routing.EndpointName", InputQueueName);

            var queueBindings = new QueueBindings();

            queueBindings.BindReceiving(InputQueueName);
            queueBindings.BindSending(ErrorQueueName);
            transportSettings.Set(ErrorQueueSettings.SettingsKey, ErrorQueueName);
            transportSettings.Set <QueueBindings>(queueBindings);

            transportSettings.Set <EndpointInstances>(new EndpointInstances());

            Configurer = CreateConfigurer();

            var configuration = Configurer.Configure(transportSettings, transactionMode);

            TransportInfrastructure = configuration.TransportInfrastructure;

            IgnoreUnsupportedTransactionModes(transactionMode);
            IgnoreUnsupportedDeliveryConstraints();

            ReceiveInfrastructure = TransportInfrastructure.ConfigureReceiveInfrastructure();
            SendInfrastructure    = TransportInfrastructure.ConfigureSendInfrastructure();

            lazyDispatcher = new Lazy <IDispatchMessages>(() => SendInfrastructure.DispatcherFactory());

            MessagePump = ReceiveInfrastructure.MessagePumpFactory();

            var queueCreator = ReceiveInfrastructure.QueueCreatorFactory();
            await queueCreator.CreateQueueIfNecessary(queueBindings, WindowsIdentity.GetCurrent().Name);

            var pushSettings = new PushSettings(InputQueueName, ErrorQueueName, configuration.PurgeInputQueueOnStartup, transactionMode);
            await MessagePump.Init(
                context =>
            {
                if (context.Headers.ContainsKey(TestIdHeaderName) && context.Headers[TestIdHeaderName] == testId)
                {
                    return(onMessage(context));
                }

                return(Task.FromResult(0));
            },
                context =>
            {
                if (context.Message.Headers.ContainsKey(TestIdHeaderName) && context.Message.Headers[TestIdHeaderName] == testId)
                {
                    return(onError(context));
                }

                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                new FakeCriticalError(onCriticalError),
                pushSettings);

            MessagePump.Start(configuration.PushRuntimeSettings);
        }
예제 #2
0
        public async Task Should_stop_pumping_messages_after_first_unsuccessful_receive()
        {
            var successfulReceives = 46;
            var queueSize          = 1000;

            var parser = new QueueAddressTranslator("nservicebus", "dbo", null, null);

            var inputQueue = new FakeTableBasedQueue(parser.Parse("input").QualifiedTableName, queueSize, successfulReceives);

            var pump = new MessagePump(
                m => new ProcessWithNoTransaction(sqlConnectionFactory),
                qa => qa == "input" ? (TableBasedQueue)inputQueue : new TableBasedQueue(parser.Parse(qa).QualifiedTableName, qa),
                new QueuePurger(sqlConnectionFactory),
                new ExpiredMessagesPurger(_ => sqlConnectionFactory.OpenNewConnection(), TimeSpan.MaxValue, 0),
                new QueuePeeker(sqlConnectionFactory, new QueuePeekerOptions()),
                new SchemaInspector(_ => sqlConnectionFactory.OpenNewConnection()),
                TimeSpan.MaxValue);

            await pump.Init(
                _ => Task.FromResult(0),
                _ => Task.FromResult(ErrorHandleResult.Handled),
                new CriticalError(_ => Task.FromResult(0)),
                new PushSettings("input", "error", false, TransportTransactionMode.None));

            pump.Start(new PushRuntimeSettings(1));

            await WaitUntil(() => inputQueue.NumberOfPeeks > 1);

            await pump.Stop();

            Assert.That(inputQueue.NumberOfReceives, Is.AtMost(successfulReceives + 2), "Pump should stop receives after first unsuccessful attempt.");
        }
        public async Task Pushes_received_message_into_pipeline()
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));

            await TestUtility.Delete("sales");

            var settings = new SettingsHolder();

            settings.Set("NServiceBus.SharedQueue", "sales");
            new DefaultConfigurationValues().Apply(settings);

            // setting up the environment
            var container = new TransportPartsContainer();

            var topology = await SetupEndpointOrientedTopology(container, "sales");

            // setup the operator
            var pump = new MessagePump(topology, container, settings);

            var completed = new AsyncManualResetEvent(false);
            //var error = new AsyncManualResetEvent(false);

            var       received = false;
            Exception ex       = null;

            // Dummy CriticalError
            var criticalError = new CriticalError(ctx => TaskEx.Completed);

            await pump.Init(context =>
            {
                received = true;

                completed.Set();

                return(TaskEx.Completed);
            }, null, criticalError, new PushSettings("sales", "error", false, TransportTransactionMode.ReceiveOnly));

            // execute
            pump.Start(new PushRuntimeSettings(1));

            // send message to queue
            var senderFactory = (MessageSenderCreator)container.Resolve(typeof(MessageSenderCreator));
            var sender        = await senderFactory.Create("sales", null, "namespaceName");

            await sender.Send(new BrokeredMessage());

            await completed.WaitAsync(cts.Token).IgnoreCancellation(); // Task.WhenAny(completed.WaitOne(), error.WaitOne());

            // validate
            Assert.IsTrue(received);
            Assert.IsNull(ex);

            // cleanup
            await pump.Stop();
        }
        public void ShouldThrowIfConfiguredToReceiveFromRemoteQueue()
        {
            var messagePump  = new MessagePump(mode => null);
            var pushSettings = new PushSettings("queue@remote", "error", false, TransportTransactionMode.None);

            var exception = Assert.Throws <Exception>(() =>
            {
                messagePump.Init(context => null, context => null, null, pushSettings);
            });

            Assert.That(exception.Message, Does.Contain($"MSMQ Dequeuing can only run against the local machine. Invalid inputQueue name '{pushSettings.InputQueue}'."));
        }
        public void ShouldThrowIfConfiguredToReceiveFromRemoteQueue()
        {
            var messagePump = new MessagePump(mode => null);
            var pushSettings = new PushSettings("queue@remote", "error", false, TransportTransactionMode.None);

            var exception = Assert.Throws<Exception>(() =>
            {
                messagePump.Init(context => null, context => null, null, pushSettings);
            });

            Assert.That(exception.Message, Does.Contain($"MSMQ Dequeuing can only run against the local machine. Invalid inputQueue name '{pushSettings.InputQueue}'."));
        }
        public void Should_throw()
        {
            var settings = SettingsHolderFactory.BuildWithSerializer();

            settings.Set("NServiceBus.SharedQueue", "sales");
            DefaultConfigurationValues.Apply(settings);

            var pump          = new MessagePump(null, null, null, null, settings, "sales");
            var criticalError = new CriticalError(ctx => TaskEx.Completed);

            const bool purgeOnStartup = true;

            Assert.ThrowsAsync <InvalidOperationException>(async() => await pump.Init(context => TaskEx.Completed, null, criticalError, new PushSettings("sales", "error", purgeOnStartup, TransportTransactionMode.SendsAtomicWithReceive)));
        }
예제 #7
0
        public async Task Should_trigger_circuit_breaker()
        {
            var cts       = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            var container = new TransportPartsContainer();

            var fakeTopologyOperator = new FakeTopologyOperator();

            container.Register <IOperateTopology>(() => fakeTopologyOperator);

            var settings = new SettingsHolder();

            settings.Set("NServiceBus.SharedQueue", "sales");
            new DefaultConfigurationValues().Apply(settings);
            container.Register <ReadOnlySettings>(() => settings);

            Exception exceptionReceivedByCircuitBreaker = null;
            var       criticalErrorWasRaised            = false;

            var tcs = new TaskCompletionSource <object>();

            cts.Token.Register(() => tcs.TrySetCanceled());

            // setup critical error action to capture exception thrown by message pump
            var criticalError = new FakeCriticalError(ctx =>
            {
                criticalErrorWasRaised            = true;
                exceptionReceivedByCircuitBreaker = ctx.Exception;

                tcs.TrySetResult(null);

                return(TaskEx.Completed);
            });

            var pump = new MessagePump(new FakeTopology(), container, settings, TimeSpan.FromSeconds(1));
            await pump.Init(context => TaskEx.Completed, null, criticalError, new PushSettings("sales", "error", false, TransportTransactionMode.ReceiveOnly));

            pump.Start(new PushRuntimeSettings(1));

            await fakeTopologyOperator.onIncomingMessage(new IncomingMessageDetails("id", new Dictionary <string, string>(), new byte[0]), new FakeReceiveContext());

            var exceptionThrownByMessagePump = new Exception("kaboom");
            await fakeTopologyOperator.onError(exceptionThrownByMessagePump);

            await tcs.Task; // let circuit breaker kick in

            // validate
            Assert.IsTrue(criticalErrorWasRaised, "Expected critical error to be raised, but it wasn't");
            Assert.AreEqual(exceptionThrownByMessagePump, exceptionReceivedByCircuitBreaker, "Exception circuit breaker got should be the same as the one raised by message pump");
        }
        public void SetUp()
        {
            routingTopology  = new ConventionalRoutingTopology(true);
            receivedMessages = new BlockingCollection <IncomingMessage>();

            var settings = new SettingsHolder();

            settings.Set("NServiceBus.Routing.EndpointName", "endpoint");

            var connectionString = Environment.GetEnvironmentVariable("RabbitMQTransport.ConnectionString");

            ConnectionConfiguration config;

            if (connectionString != null)
            {
                var parser = new ConnectionStringParser(settings);
                config = parser.Parse(connectionString);
            }
            else
            {
                config      = new ConnectionConfiguration(settings);
                config.Host = "localhost";
            }

            connectionFactory = new ConnectionFactory(config);
            channelProvider   = new ChannelProvider(connectionFactory, routingTopology, true);

            messageDispatcher = new MessageDispatcher(channelProvider);

            var purger = new QueuePurger(connectionFactory);

            messagePump = new MessagePump(connectionFactory, new MessageConverter(), "Unit test", channelProvider, purger, TimeSpan.FromMinutes(2), 3, 0);

            MakeSureQueueAndExchangeExists(ReceiverQueue);

            subscriptionManager = new SubscriptionManager(connectionFactory, routingTopology, ReceiverQueue);

            messagePump.Init(messageContext =>
            {
                receivedMessages.Add(new IncomingMessage(messageContext.MessageId, messageContext.Headers, messageContext.Body));
                return(TaskEx.CompletedTask);
            },
                             ErrorContext => Task.FromResult(ErrorHandleResult.Handled),
                             new CriticalError(_ => TaskEx.CompletedTask),
                             new PushSettings(ReceiverQueue, "error", true, TransportTransactionMode.ReceiveOnly)
                             ).GetAwaiter().GetResult();

            messagePump.Start(new PushRuntimeSettings(MaximumConcurrency));
        }
예제 #9
0
        public void Should_throw()
        {
            var container = new TransportPartsContainer();

            container.Register <TopologyOperator>();
            var settings = new SettingsHolder();

            settings.Set("NServiceBus.SharedQueue", "sales");
            new DefaultConfigurationValues().Apply(settings);
            container.Register <ReadOnlySettings>(() => settings);

            var pump          = new MessagePump(null, container, settings);
            var criticalError = new CriticalError(ctx => TaskEx.Completed);

            const bool purgeOnStartup = true;

            Assert.ThrowsAsync <InvalidOperationException> (async() => await pump.Init(context => TaskEx.Completed, null, criticalError, new PushSettings("sales", "error", purgeOnStartup, TransportTransactionMode.SendsAtomicWithReceive)));
        }
        public async Task Should_stop_pumping_messages_after_first_unsuccessful_receive()
        {
            var successfulReceives = 46;
            var queueSize          = 1000;

            var parser = new QueueAddressTranslator("nservicebus", "dbo", null, null);

            var inputQueue = new FakeTableBasedQueue(parser.Parse("input").QualifiedTableName, queueSize, successfulReceives);

            var connectionString = Environment.GetEnvironmentVariable("SqlServerTransportConnectionString");

            if (string.IsNullOrEmpty(connectionString))
            {
                connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=nservicebus;Integrated Security=True";
            }

            var sqlConnectionFactory = SqlConnectionFactory.Default(connectionString);

            var pump = new MessagePump(
                m => new ProcessWithNoTransaction(sqlConnectionFactory, null),
                qa => qa == "input" ? (TableBasedQueue)inputQueue : new TableBasedQueue(parser.Parse(qa).QualifiedTableName, qa, true),
                new QueuePurger(sqlConnectionFactory),
                new NoOpExpiredMessagesPurger(),
                new QueuePeeker(sqlConnectionFactory, new QueuePeekerOptions()),
                new QueuePeekerOptions(),
                new SchemaInspector(_ => sqlConnectionFactory.OpenNewConnection(), false),
                TimeSpan.MaxValue);

            await pump.Init(
                _ => Task.FromResult(0),
                _ => Task.FromResult(ErrorHandleResult.Handled),
                new CriticalError(_ => Task.FromResult(0)),
                new PushSettings("input", "error", false, TransportTransactionMode.None));

            pump.Start(new PushRuntimeSettings(1));

            await WaitUntil(() => inputQueue.NumberOfPeeks > 1);

            await pump.Stop();

            Assert.That(inputQueue.NumberOfReceives, Is.AtMost(successfulReceives + 2), "Pump should stop receives after first unsuccessful attempt.");
        }
예제 #11
0
        public void SetUp()
        {
            routingTopology  = new ConventionalRoutingTopology(true);
            receivedMessages = new BlockingCollection <IncomingMessage>();

            var connectionString = Environment.GetEnvironmentVariable("RabbitMQTransport_ConnectionString");

            if (string.IsNullOrEmpty(connectionString))
            {
                throw new Exception("The 'RabbitMQTransport_ConnectionString' environment variable is not set.");
            }

            var config = ConnectionConfiguration.Create(connectionString, ReceiverQueue);

            connectionFactory = new ConnectionFactory(ReceiverQueue, config, null, false, false);
            channelProvider   = new ChannelProvider(connectionFactory, config.RetryDelay, routingTopology, true);
            channelProvider.CreateConnection();

            messageDispatcher = new MessageDispatcher(channelProvider);

            var purger = new QueuePurger(connectionFactory);

            messagePump = new MessagePump(connectionFactory, new MessageConverter(), "Unit test", channelProvider, purger, TimeSpan.FromMinutes(2), 3, 0);

            routingTopology.Reset(connectionFactory, new[] { ReceiverQueue }.Concat(AdditionalReceiverQueues), new[] { ErrorQueue });

            subscriptionManager = new SubscriptionManager(connectionFactory, routingTopology, ReceiverQueue);

            messagePump.Init(messageContext =>
            {
                receivedMessages.Add(new IncomingMessage(messageContext.MessageId, messageContext.Headers, messageContext.Body));
                return(TaskEx.CompletedTask);
            },
                             ErrorContext => Task.FromResult(ErrorHandleResult.Handled),
                             new CriticalError(_ => TaskEx.CompletedTask),
                             new PushSettings(ReceiverQueue, ErrorQueue, true, TransportTransactionMode.ReceiveOnly)
                             ).GetAwaiter().GetResult();

            messagePump.Start(new PushRuntimeSettings(MaximumConcurrency));
        }
예제 #12
0
        public void SetUp(params Type[] typesToSubscribeTo)
        {
            receivedMessages = new BlockingCollection <IncomingMessage>();

            Environment.SetEnvironmentVariable("KafkaTransport.ConnectionString", "127.0.0.1:9092");
            var            connectionString = Environment.GetEnvironmentVariable("KafkaTransport.ConnectionString");//"127.0.0.1:9092"
            SettingsHolder settingsHolder   = new SettingsHolder();

            settingsHolder.Set("NServiceBus.Routing.EndpointName", endpointName);

            var kafkaTransport = new KafkaTransport();
            var infra          = kafkaTransport.Initialize(settingsHolder, connectionString);

            messageDispatcher = new MessageDispatcher(new Transports.Kafka.Connection.ProducerFactory(connectionString));


            messagePump = new MessagePump(settingsHolder, connectionString);


            subscriptionManager = new SubscriptionManager(messagePump, null);

            foreach (var t in typesToSubscribeTo)
            {
                subscriptionManager.Subscribe(t, new ContextBag());
            }


            messagePump.Init(messageContext =>
            {
                receivedMessages.Add(new IncomingMessage(messageContext.MessageId, messageContext.Headers, messageContext.Body));
                return(Task.FromResult(0));
            },
                             ErrorContext => Task.FromResult(ErrorHandleResult.Handled),
                             new CriticalError(_ => Task.FromResult(0)),
                             new PushSettings(endpointName, ErrorQueue, true, TransportTransactionMode.ReceiveOnly)
                             ).GetAwaiter().GetResult();

            messagePump.Start(new PushRuntimeSettings(MaximumConcurrency));
        }
        protected async Task StartPump(Func <MessageContext, Task> onMessage, Func <ErrorContext, Task <ErrorHandleResult> > onError, TransportTransactionMode transactionMode, Action <string, Exception> onCriticalError = null)
        {
            InputQueueName = GetTestName() + transactionMode;
            ErrorQueueName = $"{InputQueueName}.error";

            var endpointConfiguration = new EndpointConfiguration(InputQueueName);

            endpointConfiguration.SendFailedMessagesTo(ErrorQueueName);

            transportSettings = endpointConfiguration.GetSettings();


            var queueBindings = transportSettings.Get <QueueBindings>();

            queueBindings.BindReceiving(InputQueueName);
            queueBindings.BindSending(ErrorQueueName);

            Configurer = CreateConfigurer();

            var configuration = Configurer.Configure(transportSettings, transactionMode);

            TransportInfrastructure = configuration.TransportInfrastructure;

            IgnoreUnsupportedTransactionModes(transactionMode);
            IgnoreUnsupportedDeliveryConstraints();

            ReceiveInfrastructure = TransportInfrastructure.ConfigureReceiveInfrastructure();

            var queueCreator = ReceiveInfrastructure.QueueCreatorFactory();
            var userName     = GetUserName();
            await queueCreator.CreateQueueIfNecessary(queueBindings, userName);

            var result = await ReceiveInfrastructure.PreStartupCheck();

            if (result.Succeeded == false)
            {
                throw new Exception($"Pre start-up check failed: {result.ErrorMessage}");
            }

            await TransportInfrastructure.Start();

            SendInfrastructure = TransportInfrastructure.ConfigureSendInfrastructure();
            lazyDispatcher     = new Lazy <IDispatchMessages>(() => SendInfrastructure.DispatcherFactory());

            MessagePump = ReceiveInfrastructure.MessagePumpFactory();
            await MessagePump.Init(
                context =>
            {
                if (context.Headers.ContainsKey(TestIdHeaderName) && context.Headers[TestIdHeaderName] == testId)
                {
                    return(onMessage(context));
                }

                return(Task.FromResult(0));
            },
                context =>
            {
                if (context.Message.Headers.ContainsKey(TestIdHeaderName) && context.Message.Headers[TestIdHeaderName] == testId)
                {
                    return(onError(context));
                }

                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                new FakeCriticalError(onCriticalError),
                new PushSettings(InputQueueName, ErrorQueueName, configuration.PurgeInputQueueOnStartup, transactionMode));

            result = await SendInfrastructure.PreStartupCheck();

            if (result.Succeeded == false)
            {
                throw new Exception($"Pre start-up check failed: {result.ErrorMessage}");
            }

            MessagePump.Start(configuration.PushRuntimeSettings);
        }