Exemplo n.º 1
0
 /// <summary>
 /// Creates a new transport operation.
 /// </summary>
 /// <param name="message">The message to dispatch.</param>
 /// <param name="addressTag">The address to use when routing this message.</param>
 /// <param name="requiredDispatchConsistency">The required consistency level for the dispatch operation.</param>
 /// <param name="properties">Delivery properties of the message.</param>
 public TransportOperation(OutgoingMessage message, AddressTag addressTag, DispatchProperties properties = null, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default)
 {
     Message    = message;
     AddressTag = addressTag;
     Properties = properties ?? new DispatchProperties();
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
Exemplo n.º 2
0
 /// <summary>
 /// Creates a new transport operation.
 /// </summary>
 /// <param name="message">The message to dispatch.</param>
 /// <param name="addressTag">The address to use when routing this message.</param>
 /// <param name="requiredDispatchConsistency">The required consistency level for the dispatch operation.</param>
 /// <param name="deliveryConstraints">The delivery constraints that must be honored by the transport.</param>
 public TransportOperation(OutgoingMessage message, AddressTag addressTag, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List<DeliveryConstraint> deliveryConstraints = null)
 {
     Message = message;
     AddressTag = addressTag;
     RequiredDispatchConsistency = requiredDispatchConsistency;
     DeliveryConstraints = deliveryConstraints ?? DeliveryConstraint.EmptyConstraints;
 }
Exemplo n.º 3
0
 /// <summary>
 /// Creates a new transport operation.
 /// </summary>
 /// <param name="message">The message to dispatch.</param>
 /// <param name="addressTag">The address to use when routing this message.</param>
 /// <param name="requiredDispatchConsistency">The required consistency level for the dispatch operation.</param>
 /// <param name="deliveryConstraints">The delivery constraints that must be honored by the transport.</param>
 public TransportOperation(OutgoingMessage message, AddressTag addressTag, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List <DeliveryConstraint> deliveryConstraints = null)
 {
     Message    = message;
     AddressTag = addressTag;
     RequiredDispatchConsistency = requiredDispatchConsistency;
     DeliveryConstraints         = deliveryConstraints ?? new List <DeliveryConstraint>(0);
 }
 /// <summary>
 /// Creates a new <see cref="MulticastTransportOperation" /> instance.
 /// </summary>
 // ReSharper disable once ParameterTypeCanBeEnumerable.Local
 public MulticastTransportOperation(OutgoingMessage message, Type messageType, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List<DeliveryConstraint> deliveryConstraints = null)
 {
     Message = message;
     MessageType = messageType;
     DeliveryConstraints = deliveryConstraints ?? DeliveryConstraint.EmptyConstraints;
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
 /// <summary>
 /// Creates a new <see cref="MulticastTransportOperation" /> instance.
 /// </summary>
 public MulticastTransportOperation(OutgoingMessage message, Type messageType, DispatchProperties properties, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default)
 {
     Message     = message;
     MessageType = messageType;
     Properties  = properties;
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
Exemplo n.º 6
0
 /// <summary>
 /// Creates a new <see cref="MulticastTransportOperation" /> instance.
 /// </summary>
 // ReSharper disable once ParameterTypeCanBeEnumerable.Local
 public MulticastTransportOperation(OutgoingMessage message, Type messageType, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List <DeliveryConstraint> deliveryConstraints = null)
 {
     Message                     = message;
     MessageType                 = messageType;
     DeliveryConstraints         = deliveryConstraints ?? DeliveryConstraint.EmptyConstraints;
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
        protected Task SendMessage(
            string address,
            Dictionary <string, string> headers       = null,
            TransportTransaction transportTransaction = null,
            DispatchProperties dispatchProperties     = null,
            DispatchConsistency dispatchConsistency   = DispatchConsistency.Default,
            byte[] body = null)
        {
            var messageId = Guid.NewGuid().ToString();
            var message   = new OutgoingMessage(messageId, headers ?? new Dictionary <string, string>(), body ?? Array.Empty <byte>());

            if (message.Headers.ContainsKey(TestIdHeaderName) == false)
            {
                message.Headers.Add(TestIdHeaderName, testId);
            }

            if (transportTransaction == null)
            {
                transportTransaction = new TransportTransaction();
            }

            var transportOperation = new TransportOperation(message, new UnicastAddressTag(address), dispatchProperties, dispatchConsistency);

            return(transportInfrastructure.Dispatcher.Dispatch(new TransportOperations(transportOperation), transportTransaction));
        }
Exemplo n.º 8
0
 /// <summary>
 /// Creates a new <see cref="UnicastTransportOperation" /> instance.
 /// </summary>
 public UnicastTransportOperation(OutgoingMessage message, string destination, DispatchProperties properties, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default)
 {
     Message     = message;
     Destination = destination;
     Properties  = properties;
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
 /// <summary>
 /// Creates a new <see cref="UnicastTransportOperation" /> instance.
 /// </summary>
 public UnicastTransportOperation(OutgoingMessage message, string destination, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List<DeliveryConstraint> deliveryConstraints = null)
 {
     Message = message;
     Destination = destination;
     DeliveryConstraints = deliveryConstraints ?? DeliveryConstraint.EmptyConstraints;
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
Exemplo n.º 10
0
        bool IsCombiningTimeToBeReceivedWithTransactions(TransportTransaction transaction,
                                                         DispatchConsistency requiredDispatchConsistency, DispatchProperties dispatchProperties)
        {
            if (!transportSettings.UseTransactionalQueues)
            {
                return(false);
            }

            if (requiredDispatchConsistency == DispatchConsistency.Isolated)
            {
                return(false);
            }

            var timeToBeReceivedRequested =
                dispatchProperties.DiscardIfNotReceivedBefore?.MaxTime < MessageQueue.InfiniteTimeout;

            if (!timeToBeReceivedRequested)
            {
                return(false);
            }

            if (Transaction.Current != null)
            {
                return(true);
            }


            return(TryGetNativeTransaction(transaction, out _));
        }
        protected Task SendMessage(string address,
                                   Dictionary <string, string> headers           = null,
                                   TransportTransaction transportTransaction     = null,
                                   List <DeliveryConstraint> deliveryConstraints = null,
                                   DispatchConsistency dispatchConsistency       = DispatchConsistency.Default)
        {
            var messageId = Guid.NewGuid().ToString();
            var message   = new OutgoingMessage(messageId, headers ?? new Dictionary <string, string>(), new byte[0]);

            if (message.Headers.ContainsKey(TestIdHeaderName) == false)
            {
                message.Headers.Add(TestIdHeaderName, testId);
            }

            var dispatcher = lazyDispatcher.Value;

            if (transportTransaction == null)
            {
                transportTransaction = new TransportTransaction();
            }

            var transportOperation = new TransportOperation(message, new UnicastAddressTag(address), dispatchConsistency, deliveryConstraints ?? new List <DeliveryConstraint>());

            return(dispatcher.Dispatch(new TransportOperations(transportOperation), transportTransaction, new ContextBag()));
        }
Exemplo n.º 12
0
 /// <summary>
 /// Creates a new <see cref="UnicastTransportOperation" /> instance.
 /// </summary>
 public UnicastTransportOperation(OutgoingMessage message, string destination, DispatchConsistency requiredDispatchConsistency = DispatchConsistency.Default, List <DeliveryConstraint> deliveryConstraints = null)
 {
     Message                     = message;
     Destination                 = destination;
     DeliveryConstraints         = deliveryConstraints ?? new List <DeliveryConstraint>(0);
     RequiredDispatchConsistency = requiredDispatchConsistency;
 }
Exemplo n.º 13
0
        public async Task Should_recover(Type contextProviderType, DispatchConsistency dispatchConsistency)
        {
            // Setup

            var token = CancellationToken.None;

            var connectionString = Environment.GetEnvironmentVariable("SqlServerTransportConnectionString") ?? @"Data Source=.\SQLEXPRESS;Initial Catalog=nservicebus;Integrated Security=True";

            sqlConnectionFactory = SqlConnectionFactory.Default(connectionString);

            var addressParser = new QueueAddressTranslator("nservicebus", "dbo", null, null);
            var purger        = new QueuePurger(sqlConnectionFactory);

            await RemoveQueueIfPresent(QueueName, token);
            await RemoveQueueIfPresent($"{QueueName}.Delayed", token);
            await CreateOutputQueueIfNecessary(addressParser, sqlConnectionFactory);

            var tableCache = new TableBasedQueueCache(addressParser, true);
            var queue      = tableCache.Get(QueueName);

            dispatcher = new MessageDispatcher(addressParser, new NoOpMulticastToUnicastConverter(), tableCache, null, sqlConnectionFactory);

            // Run normally
            int messagesSent = await RunTest(contextProviderType, dispatchConsistency, queue, purger, token);

            Assert.AreEqual(1, messagesSent);

            // Remove Recoverable column
            await DropRecoverableColumn(token);

            var exception = Assert.ThrowsAsync <Exception>(() => RunTest(contextProviderType, dispatchConsistency, queue, purger, token));

            Assert.True(exception.Message.Contains("change in the existence of the Recoverable column"));

            // Try again, should work
            int messagesSentAttempt2 = await RunTest(contextProviderType, dispatchConsistency, queue, purger, token);

            Assert.AreEqual(1, messagesSentAttempt2);

            // Put the Recoverable column back
            await AddRecoverableColumn(token);

            var exception2 = Assert.ThrowsAsync <Exception>(() => RunTest(contextProviderType, dispatchConsistency, queue, purger, token));

            Assert.True(exception2.Message.Contains("change in the existence of the Recoverable column"));

            // Try again, should work
            int messagesSentAttempt3 = await RunTest(contextProviderType, dispatchConsistency, queue, purger, token);

            Assert.AreEqual(1, messagesSentAttempt3);
        }
Exemplo n.º 14
0
        async Task <int> RunTest(Type contextProviderType, DispatchConsistency dispatchConsistency, TableBasedQueue queue, QueuePurger purger, CancellationToken cancellationToken)
        {
            using (var contextProvider = CreateContext(contextProviderType, sqlConnectionFactory))
            {
                // Run with Recoverable column in place

                var operations = new TransportOperations(CreateTransportOperation(id: "1", destination: QueueName, consistency: dispatchConsistency));
                await dispatcher.Dispatch(operations, contextProvider.TransportTransaction, cancellationToken);

                contextProvider.Complete();

                return(await purger.Purge(queue, cancellationToken));
            }
        }
        RoutingOptions GetRoutingOptions(ReceiveContext receiveContext, DispatchConsistency consistency)
        {
            var sendVia = false;
            var context = receiveContext as BrokeredMessageReceiveContext;

            if (context?.Recovering == false) // avoid send via when recovering to prevent error message from rolling back
            {
                sendVia  = settings.Get <bool>(WellKnownConfigurationKeys.Connectivity.SendViaReceiveQueue);
                sendVia &= settings.Get <TransportType>(WellKnownConfigurationKeys.Connectivity.TransportType) == TransportType.NetMessaging;
                sendVia &= consistency != DispatchConsistency.Isolated;
            }
            return(new RoutingOptions
            {
                SendVia = sendVia,
                ViaEntityPath = GetViaEntityPathFor(context?.Entity),
                ViaConnectionString = context?.Entity.Namespace.ConnectionString,
                ViaPartitionKey = context?.IncomingBrokeredMessage.PartitionKey
            });
        }
        internal Task RouteBatch(Batch batch, BrokeredMessageReceiveContext context, DispatchConsistency consistency)
        {
            var outgoingBatches = batch.Operations;

            var passiveNamespaces = batch.Destinations.Namespaces.Where(n => n.Mode == NamespaceMode.Passive).ToList();
            var pendingSends      = new List <Task>();

            foreach (var entity in batch.Destinations.Entities.Where(entity => entity.Namespace.Mode == NamespaceMode.Active))
            {
                var routingOptions = GetRoutingOptions(context, consistency);

                if (!string.IsNullOrEmpty(routingOptions.ViaEntityPath))
                {
                    Logger.DebugFormat("Routing {0} messages to {1} via {2}", outgoingBatches.Count, entity.Path, routingOptions.ViaEntityPath);
                }
                else
                {
                    Logger.DebugFormat("Routing {0} messages to {1}", outgoingBatches.Count, entity.Path);
                }

                // don't use via on fallback, not supported across namespaces
                var fallbacks = passiveNamespaces.Select(n => senders.Get(entity.Path, null, n.Alias)).ToList();

                var ns = entity.Namespace;
                // only use via if the destination and via namespace are the same
                var via = routingOptions.SendVia && ns.ConnectionString == routingOptions.ViaConnectionString ? routingOptions.ViaEntityPath : null;
                var suppressTransaction = via == null;
                var messageSender       = senders.Get(entity.Path, via, ns.Alias);

                routingOptions.DestinationEntityPath = entity.Path;
                routingOptions.DestinationNamespace  = ns;

                var brokeredMessages = outgoingMessageConverter.Convert(outgoingBatches, routingOptions).ToList();

                pendingSends.Add(RouteOutBatchesWithFallbackAndLogExceptionsAsync(messageSender, fallbacks, brokeredMessages, suppressTransaction));
            }
            return(Task.WhenAll(pendingSends));
        }
        RoutingOptionsInternal GetRoutingOptions(ReceiveContextInternal receiveContext, DispatchConsistency consistency)
        {
            var sendVia = false;
            var context = receiveContext as BrokeredMessageReceiveContextInternal;

            if (context?.Recovering == false) // avoid send via when recovering to prevent error message from rolling back
            {
                sendVia  = sendViaFromConfiguration & transportTypeIsNetMessaging;
                sendVia &= consistency != DispatchConsistency.Isolated;
            }
            return(new RoutingOptionsInternal
            {
                SendVia = sendVia,
                ViaEntityPath = GetViaEntityPathFor(context?.Entity),
                ViaConnectionString = context?.Entity.Namespace.ConnectionString,
                ViaPartitionKey = context?.IncomingBrokeredMessage.PartitionKey
            });
        }
        public Task RouteBatches(IEnumerable <BatchInternal> outgoingBatches, ReceiveContextInternal context, DispatchConsistency consistency)
        {
            var pendingBatches = new List <Task>();

            foreach (var batch in outgoingBatches)
            {
                pendingBatches.Add(RouteBatch(batch, context as BrokeredMessageReceiveContextInternal, consistency));
            }
            return(Task.WhenAll(pendingBatches));
        }
 static TransportOperation CreateTransportOperation(string id, string destination, DispatchConsistency consistency)
 {
     return(new TransportOperation(
                new OutgoingMessage(id, new Dictionary <string, string>(), new byte[0]),
                new UnicastAddressTag(destination),
                requiredDispatchConsistency: consistency
                ));
 }
        public async Task Outgoing_operations_are_stored_atomically(Type contextProviderType, DispatchConsistency dispatchConsistency)
        {
            using (var contextProvider = CreateContext(contextProviderType, sqlConnectionFactory))
            {
                var invalidOperations = new TransportOperations(
                    CreateTransportOperation(id: "3", destination: ValidAddress, consistency: dispatchConsistency),
                    CreateTransportOperation(id: "4", destination: InvalidAddress, consistency: dispatchConsistency)
                    );

                Assert.ThrowsAsync(Is.AssignableTo <Exception>(), async() =>
                {
                    await dispatcher.Dispatch(invalidOperations, contextProvider.TransportTransaction);
                    contextProvider.Complete();
                });
            }

            var messagesSent = await purger.Purge(queue);

            Assert.AreEqual(0, messagesSent);
        }
        public async Task Outgoing_operations_are_stored_in_destination_queue(Type contextProviderType, DispatchConsistency dispatchConsistency)
        {
            using (var contextProvider = CreateContext(contextProviderType, sqlConnectionFactory))
            {
                var operations = new TransportOperations(
                    CreateTransportOperation(id: "1", destination: ValidAddress, consistency: dispatchConsistency),
                    CreateTransportOperation(id: "2", destination: ValidAddress, consistency: dispatchConsistency)
                    );

                await dispatcher.Dispatch(operations, contextProvider.TransportTransaction);

                contextProvider.Complete();

                var messagesSent = await purger.Purge(queue);

                Assert.AreEqual(2, messagesSent);
            }
        }
 static TransportOperation CreateTransportOperations(string messageId, string destination, DispatchConsistency dispatchConsistency = DispatchConsistency.Default)
 {
     return(new TransportOperation(new OutgoingMessage(messageId, new Dictionary <string, string>(), new byte[0]), new UnicastAddressTag(destination), dispatchConsistency));
 }
Exemplo n.º 23
0
        bool IsCombiningTimeToBeReceivedWithTransactions(TransportTransaction transaction, DispatchConsistency requiredDispatchConsistency, List <DeliveryConstraint> deliveryConstraints)
        {
            if (!settings.UseTransactionalQueues)
            {
                return(false);
            }

            if (requiredDispatchConsistency == DispatchConsistency.Isolated)
            {
                return(false);
            }

            DiscardIfNotReceivedBefore discardIfNotReceivedBefore;
            var timeToBeReceivedRequested = deliveryConstraints.TryGet(out discardIfNotReceivedBefore) && discardIfNotReceivedBefore.MaxTime < MessageQueue.InfiniteTimeout;

            if (!timeToBeReceivedRequested)
            {
                return(false);
            }

            if (Transaction.Current != null)
            {
                return(true);
            }

            MessageQueueTransaction activeReceiveTransaction;

            return(TryGetNativeTransaction(transaction, out activeReceiveTransaction));
        }
 TransactionScope CreateTransactionScope(DispatchConsistency dispatchConsistency, bool shouldSuppressTransaction)
 {
     return(dispatchConsistency == DispatchConsistency.Isolated || shouldSuppressTransaction
         ? new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)
         : null);
 }
Exemplo n.º 25
0
        async Task DispatchWithTransactionScopeIfRequired(IList <Batch> toBeDispatchedOnComplete, BrokeredMessageReceiveContext context, DispatchConsistency consistency)
        {
            if (context.CancellationToken.IsCancellationRequested || !toBeDispatchedOnComplete.Any())
            {
                return;
            }

            await routeOutgoingBatches.RouteBatches(toBeDispatchedOnComplete, context, consistency).ConfigureAwait(false);
        }
Exemplo n.º 26
0
        Task DeduplicateAndDispatch(TransportOperations operations, Func <List <UnicastTransportOperation>, Task> dispatchMethod, DispatchConsistency dispatchConsistency)
        {
            var operationsToDispatch = operations.UnicastTransportOperations
                                       .Where(o => o.RequiredDispatchConsistency == dispatchConsistency)
                                       .GroupBy(o => new DeduplicationKey(o.Message.MessageId, addressTranslator.Parse(o.Destination).Address))
                                       .Select(g => g.First())
                                       .ToList();

            return(dispatchMethod(operationsToDispatch));
        }
Exemplo n.º 27
0
        bool IsCombiningTimeToBeReceivedWithTransactions(TransportTransaction transaction, DispatchConsistency requiredDispatchConsistency, List<DeliveryConstraint> deliveryConstraints)
        {
            if (!settings.UseTransactionalQueues)
            {
                return false;
            }

            if (requiredDispatchConsistency == DispatchConsistency.Isolated)
            {
                return false;
            }

            DiscardIfNotReceivedBefore discardIfNotReceivedBefore;
            var timeToBeReceivedRequested = deliveryConstraints.TryGet(out discardIfNotReceivedBefore) && discardIfNotReceivedBefore.MaxTime < MessageQueue.InfiniteTimeout;

            if (!timeToBeReceivedRequested)
            {
                return false;
            }

            if (Transaction.Current != null)
            {
                return true;
            }

            MessageQueueTransaction activeReceiveTransaction;

            return TryGetNativeTransaction(transaction, out activeReceiveTransaction);
        }