public async Task Should_reset_delivery_counter(TransportTransactionMode transactionMode)
        {
            var sentDelayedMessage = CreateTaskCompletionSource <ErrorContext>();

            var sendingDelayedMessage = false;

            await StartPump(
                (_, __) => throw new Exception("Simulated exception"),
                async (context, _) =>
            {
                if (!sendingDelayedMessage)
                {
                    sendingDelayedMessage = true;
                    await SendMessage(InputQueueName, context.Message.Headers, context.TransportTransaction);
                }
                else
                {
                    sentDelayedMessage.SetResult(context);
                }

                return(ErrorHandleResult.Handled);
            },
                transactionMode);

            await SendMessage(InputQueueName);

            var errorContext = await sentDelayedMessage.Task;

            Assert.AreEqual(1, errorContext.ImmediateProcessingFailures, "Should track delivery attempts between immediate retries");
        }
        public async Task Should_dispatch_the_message(TransportTransactionMode transactionMode)
        {
            var messageReceived = new TaskCompletionSource<bool>();

            OnTestTimeout(() => messageReceived.SetResult(false));

            await StartPump(
                context =>
                {
                    if (context.Headers.ContainsKey("FromOnError"))
                    {
                        messageReceived.SetResult(true);
                        return Task.FromResult(0);
                    }

                    throw new Exception("Simulated exception");
                },
                async context =>
                {
                    await SendMessage(InputQueueName, new Dictionary<string, string> { { "FromOnError", "true" } }, context.TransportTransaction);

                    return ErrorHandleResult.Handled;
                }, transactionMode);

            await SendMessage(InputQueueName);

            Assert.True(await messageReceived.Task, "Message not dispatched properly");
        }
Esempio n. 3
0
        public async Task Should_call_on_error(TransportTransactionMode transactionMode)
        {
            var onErrorCalled = new TaskCompletionSource <ErrorContext>();

            OnTestTimeout(() => onErrorCalled.SetCanceled());

            await StartPump(context =>
            {
                throw new Exception("Simulated exception");
            },
                            context =>
            {
                onErrorCalled.SetResult(context);

                return(Task.FromResult(ErrorHandleResult.Handled));
            }, transactionMode);

            await SendMessage(InputQueueName, new Dictionary <string, string> {
                { "MyHeader", "MyValue" }
            });

            var errorContext = await onErrorCalled.Task;

            Assert.AreEqual(errorContext.Exception.Message, "Simulated exception", "Should preserve the exception");
            Assert.AreEqual(1, errorContext.ImmediateProcessingFailures, "Should track the number of delivery attempts");
            Assert.AreEqual("MyValue", errorContext.Message.Headers["MyHeader"], "Should pass the message headers");
        }
        public async Task Should_retry_immediately(TransportTransactionMode transactionMode)
        {
            var messageRedelivered = new TaskCompletionSource<bool>();

            OnTestTimeout(() => messageRedelivered.SetResult(false));

            var hasBeenCalled = false;
            var onErrorCalled = false;

            await StartPump(
                context =>
                {
                    if (hasBeenCalled)
                    {
                        messageRedelivered.SetResult(true);
                        return Task.FromResult(0);
                    }
                    hasBeenCalled = true;
                    context.ReceiveCancellationTokenSource.Cancel();

                    return Task.FromResult(0);
                },
                context =>
                {
                    onErrorCalled = true;
                    return Task.FromResult(ErrorHandleResult.RetryRequired);
                }, transactionMode);

            await SendMessage(InputQueueName);

            Assert.True(await messageRedelivered.Task, "Should redeliver message");
            Assert.False(onErrorCalled, "Abort should not invoke on error");
        }
        public async Task Should_call_on_error(TransportTransactionMode transactionMode)
        {
            var onErrorCalled = new TaskCompletionSource<ErrorContext>();

            OnTestTimeout(() => onErrorCalled.SetCanceled());

            await StartPump(context =>
            {
                throw new Exception("Simulated exception");
            },
                context =>
                {
                    onErrorCalled.SetResult(context);

                    return Task.FromResult(ErrorHandleResult.Handled);
                }, transactionMode);

            await SendMessage(InputQueueName, new Dictionary<string, string> { { "MyHeader", "MyValue" } });

            var errorContext = await onErrorCalled.Task;

            Assert.AreEqual(errorContext.Exception.Message, "Simulated exception", "Should preserve the exception");
            Assert.AreEqual(1, errorContext.ImmediateProcessingFailures, "Should track the number of delivery attempts");
            Assert.AreEqual("MyValue", errorContext.Message.Headers["MyHeader"], "Should pass the message headers");
        }
        public async Task Should_retry_immediately(TransportTransactionMode transactionMode)
        {
            var messageRetried = new TaskCompletionSource<bool>();

            OnTestTimeout(() => messageRetried.SetResult(false));

            var hasBeenCalled = false;

            await StartPump(
                context =>
                {
                    if (hasBeenCalled)
                    {
                        messageRetried.SetResult(true);
                        return Task.FromResult(0);
                    }
                    hasBeenCalled = true;
                    throw new Exception("Simulated exception");
                },
                context => Task.FromResult(ErrorHandleResult.RetryRequired), transactionMode);

            await SendMessage(InputQueueName);

            Assert.True(await messageRetried.Task, "Should retry if asked so");
        }
    public async Task Write(TransportTransactionMode transactionMode)
    {
        var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(nameof(MsmqTransportIntegrationTests));
        var typesToScan           = TypeScanner.NestedTypes <MsmqTransportIntegrationTests>();

        endpointConfiguration.SetTypesToScan(typesToScan);
        var transport = endpointConfiguration.UseTransport <MsmqTransport>();

        transport.Transactions(transactionMode);
        var persistence = endpointConfiguration.UsePersistence <SqlPersistence>();

        persistence.ConnectionBuilder(MsSqlConnectionBuilder.Build);
        persistence.DisableInstaller();
        persistence.SubscriptionSettings().DisableCache();

        var endpoint = await Endpoint.Start(endpointConfiguration).ConfigureAwait(false);

        var startSagaMessage = new StartSagaMessage
        {
            StartId = Guid.NewGuid()
        };
        await endpoint.SendLocal(startSagaMessage).ConfigureAwait(false);

        ManualResetEvent.WaitOne();
        await endpoint.Stop().ConfigureAwait(false);
    }
        public async Task Should_complete(TransportTransactionMode transactionMode)
        {
            CancellationToken onErrorToken = default;

            var onErrorStarted = CreateTaskCompletionSource();

            var pumpStopping = CreateTaskCompletionSource();

            await StartPump(
                (_, __) => throw new Exception(),
                async (_, cancellationToken) =>
            {
                onErrorStarted.SetResult();
                await pumpStopping.Task;
                onErrorToken = cancellationToken;
                return(ErrorHandleResult.Handled);
            },
                transactionMode);

            await SendMessage(InputQueueName);

            await onErrorStarted.Task;

            var pumpTask = StopPump();

            pumpStopping.SetResult();

            await pumpTask;

            Assert.False(onErrorToken.IsCancellationRequested);
        }
