internal async Task RouteBatch(BatchInternal batch, BrokeredMessageReceiveContextInternal 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 (routingOptions.SendVia && !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 = new List <IMessageSenderInternal>(passiveNamespaces.Count);
                foreach (var passiveNamespace in passiveNamespaces)
                {
                    fallbacks.Add(await sendersLifeCycleManager.Get(entity.Path, null, passiveNamespace.Alias)
                                  .ConfigureAwait(false));
                }

                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       = await sendersLifeCycleManager.Get(entity.Path, via, ns.Alias)
                                          .ConfigureAwait(false);

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

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

                pendingSends.Add(RouteOutBatchesWithFallbackAndLogExceptionsAsync(messageSender, fallbacks, brokeredMessages, suppressTransaction));
            }
            await Task.WhenAll(pendingSends)
            .ConfigureAwait(false);
        }
        void AddMulticastOperationBatches(TransportOperations operations, Dictionary <string, BatchInternal> indexedBatches)
        {
            foreach (var multicastOperation in operations.MulticastTransportOperations)
            {
                var key = $"multicast-{multicastOperation.MessageType}-consistency-{multicastOperation.RequiredDispatchConsistency}";
                if (!indexedBatches.TryGetValue(key, out var batch))
                {
                    batch = new BatchInternal();
                    indexedBatches[key] = batch;

                    batch.Destinations = topologySectionManager.DeterminePublishDestination(multicastOperation.MessageType, localAddress);
                    batch.RequiredDispatchConsistency = multicastOperation.RequiredDispatchConsistency;
                }
                batch.Operations.Add(new BatchedOperationInternal(messageSizePaddingPercentage)
                {
                    DeliveryConstraints = multicastOperation.DeliveryConstraints,
                    Message             = multicastOperation.Message
                });
            }
        }
        void AddUnicastOperationBatches(TransportOperations operations, Dictionary <string, BatchInternal> indexedBatches)
        {
            foreach (var unicastOperation in operations.UnicastTransportOperations)
            {
                var key = $"unicast-{unicastOperation.Destination}-consistency-{unicastOperation.RequiredDispatchConsistency}";
                if (!indexedBatches.TryGetValue(key, out var batch))
                {
                    batch = new BatchInternal();
                    indexedBatches[key] = batch;

                    batch.Destinations = topologySectionManager.DetermineSendDestination(unicastOperation.Destination);
                    batch.RequiredDispatchConsistency = unicastOperation.RequiredDispatchConsistency;
                }
                batch.Operations.Add(new BatchedOperationInternal(messageSizePaddingPercentage)
                {
                    Message             = unicastOperation.Message,
                    DeliveryConstraints = unicastOperation.DeliveryConstraints
                });
            }
        }