示例#1
0
        NamespaceInfo SelectMostAppropriateReplyToNamespace(RuntimeNamespaceInfo destinationNamespace)
        {
            var selected = destinationNamespace != null?namespaceConfigurations.FirstOrDefault(ns => ns.Alias == destinationNamespace.Alias) : null;

            if (selected == null)
            {
                selected = namespaceConfigurations.FirstOrDefault(ns => ns.Alias == defaultAlias);
            }
            if (selected == null)
            {
                selected = namespaceConfigurations.FirstOrDefault(ns => ns.Purpose == NamespacePurpose.Partitioning);
            }
            return(selected);
        }
示例#2
0
        NamespaceInfo SelectMostAppropriateReplyToNamespace(RuntimeNamespaceInfo destinationNamespace)
        {
            var namespaces   = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces).Where(n => n.Purpose == NamespacePurpose.Partitioning).ToList();
            var defaultAlias = settings.Get <string>(WellKnownConfigurationKeys.Topology.Addressing.DefaultNamespaceAlias);

            var selected = destinationNamespace != null?namespaces.FirstOrDefault(ns => ns.Alias == destinationNamespace.Alias) : null;

            if (selected == null)
            {
                selected = namespaces.FirstOrDefault(ns => ns.Alias == defaultAlias);
            }
            if (selected == null)
            {
                selected = namespaces.FirstOrDefault(ns => ns.Purpose == NamespacePurpose.Partitioning);
            }
            return(selected);
        }
        TopologySectionInternal BuildSubscriptionHierarchy(Type eventType, string localAddress)
        {
            var namespaces = namespacePartitioningStrategy.GetNamespaces(PartitioningIntent.Creating).ToArray();

            var publishers = publishersConfiguration.GetPublishersFor(eventType);

            // Using localAddress that will be provided by SubscriptionManager instead of the endpoint name.
            // Reason: endpoint name can be overridden. If the endpoint name is overridden, "originalEndpointName" will not have the override value.
            var subscriptionNameCandidateV6 = $"{localAddress}.{eventType.Name}";
            var subscriptionNameV6          = addressingLogic.Apply(subscriptionNameCandidateV6, EntityType.Subscription).Name;
            var subscriptionNameCandidate   = $"{localAddress}.{eventType.FullName}";
            var subscriptionName            = addressingLogic.Apply(subscriptionNameCandidate, EntityType.Subscription).Name;

            // Using localAddress that will be provided by SubscriptionManager instead of the endpoint name.
            // Reason: endpoint name can be overridden. If the endpoint name is overridden, "originalEndpointName" will not have the override value.
            var sanitizedInputQueuePath   = addressingLogic.Apply(localAddress, EntityType.Queue).Name;
            var sanitizedSubscriptionPath = addressingLogic.Apply(localAddress, EntityType.Subscription).Name;

            var ruleName = addressingLogic.Apply(eventType.FullName, EntityType.Rule).Name;

            var topics = new List <EntityInfoInternal>();
            var subs   = new List <SubscriptionInfoInternal>();

            foreach (var publisher in publishers)
            {
                var topicPath = $"{publisher}.events";
                var path      = addressingLogic.Apply(topicPath, EntityType.Topic).Name;

                var destinationsOutsideTopology = namespaceConfigurations.Where(c => c.RegisteredEndpoints.Contains(publisher, StringComparer.OrdinalIgnoreCase)).ToList();
                if (destinationsOutsideTopology.Any())
                {
                    // It's important to create Forwarding topology subscription infrastructure first in order not to lose messages in flight auto-forwarded by subscriptions under Endpoint-oriented topology
                    CreateForwardingTopologyPart(eventType, subs, namespaces, sanitizedSubscriptionPath, ruleName, sanitizedInputQueuePath);

                    topics.AddRange(destinationsOutsideTopology.Select(ns => new EntityInfoInternal
                    {
                        Namespace = new RuntimeNamespaceInfo(ns.Alias, ns.Connection, NamespacePurpose.Routing),
                        Type      = EntityType.Topic,
                        Path      = path
                    }));

                    subs.AddRange(destinationsOutsideTopology.Select(ns =>
                    {
                        var rns = new RuntimeNamespaceInfo(ns.Alias, ns.Connection, NamespacePurpose.Routing);
                        var sub = new SubscriptionInfoInternal
                        {
                            Namespace = rns,
                            Type      = EntityType.Subscription,
                            Path      = subscriptionNameV6,
                            Metadata  = new SubscriptionMetadataInternal
                            {
                                Description = $"{originalEndpointName} subscribed to {eventType.FullName}",
                                SubscriptionNameBasedOnEventWithNamespace = subscriptionName
                            },
                            BrokerSideFilter   = new SqlSubscriptionFilter(eventType),
                            ShouldBeListenedTo = false
                        };
                        sub.RelationShips.Add(new EntityRelationShipInfoInternal
                        {
                            Source = sub,
                            Target = topics.First(t => t.Path == path && t.Namespace == rns),
                            Type   = EntityRelationShipTypeInternal.Subscription
                        });
                        sub.RelationShips.Add(new EntityRelationShipInfoInternal
                        {
                            Source = sub,
                            Target = new EntityInfoInternal
                            {
                                Namespace = new RuntimeNamespaceInfo(ns.Alias, ns.Connection),
                                Path      = MigrationTopicName,
                                Type      = EntityType.Topic
                            },
                            Type = EntityRelationShipTypeInternal.Forward
                        });
                        return(sub);
                    }));
                }
                else
                {
                    // It's important to create Forwarding topology subscription infrastructure first in order not to lose messages in flight auto-forwarded by subscriptions under Endpoint-oriented topology
                    CreateForwardingTopologyPart(eventType, subs, namespaces, sanitizedSubscriptionPath, ruleName, sanitizedInputQueuePath);

                    topics.AddRange(namespaces.Select(ns => new EntityInfoInternal
                    {
                        Namespace = ns,
                        Type      = EntityType.Topic,
                        Path      = path
                    }));

                    subs.AddRange(namespaces.Select(ns =>
                    {
                        var sub = new SubscriptionInfoInternal
                        {
                            Namespace = ns,
                            Type      = EntityType.Subscription,
                            Path      = subscriptionNameV6,
                            Metadata  = new SubscriptionMetadataInternal
                            {
                                Description = $"{originalEndpointName} subscribed to {eventType.FullName}",
                                SubscriptionNameBasedOnEventWithNamespace = subscriptionName
                            },
                            BrokerSideFilter   = new SqlSubscriptionFilter(eventType),
                            ShouldBeListenedTo = false
                        };
                        sub.RelationShips.Add(new EntityRelationShipInfoInternal
                        {
                            Source = sub,
                            Target = topics.First(t => t.Path == path && t.Namespace == ns),
                            Type   = EntityRelationShipTypeInternal.Subscription
                        });
                        sub.RelationShips.Add(new EntityRelationShipInfoInternal
                        {
                            Source = sub,
                            Target = new EntityInfoInternal
                            {
                                Namespace = ns,
                                Path      = MigrationTopicName,
                                Type      = EntityType.Topic
                            },
                            Type = EntityRelationShipTypeInternal.Forward
                        });

                        return(sub);
                    }));
                }
            }

            return(new TopologySectionInternal
            {
                Entities = subs,
                Namespaces = namespaces
            });
        }