Esempio n. 9
0
        public async Task Should_roll_back(TransportTransactionMode transactionMode)
        {
            var errorHandled = CreateTaskCompletionSource <ErrorContext>();

            await StartPump(
                (context, _) =>
            {
                context.Headers["test-header"] = "modified";
                throw new Exception();
            },
                (context, __) =>
            {
                errorHandled.SetResult(context);
                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                transactionMode);

            await SendMessage(InputQueueName, new Dictionary <string, string> {
                { "test-header", "original" }
            });

            var errorContext = await errorHandled.Task;

            Assert.AreEqual("original", errorContext.Message.Headers["test-header"]);
        }
Esempio n. 10
0
    public TransportConfigurationResult Configure(SettingsHolder settings, TransportTransactionMode transactionMode)
    {
        settings.Set("Transport.ConnectionString", Environment.GetEnvironmentVariable("AzureServiceBus.ConnectionString"));
        var connectionString = settings.Get <string>("Transport.ConnectionString");

        settings.Set <Conventions>(new Conventions());
        settings.Set(WellKnownConfigurationKeys.Core.MainSerializerSettingsKey, Tuple.Create <SerializationDefinition, SettingsHolder>(new XmlSerializer(), settings));
        settings.Set("NServiceBus.SharedQueue", settings.Get("NServiceBus.Routing.EndpointName"));
        var topologyName = Environment.GetEnvironmentVariable("AzureServiceBusTransport.Topology", EnvironmentVariableTarget.User);

        topologyName = topologyName ?? Environment.GetEnvironmentVariable("AzureServiceBusTransport.Topology");

        var transportExtension = new TransportExtensions <AzureServiceBusTransport>(settings);

        if (topologyName == "ForwardingTopology")
        {
            transportExtension.UseForwardingTopology();
        }
        else
        {
            transportExtension.UseEndpointOrientedTopology();
        }

        var transport      = new AzureServiceBusTransport();
        var infrastructure = transport.Initialize(settings, connectionString);

        return(new TransportConfigurationResult
        {
            PurgeInputQueueOnStartup = false,
            TransportInfrastructure = infrastructure
        });
    }
Esempio n. 11
0
        public async Task Should_retry_immediately(TransportTransactionMode transactionMode)
        {
            var completed = new TaskCompletionSource <bool>();

            OnTestTimeout(() => completed.SetCanceled());

            var retrying = false;
            var retried  = true;

            await StartPump(
                (context, _) =>
            {
                if (retrying)
                {
                    retried = true;
                    return(Task.CompletedTask);
                }

                throw new Exception("Simulated exception");
            },
                (context, _) =>
            {
                retrying = true;
                return(Task.FromResult(ErrorHandleResult.RetryRequired));
            },
                (_, __) => retried?completed.SetCompleted() : Task.CompletedTask,
                    transactionMode);

            await SendMessage(InputQueueName);

            _ = await completed.Task;
        }
        public async Task Should_not_emit_messages(TransportTransactionMode transactionMode)
        {
            var messageEmitted = false;

            var completed = new TaskCompletionSource <bool>();

            OnTestTimeout(() => completed.SetCanceled());

            await StartPump(
                async (context, _) =>
            {
                if (context.Headers.ContainsKey("SentBeforeFailure"))
                {
                    messageEmitted = true;
                    return;
                }

                await SendMessage(InputQueueName, new Dictionary <string, string> {
                    { "SentBeforeFailure", "" }
                }, context.TransportTransaction);

                throw new Exception("Simulated exception");
            },
                (errorContext, __) => Task.FromResult(ErrorHandleResult.Handled),
                (context, __) => completed.SetCompleted(),
                transactionMode);

            await SendMessage(InputQueueName);

            _ = await completed.Task;

            await StopPump(CancellationToken.None);

            Assert.False(messageEmitted);
        }
        public async Task Should_not_raise_critical_error(TransportTransactionMode transactionMode)
        {
            var    onErrorCalled        = CreateTaskCompletionSource <bool>();
            string criticalErrorDetails = null;

            await StartPump(
                (_, __) =>
            {
                throw new Exception("from onMessage");
            },
                (_, __) =>
            {
                onErrorCalled.TrySetResult(true);
                throw new ServiceBusException("from onError", ServiceBusFailureReason.ServiceTimeout);
            },
                transactionMode,
                (msg, ex, ___) =>
            {
                criticalErrorDetails = $"{msg}, Exception: {ex}";
            }
                );

            await SendMessage(InputQueueName);

            await onErrorCalled.Task;

            await StopPump();

            Assert.IsNull(criticalErrorDetails, $"Should not invoke critical error for {nameof(ServiceBusException)}");
        }
 public Configuration(LogicalAddress logicalAddress,
                      string queueNameBase,
                      string localAddress,
                      string instanceSpecificQueue,
                      TransportTransactionMode transactionMode,
                      PushRuntimeSettings pushRuntimeSettings,
                      bool purgeOnStartup,
                      Notification <ReceivePipelineCompleted> pipelineCompletedSubscribers,
                      bool isSendOnlyEndpoint,
                      List <Type> executeTheseHandlersFirst,
                      MessageHandlerRegistry messageHandlerRegistry,
                      bool createQueues, TransportSeam transportSeam)
 {
     LogicalAddress               = logicalAddress;
     QueueNameBase                = queueNameBase;
     LocalAddress                 = localAddress;
     InstanceSpecificQueue        = instanceSpecificQueue;
     TransactionMode              = transactionMode;
     PushRuntimeSettings          = pushRuntimeSettings;
     PurgeOnStartup               = purgeOnStartup;
     IsSendOnlyEndpoint           = isSendOnlyEndpoint;
     PipelineCompletedSubscribers = pipelineCompletedSubscribers;
     ExecuteTheseHandlersFirst    = executeTheseHandlersFirst;
     satelliteDefinitions         = new List <SatelliteDefinition>();
     this.messageHandlerRegistry  = messageHandlerRegistry;
     CreateQueues                 = createQueues;
     this.transportSeam           = transportSeam;
 }
Esempio n. 15
0
        public async Task Should_allow_message_processing_to_complete(TransportTransactionMode transactionMode)
        {
            var messageProcessingStarted   = new TaskCompletionSource <bool>();
            var messageProcessingCancelled = new TaskCompletionSource <bool>();

            OnTestTimeout(() =>
            {
                messageProcessingStarted.SetCanceled();
                messageProcessingCancelled.SetCanceled();
            });

            await StartPump(
                async (_, cancellationToken) =>
            {
                messageProcessingStarted.SetResult(true);

                try
                {
                    await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    messageProcessingCancelled.SetResult(true);
                }

                messageProcessingCancelled.SetResult(false);
            },
                (_, __) => Task.FromResult(ErrorHandleResult.Handled),
                transactionMode);

            await SendMessage(InputQueueName);

            _ = await messageProcessingStarted.Task;

            await StopPump(default);
        public async Task Should_cancel(TransportTransactionMode transactionMode)
        {
            var started     = CreateTaskCompletionSource();
            var wasCanceled = CreateTaskCompletionSource <bool>();

            await StartPump(
                async (_, cancellationToken) =>
            {
                started.SetResult();

                try
                {
                    await Task.Delay(TestTimeout, cancellationToken);
                }
                catch (Exception ex) when(ex.IsCausedBy(cancellationToken))
                {
                    wasCanceled.SetResult(true);
                    throw;
                }

                wasCanceled.SetResult(false);
            },
                (_, __) => Task.FromResult(ErrorHandleResult.Handled),
                transactionMode);

            await SendMessage(InputQueueName);

            await started.Task;

            await StopPump(new CancellationToken(true));

            Assert.True(await wasCanceled.Task, "onMessage was not canceled.");
        }
        public async Task Should_emit_messages(TransportTransactionMode transactionMode)
        {
            var completed = new TaskCompletionSource <bool>();

            OnTestTimeout(() => completed.SetCanceled());

            await StartPump(
                async (context, _) =>
            {
                if (context.Headers.ContainsKey("IsolatedSend"))
                {
                    return;
                }

                await SendMessage(
                    InputQueueName,
                    new Dictionary <string, string> {
                    { "IsolatedSend", "" }
                },
                    context.TransportTransaction,
                    dispatchConsistency: DispatchConsistency.Isolated);

                throw new Exception("Simulated exception");
            },
                (errorContext, __) => Task.FromResult(ErrorHandleResult.Handled),
                (context, __) => context.Headers.ContainsKey("IsolatedSend")?completed.SetCompleted() : Task.CompletedTask,
                    transactionMode);

            await SendMessage(InputQueueName);

            _ = await completed.Task;
        }
        public async Task Should_roll_back(TransportTransactionMode transactionMode)
        {
            var retried = CreateTaskCompletionSource <MessageContext>();

            var retrying = false;

            await StartPump(
                (context, _) =>
            {
                if (retrying)
                {
                    return(retried.SetCompleted(context));
                }

                context.Headers["test-header"] = "modified";
                throw new Exception();
            },
                (context, _) =>
            {
                retrying = true;
                return(Task.FromResult(ErrorHandleResult.RetryRequired));
            },
                transactionMode);

            await SendMessage(InputQueueName, new Dictionary <string, string> {
                { "test-header", "original" }
            });

            var retryMessageContext = await retried.Task;

            Assert.AreEqual("original", retryMessageContext.Headers["test-header"]);
        }
Esempio n. 19
0
    public TransportConfigurationResult Configure(SettingsHolder settings, TransportTransactionMode transportTransactionMode)
    {
#if !NETFRAMEWORK
        if (transportTransactionMode == TransportTransactionMode.TransactionScope)
        {
            NUnit.Framework.Assert.Ignore("TransactionScope not supported in .NET Core");
        }
#endif
        this.settings = settings;
        settings.Set(transportTransactionMode);
        settings.Set("NServiceBus.SharedQueue", settings.EndpointName());
        var delayedDeliverySettings = new DelayedDeliverySettings(settings);
        delayedDeliverySettings.TableSuffix("Delayed");

        var pubSubSettings = new SubscriptionSettings();
        pubSubSettings.DisableSubscriptionCache();
        settings.Set(pubSubSettings);

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

        var logicalAddress = LogicalAddress.CreateLocalAddress(settings.ErrorQueueAddress(), new Dictionary <string, string>());
        var localAddress   = settings.EndpointName();
        return(new TransportConfigurationResult
        {
            TransportInfrastructure = new SqlServerTransportInfrastructure("nservicebus", settings, connectionString, () => localAddress, () => logicalAddress, false)
        });
    }
Esempio n. 20
0
        public async Task Should_dispatch_the_message(TransportTransactionMode transactionMode)
        {
            var messageReceived = new TaskCompletionSource <bool>();

            OnTestTimeout(() => messageReceived.SetResult(false));

            await StartPump(
                (context, _) =>
            {
                if (context.Headers.ContainsKey("FromOnError"))
                {
                    messageReceived.SetResult(true);
                    return(Task.FromResult(0));
                }

                throw new Exception("Simulated exception");
            },
                async (context, _) =>
            {
                await SendMessage(InputQueueName, new Dictionary <string, string> {
                    { "FromOnError", "true" }
                }, context.TransportTransaction);

                return(ErrorHandleResult.Handled);
            }, transactionMode);

            await SendMessage(InputQueueName);

            Assert.True(await messageReceived.Task, "Message not dispatched properly");
        }
Esempio n. 21
0
        public async Task Should_cancel(TransportTransactionMode transactionMode)
        {
            var started      = CreateTaskCompletionSource();
            var wasCancelled = CreateTaskCompletionSource <bool>();

            await StartPump(
                (_, __) => throw new Exception(),
                async (_, cancellationToken) =>
            {
                started.SetResult();

                try
                {
                    await Task.Delay(TestTimeout, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    wasCancelled.SetResult(true);
                    throw;
                }

                wasCancelled.SetResult(false);

                return(ErrorHandleResult.Handled);
            },
                transactionMode);

            await SendMessage(InputQueueName);

            await started.Task;

            await StopPump(new CancellationToken(true));

            Assert.True(await wasCancelled.Task, "onError was not cancelled.");
        }
        public async Task Should_invoke_on_message(TransportTransactionMode transactionMode)
        {
            var onMessageCalled = new TaskCompletionSource<MessageContext>();

            OnTestTimeout(() => onMessageCalled.SetCanceled());

            await StartPump(context =>
            {
                var body = Encoding.UTF8.GetString(context.Body);

                Assert.AreEqual("", body, "Should pass the body");

                onMessageCalled.SetResult(context);
                return Task.FromResult(0);
            },
                context => Task.FromResult(ErrorHandleResult.Handled), transactionMode);

            await SendMessage(InputQueueName, new Dictionary<string, string>
            {
                {"MyHeader", "MyValue"}
            });

            var messageContext = await onMessageCalled.Task;

            Assert.False(string.IsNullOrEmpty(messageContext.MessageId), "Should pass the native message id");
            Assert.AreEqual("MyValue", messageContext.Headers["MyHeader"], "Should pass the message headers");
        }
Esempio n. 23
0
    public TransportConfigurationResult Configure(SettingsHolder settings, TransportTransactionMode transactionMode)
    {
        var result    = new TransportConfigurationResult();
        var transport = new RabbitMQTransport();

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

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

        connectionStringBuilder = new DbConnectionStringBuilder {
            ConnectionString = connectionString
        };

        queueBindings = settings.Get <QueueBindings>();

        new TransportExtensions <RabbitMQTransport>(settings).UseConventionalRoutingTopology();
        result.TransportInfrastructure  = transport.Initialize(settings, connectionStringBuilder.ConnectionString);
        isTransportInitialized          = true;
        result.PurgeInputQueueOnStartup = true;

        transportTransactionMode = result.TransportInfrastructure.TransactionMode;
        requestedTransactionMode = transactionMode;

        //work around for TransportTests not calling Start
        result.TransportInfrastructure.Start();

        return(result);
    }
 static DispatchConsistency GetDispatchConsistency(TransportTransactionMode transportTransactionMode)
 {
     // dispatch message isolated from existing transactions when not using DTC to avoid loosing timeout data when the transaction commit fails.
     return transportTransactionMode == TransportTransactionMode.TransactionScope
         ? DispatchConsistency.Default
         : DispatchConsistency.Isolated;
 }
Esempio n. 25
0
        public async Task Should_invoke_critical_error(TransportTransactionMode transactionMode)
        {
            var recoverabilityStarted = new TaskCompletionSource <bool>();
            var criticalErrorInvoked  = false;

            OnTestTimeout(() => recoverabilityStarted.SetCanceled());

            await StartPump(
                (_, __) => throw new Exception(),
                (_, cancellationToken) =>
            {
                recoverabilityStarted.SetResult(true);

                throw new OperationCanceledException();
            },
                transactionMode,
                (_, __, ___) => criticalErrorInvoked = true);

            await SendMessage(InputQueueName);

            _ = await recoverabilityStarted.Task;

            await Task.Delay(TimeSpan.FromSeconds(1));

            await StopPump(default);
        public async Task Should_reset_delivery_counter(TransportTransactionMode transactionMode)
        {
            var onErrorInvoked = new TaskCompletionSource<ErrorContext>();

            OnTestTimeout(() => onErrorInvoked.SetCanceled());

            var numberOfOnErrorInvocations = 0;

            await StartPump(
                context =>
                {
                    throw new Exception("Simulated exception");
                },
                async context =>
                {
                    numberOfOnErrorInvocations += 1;

                    if (numberOfOnErrorInvocations == 1)
                    {
                        await SendMessage(InputQueueName, context.Message.Headers, context.TransportTransaction);
                    }
                    else
                    {
                        onErrorInvoked.SetResult(context);
                    }

                    return ErrorHandleResult.Handled;
                }, transactionMode);

            await SendMessage(InputQueueName, new Dictionary<string, string> { { "MyHeader", "MyValue" } });

            var errorContext = await onErrorInvoked.Task;

            Assert.AreEqual(1, errorContext.ImmediateProcessingFailures, "Should track delivery attempts between immediate retries");
        }
Esempio n. 27
0
        public async Task Should_emit_messages(TransportTransactionMode transactionMode)
        {
            var messageEmitted = CreateTaskCompletionSource();

            await StartPump(
                async (context, _) =>
            {
                if (context.Headers.ContainsKey("IsolatedSend"))
                {
                    messageEmitted.SetResult();
                    return;
                }

                await SendMessage(
                    InputQueueName,
                    new Dictionary <string, string> {
                    { "IsolatedSend", "" }
                },
                    context.TransportTransaction,
                    dispatchConsistency: DispatchConsistency.Isolated);

                throw new Exception("Simulated exception");
            },
                (_, __) => Task.FromResult(ErrorHandleResult.Handled),
                transactionMode);

            await SendMessage(InputQueueName);

            await messageEmitted.Task;
        }
        public async Task Should_invoke_recoverability(TransportTransactionMode transactionMode)
        {
            var messageProcessingStarted = new TaskCompletionSource <bool>();
            var recoverabilityInvoked    = false;

            OnTestTimeout(() => messageProcessingStarted.SetCanceled());

            await StartPump(
                (context, _) =>
            {
                messageProcessingStarted.SetResult(true);

                throw new OperationCanceledException();
            },
                (_, __) =>
            {
                recoverabilityInvoked = true;

                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                transactionMode);

            await SendMessage(InputQueueName);

            _ = await messageProcessingStarted.Task;

            await Task.Delay(TimeSpan.FromSeconds(1));

            await StopPump(default);
Esempio n. 29
0
    public async Task Should_move_to_error_queue(TransportTransactionMode transactionMode)
    {
        var onMessageCalled         = false;
        var onErrorCalled           = false;
        var cancellationTokenSource = new CancellationTokenSource();

        OnTestTimeout(() => cancellationTokenSource.Cancel());

        await StartPump(
            context =>
        {
            onMessageCalled = true;
            return(Task.FromResult(0));
        },
            context =>
        {
            onErrorCalled = true;
            return(Task.FromResult(ErrorHandleResult.Handled));
        }, transactionMode);

        await SendPoisonMessage(InputQueueName);

        await CheckErrorQueue(ErrorQueueName, cancellationTokenSource.Token);

        Assert.False(onErrorCalled, "Poison message should not invoke onError");
        Assert.False(onMessageCalled, "Poison message should not invoke onMessage");
    }
Esempio n. 30
0
        public async Task Should_invoke_on_message(TransportTransactionMode transactionMode)
        {
            MessageContext messageContext = null;

            var completed = new TaskCompletionSource <CompleteContext>();

            OnTestTimeout(() => completed.SetCanceled());

            await StartPump(
                (context, _) =>
            {
                messageContext = context;
                return(Task.CompletedTask);
            },
                (context, _) => Task.FromResult(ErrorHandleResult.Handled),
                (context, _) => completed.SetCompleted(context),
                transactionMode);

            await SendMessage(InputQueueName, new Dictionary <string, string> {
                { "MyHeader", "MyValue" }
            }, body : new byte[] { 1, 2, 3 });

            var completeContext = await completed.Task;

            Assert.False(completeContext.OnMessageFailed, "Message failure should not be indicated");
            Assert.NotNull(messageContext, "On message should have been called");
            Assert.False(string.IsNullOrEmpty(messageContext.NativeMessageId), "Should pass the native message id");
            Assert.AreEqual("MyValue", messageContext.Headers["MyHeader"], "Should pass the message headers");
            Assert.AreEqual(new byte[] { 1, 2, 3 }, messageContext.Body, "Should pass the body");
        }
Esempio n. 31
0
        public async Task Should_not_invoke_recoverability(TransportTransactionMode transactionMode)
        {
            var messageProcessingStarted = new TaskCompletionSource <bool>();
            var recoverabilityInvoked    = false;

            OnTestTimeout(() => messageProcessingStarted.SetCanceled());

            await StartPump(
                async (_, cancellationToken) =>
            {
                messageProcessingStarted.SetResult(true);

                await Task.Delay(TestTimeout, cancellationToken);
            },
                (_, __) =>
            {
                recoverabilityInvoked = true;

                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                transactionMode);

            await SendMessage(InputQueueName);

            _ = await messageProcessingStarted.Task;

            await StopPump(new CancellationToken(true));

            Assert.False(recoverabilityInvoked);
        }
Esempio n. 32
0
        public async Task Should_call_on_error_and_indicate_failure(TransportTransactionMode transactionMode)
        {
            ErrorContext errorContext = null;

            var completed = new TaskCompletionSource <CompleteContext>();

            OnTestTimeout(() => completed.SetCanceled());

            await StartPump(
                (context, _) => throw new Exception("Simulated exception"),
                (context, _) =>
            {
                errorContext = context;
                return(Task.FromResult(ErrorHandleResult.Handled));
            },
                (context, _) => completed.SetCompleted(context),
                transactionMode);

            await SendMessage(InputQueueName, new Dictionary <string, string> {
                { "MyHeader", "MyValue" }
            });

            var completeContext = await completed.Task;

            Assert.NotNull(errorContext, "On error should have been called");
            Assert.AreEqual(errorContext.Exception.Message, "Simulated exception", "Should preserve the exception");
            Assert.AreEqual(1, errorContext.ImmediateProcessingFailures, "Should track the number of delivery attempts");
            Assert.AreEqual("MyValue", errorContext.Message.Headers["MyHeader"], "Should pass the message headers");

            Assert.True(completeContext.OnMessageFailed, "Message failure should be indicated");
            Assert.True(completeContext.WasAcknowledged, "Message should be acknowleged");
        }
 void IgnoreUnsupportedTransactionModes(TransportTransactionMode requestedTransactionMode)
 {
     if (TransportInfrastructure.TransactionMode < requestedTransactionMode)
     {
         Assert.Ignore($"Only relevant for transports supporting {requestedTransactionMode} or higher");
     }
 }
Esempio n. 34
0
 static DispatchConsistency GetDispatchConsistency(TransportTransactionMode transportTransactionMode)
 {
     // dispatch message isolated from existing transactions when not using DTC to avoid loosing timeout data when the transaction commit fails.
     return(transportTransactionMode == TransportTransactionMode.TransactionScope
         ? DispatchConsistency.Default
         : DispatchConsistency.Isolated);
 }
Esempio n. 35
0
        public async Task Should_invoke_critical_error(TransportTransactionMode transactionMode)
        {
            var criticalErrorInvoked = false;

            var completed = new TaskCompletionSource <CompleteContext>();

            OnTestTimeout(() => completed.SetCanceled());

            await StartPump(
                (_, __) => throw new Exception(),
                (_, __) => throw new OperationCanceledException(),
                (context, _) => completed.SetCompleted(context),
                transactionMode,
                (_, __, ___) => criticalErrorInvoked = true);

            await SendMessage(InputQueueName);

            var completeContext = await completed.Task;

            await StopPump();

            Assert.True(criticalErrorInvoked);
            Assert.False(completeContext.WasAcknowledged);
            Assert.True(completeContext.OnMessageFailed);
        }
        public async Task Should_emit_messages(TransportTransactionMode transactionMode)
        {
            var onMessageCalled = new TaskCompletionSource <bool>();

            OnTestTimeout(() => onMessageCalled.SetCanceled());

            await StartPump(async context =>
            {
                if (context.Headers.ContainsKey("IsolatedSend"))
                {
                    onMessageCalled.SetResult(true);
                    return;
                }

                await SendMessage(InputQueueName, new Dictionary <string, string>
                {
                    { "IsolatedSend", "true" }
                }, context.TransportTransaction, null, DispatchConsistency.Isolated);

                throw new Exception("Simulated exception");
            },
                            errorContext => Task.FromResult(ErrorHandleResult.Handled),
                            transactionMode);

            await SendMessage(InputQueueName);

            Assert.True(await onMessageCalled.Task, "Should emit isolated sends");
        }
    public async Task SmokeTest(TransportTransactionMode transactionMode)
    {
        var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(nameof(SqlTransportIntegrationTests));
        var typesToScan           = TypeScanner.NestedTypes <SqlTransportIntegrationTests>();

        endpointConfiguration.SetTypesToScan(typesToScan);
        var transport = endpointConfiguration.UseTransport <SqlServerTransport>();

        transport.Transactions(transactionMode);
        transport.UseCustomSqlConnectionFactory(async() =>
        {
            var connection = MsSqlConnectionBuilder.Build();
            await connection.OpenAsync().ConfigureAwait(false);
            return(connection);
        });
        var persistence = endpointConfiguration.UsePersistence <SqlPersistence>();

        persistence.SqlDialect <SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(MsSqlConnectionBuilder.Build);
        persistence.DisableInstaller();
        persistence.SubscriptionSettings().DisableCache();

        var endpoint = await Endpoint.Start(endpointConfiguration).ConfigureAwait(false);

        var startSagaMessage = new StartSagaMessage
        {
            StartId = Guid.NewGuid()
        };
        await endpoint.SendLocal(startSagaMessage).ConfigureAwait(false);

        ManualResetEvent.WaitOne();
        await endpoint.Stop().ConfigureAwait(false);
    }
 public SatelliteDefinition(string name, string receiveAddress, TransportTransactionMode requiredTransportTransactionMode, PushRuntimeSettings runtimeSettings, Func<RecoverabilityConfig, ErrorContext, RecoverabilityAction> recoverabilityPolicy, Func<IBuilder, MessageContext, Task> onMessage)
 {
     Name = name;
     ReceiveAddress = receiveAddress;
     RequiredTransportTransactionMode = requiredTransportTransactionMode;
     RuntimeSettings = runtimeSettings;
     RecoverabilityPolicy = recoverabilityPolicy;
     OnMessage = onMessage;
 }
 public TransportConfigurationResult Configure(SettingsHolder settings, TransportTransactionMode transactionMode)
 {
     var msmqTransportDefinition = new MsmqTransport();
     settingsHolder = settings;
     return new TransportConfigurationResult
     {
         TransportInfrastructure = msmqTransportDefinition.Initialize(settingsHolder, ""),
         PurgeInputQueueOnStartup = true
     };
 }
Esempio n. 40
0
        /// <summary>
        /// Creates an instance of <see cref="PushSettings" />.
        /// </summary>
        /// <param name="inputQueue">Input queue name.</param>
        /// <param name="errorQueue">Error queue name.</param>
        /// <param name="purgeOnStartup"><code>true</code> to purge <paramref name="inputQueue" /> at startup.</param>
        /// <param name="requiredTransactionMode">The transaction mode required for receive operations.</param>
        public PushSettings(string inputQueue, string errorQueue, bool purgeOnStartup, TransportTransactionMode requiredTransactionMode)
        {
            Guard.AgainstNullAndEmpty(nameof(inputQueue), inputQueue);
            Guard.AgainstNullAndEmpty(nameof(errorQueue), errorQueue);
            Guard.AgainstNull(nameof(requiredTransactionMode), requiredTransactionMode);

            PurgeOnStartup = purgeOnStartup;
            RequiredTransactionMode = requiredTransactionMode;
            InputQueue = inputQueue;
            ErrorQueue = errorQueue;
        }
 ReceiveStrategy SelectReceiveStrategy(TransportTransactionMode minimumConsistencyGuarantee, TransactionOptions transactionOptions)
 {
     switch (minimumConsistencyGuarantee)
     {
         case TransportTransactionMode.TransactionScope:
             return new TransactionScopeStrategy(transactionOptions, new MsmqFailureInfoStorage(1000));
         case TransportTransactionMode.SendsAtomicWithReceive:
             return new SendsAtomicWithReceiveNativeTransactionStrategy(new MsmqFailureInfoStorage(1000));
         case TransportTransactionMode.ReceiveOnly:
             return new ReceiveOnlyNativeTransactionStrategy(new MsmqFailureInfoStorage(1000));
         case TransportTransactionMode.None:
             return new NoTransactionStrategy();
         default:
             throw new NotSupportedException($"TransportTransactionMode {minimumConsistencyGuarantee} is not supported by the MSMQ transport");
     }
 }
Esempio n. 42
0
        static string SetupDispatcherSatellite(FeatureConfigurationContext context, TransportTransactionMode requiredTransactionSupport, PushRuntimeSettings pushRuntimeSettings)
        {
            var satelliteLogicalAddress = context.Settings.LogicalAddress().CreateQualifiedAddress("TimeoutsDispatcher");
            var satelliteAddress = context.Settings.GetTransportAddress(satelliteLogicalAddress);

            context.AddSatelliteReceiver("Timeout Dispatcher Processor", satelliteAddress, requiredTransactionSupport, pushRuntimeSettings, RecoverabilityPolicy,
                (builder, pushContext) =>
                {
                    var dispatchBehavior = new DispatchTimeoutBehavior(
                        builder.Build<IDispatchMessages>(),
                        builder.Build<IPersistTimeouts>(),
                        requiredTransactionSupport);

                    return dispatchBehavior.Invoke(pushContext);
                });

            return satelliteAddress;
        }
Esempio n. 43
0
        static void SetupStorageSatellite(FeatureConfigurationContext context, TransportTransactionMode requiredTransactionSupport, PushRuntimeSettings pushRuntimeSettings)
        {
            var satelliteLogicalAddress = context.Settings.LogicalAddress().CreateQualifiedAddress("Timeouts");
            var satelliteAddress = context.Settings.GetTransportAddress(satelliteLogicalAddress);

            context.AddSatelliteReceiver("Timeout Message Processor", satelliteAddress, requiredTransactionSupport, pushRuntimeSettings, RecoverabilityPolicy,
                (builder, pushContext) =>
                {
                    var storeBehavior = new StoreTimeoutBehavior(
                        builder.Build<ExpiredTimeoutsPoller>(),
                        builder.Build<IDispatchMessages>(),
                        builder.Build<IPersistTimeouts>(),
                        context.Settings.EndpointName().ToString());

                    return storeBehavior.Invoke(pushContext);
                });

            context.Settings.Get<TimeoutManagerAddressConfiguration>().Set(satelliteAddress);
        }
        public async Task Should_invoke_on_message(TransportTransactionMode transactionMode)
        {
            RequireDeliveryConstraint<NonDurableDelivery>();

            var onMessageCalled = new TaskCompletionSource<MessageContext>();

            OnTestTimeout(() => onMessageCalled.SetCanceled());

            await StartPump(context =>
            {
                onMessageCalled.SetResult(context);
                return Task.FromResult(0);
            },
                context => Task.FromResult(ErrorHandleResult.Handled), transactionMode);

            await SendMessage(InputQueueName, deliveryConstraints: new List<DeliveryConstraint> { new NonDurableDelivery() });

            var messageContext = await onMessageCalled.Task;

            Assert.NotNull(messageContext);
        }
        public async Task Should_move_it_to_the_error_queue(TransportTransactionMode transactionMode)
        {
            DeleteQueue();
            try
            {
                await Scenario.Define<Context>()
                    .WithEndpoint<Endpoint>(b =>
                    {
                        b.CustomConfig(c =>
                        {
                            c.UseTransport<MsmqTransport>()
                                .Transactions(transactionMode);
                        });
                        b.When((session, c) =>
                        {
                            var endpoint = AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(Endpoint));

                            var inputQueue = $@".\private$\{endpoint}";

                            using (var queue = new MessageQueue(inputQueue))
                            using (var message = new Message())
                            {
                                message.Extension = Encoding.UTF8.GetBytes("<badheaders");
                                queue.Send(message, MessageQueueTransactionType.Single);
                            }

                            return Task.FromResult(0);
                        });
                    })
                    .Done(c => c.Logs.Any(l => l.Level == LogLevel.Error))
                    .Run();
                Assert.True(MessageExistsInErrorQueue(), "The message should have been moved to the error queue");
            }
            finally
            {
                DeleteQueue();
            }
        }
        public async Task Should_reinvoke_on_error_with_original_exception(TransportTransactionMode transactionMode)
        {
            var onErrorCalled = new TaskCompletionSource<ErrorContext>();
            Exception criticalError = null;

            OnTestTimeout(() => onErrorCalled.SetCanceled());

            var firstInvocation = true;

            await StartPump(
                context =>
                {
                    throw new Exception("Simulated exception");
                },
                context =>
                {
                    if (firstInvocation)
                    {
                        firstInvocation = false;

                        throw new Exception("Exception from onError");
                    }

                    onErrorCalled.SetResult(context);

                    return Task.FromResult(ErrorHandleResult.Handled);
                },
                transactionMode,
                (s, exception) => criticalError = exception);

            await SendMessage(InputQueueName);

            var errorContext = await onErrorCalled.Task;

            Assert.AreEqual("Simulated exception", errorContext.Exception.Message);
            Assert.AreEqual(2, errorContext.ImmediateProcessingFailures);
            Assert.IsNotNull(criticalError);
        }
        public async Task Should_not_emit_messages(TransportTransactionMode transactionMode)
        {
            var onMessageCalled = new TaskCompletionSource<bool>();

            OnTestTimeout(() => onMessageCalled.SetCanceled());

            await StartPump(async context =>
            {
                if (context.Headers.ContainsKey("CompleteTest"))
                {
                    onMessageCalled.SetResult(true);
                    return;
                }

                if (context.Headers.ContainsKey("EnlistedSend"))
                {
                    onMessageCalled.SetResult(false);
                    return;
                }

                await SendMessage(InputQueueName, new Dictionary<string, string> { { "EnlistedSend", "true" } }, context.TransportTransaction);

                throw new Exception("Simulated exception");

            },
                async context =>
                {
                    await SendMessage(InputQueueName, new Dictionary<string, string> { { "CompleteTest", "true" } }, context.TransportTransaction);

                    return ErrorHandleResult.Handled;
                }, transactionMode);

            await SendMessage(InputQueueName, new Dictionary<string, string> { { "MyHeader", "MyValue" } });

            Assert.True(await onMessageCalled.Task, "Should not emit enlisted sends");
        }
 public DispatchTimeoutBehavior(IDispatchMessages dispatcher, IPersistTimeouts persister, TransportTransactionMode transportTransactionMode)
 {
     this.dispatcher = dispatcher;
     this.persister = persister;
     dispatchConsistency = GetDispatchConsistency(transportTransactionMode);
 }
Esempio n. 49
0
        List<TransportReceiver> BuildMainReceivers(string errorQueue, bool purgeOnStartup, TransportTransactionMode requiredTransactionSupport, RecoverabilityExecutorFactory recoverabilityExecutorFactory, IPipeline<ITransportReceiveContext> mainPipeline)
        {
            var localAddress = settings.LocalAddress();
            var distributorAddress = settings.GetOrDefault<string>("LegacyDistributor.Address");

            var recoverabilityExecutor = recoverabilityExecutorFactory.CreateDefault(eventAggregator, distributorAddress ?? localAddress);
            var pushSettings = new PushSettings(settings.LocalAddress(), errorQueue, purgeOnStartup, requiredTransactionSupport);
            var mainPipelineExecutor = new MainPipelineExecutor(builder, eventAggregator, pipelineCache, mainPipeline);
            var dequeueLimitations = GetDequeueLimitationsForReceivePipeline();

            var receivers = new List<TransportReceiver>();

            receivers.Add(new TransportReceiver(MainReceiverId, builder.Build<IPushMessages>(), pushSettings, dequeueLimitations, mainPipelineExecutor, recoverabilityExecutor, criticalError));

            if (settings.InstanceSpecificQueue() != null)
            {
                var instanceSpecificQueue = settings.InstanceSpecificQueue();
                var instanceSpecificRecoverabilityExecutor = recoverabilityExecutorFactory.CreateDefault(eventAggregator, instanceSpecificQueue);
                var sharedReceiverPushSettings = new PushSettings(settings.InstanceSpecificQueue(), errorQueue, purgeOnStartup, requiredTransactionSupport);

                receivers.Add(new TransportReceiver(MainReceiverId, builder.Build<IPushMessages>(), sharedReceiverPushSettings, dequeueLimitations, mainPipelineExecutor, instanceSpecificRecoverabilityExecutor, criticalError));
            }

            return receivers;
        }
 public FakeRavenDBTransportInfrastructure(TransportTransactionMode transactionMode)
 {
     this.transactionMode = transactionMode;
 }
        public async Task Invoke_when_not_using_dtc_transport_should_not_enlist_dispatch_in_transaction(TransportTransactionMode nonDtcTxSettings)
        {
            var messageDispatcher = new FakeMessageDispatcher();
            var timeoutPersister = new InMemoryTimeoutPersister(() => DateTime.UtcNow);
            var behavior = new DispatchTimeoutBehavior(messageDispatcher, timeoutPersister, nonDtcTxSettings);
            var timeoutData = CreateTimeout();
            await timeoutPersister.Add(timeoutData, null);

            await behavior.Invoke(CreateContext(timeoutData.Id));

            var transportOperation = messageDispatcher.OutgoingTransportOperations.UnicastTransportOperations.Single();
            Assert.AreEqual(DispatchConsistency.Isolated, transportOperation.RequiredDispatchConsistency);
        }