示例#4
0
        void SetReplyToAddress(OutgoingMessage outgoingMessage, BrokeredMessage brokeredMessage, RuntimeNamespaceInfo destinationNamespace)
        {
            if (outgoingMessage.Headers.ContainsKey(Headers.ReplyToAddress))
            {
                var replyToAddress = outgoingMessage.Headers[Headers.ReplyToAddress];
                // Read-only endpoints have no reply-to value
                if (string.IsNullOrWhiteSpace(replyToAddress))
                {
                    return;
                }

                var replyTo = new EntityAddress(replyToAddress);

                if (!replyTo.HasSuffix)
                {
                    var useAliases = settings.Get <bool>(WellKnownConfigurationKeys.Topology.Addressing.UseNamespaceAliasesInsteadOfConnectionStrings);

                    var selected = SelectMostAppropriateReplyToNamespace(destinationNamespace);

                    if (selected != null)
                    {
                        if (useAliases)
                        {
                            replyTo = new EntityAddress(replyTo.Name, selected.Alias);
                        }
                        else
                        {
                            replyTo = new EntityAddress(replyTo.Name, selected.ConnectionString);
                        }
                    }
                }

                var replyToAsString = replyTo.ToString();
                brokeredMessage.ReplyTo = replyToAsString;
            }
        }