Example #1
0
        /// <summary>
        /// See <see cref="Feature.Setup" />.
        /// </summary>
        protected internal override void Setup(FeatureConfigurationContext context)
        {
            if (!PersistenceStartup.HasSupportFor <StorageType.Subscriptions>(context.Settings))
            {
                throw new Exception("The selected persistence doesn't have support for subscription storage. Select another persistence or disable the message-driven subscriptions feature using endpointConfiguration.DisableFeature<MessageDrivenSubscriptions>()");
            }

            var transportInfrastructure = context.Settings.Get <TransportInfrastructure>();
            var canReceive           = !context.Settings.GetOrDefault <bool>("Endpoint.SendOnly");
            var conventions          = context.Settings.Get <Conventions>();
            var enforceBestPractices = context.Routing.EnforceBestPractices;

            var distributionPolicy   = context.Routing.DistributionPolicy;
            var endpointInstances    = context.Routing.EndpointInstances;
            var publishers           = context.Routing.Publishers;
            var configuredPublishers = context.Settings.Get <ConfiguredPublishers>();

            configuredPublishers.Apply(publishers, conventions, enforceBestPractices);

            context.Pipeline.Register(b =>
            {
                var unicastPublishRouter = new UnicastPublishRouter(b.Build <MessageMetadataRegistry>(), i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)), b.Build <ISubscriptionStorage>());
                return(new UnicastPublishRouterConnector(unicastPublishRouter, distributionPolicy));
            }, "Determines how the published messages should be routed");

            if (canReceive)
            {
                var subscriberAddress  = context.Receiving.LocalAddress;
                var subscriptionRouter = new SubscriptionRouter(publishers, endpointInstances, i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)));

                context.Pipeline.Register(b => new MessageDrivenSubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends subscription requests when message driven subscriptions is in use");
                context.Pipeline.Register(b => new MessageDrivenUnsubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends requests to unsubscribe when message driven subscriptions is in use");

                var authorizer = context.Settings.GetSubscriptionAuthorizer();
                if (authorizer == null)
                {
                    authorizer = _ => true;
                }
                context.Container.RegisterSingleton(authorizer);
                context.Pipeline.Register <SubscriptionReceiverBehavior.Registration>();
            }
        }
Example #2
0
        /// <summary>
        /// See <see cref="Feature.Setup" />.
        /// </summary>
        protected internal override void Setup(FeatureConfigurationContext context)
        {
            // The MessageDrivenSubscriptions feature needs to be activated when using the subscription migration mode as some persister packages check this feature before enabling the subscription storage.
            if (SubscriptionMigrationMode.IsMigrationModeEnabled(context.Settings))
            {
                return;
            }

            var transportInfrastructure = context.Settings.Get <TransportInfrastructure>();
            var conventions             = context.Settings.Get <Conventions>();
            var enforceBestPractices    = context.Routing.EnforceBestPractices;

            var distributionPolicy = context.Routing.DistributionPolicy;
            var endpointInstances  = context.Routing.EndpointInstances;
            var publishers         = context.Routing.Publishers;

            var configuredPublishers = context.Settings.Get <ConfiguredPublishers>();

            configuredPublishers.Apply(publishers, conventions, enforceBestPractices);

            var publishingEnabled = context.Settings.Get <bool>(EnablePublishingSettingsKey);

            if (publishingEnabled)
            {
                if (!PersistenceStartup.HasSupportFor <StorageType.Subscriptions>(context.Settings))
                {
                    throw new Exception("The selected persistence doesn't have support for subscription storage. Select another persistence or disable the publish functionality using transportConfiguration.DisablePublishing()");
                }

                context.Pipeline.Register("UnicastPublishRouterConnector", b =>
                {
                    var unicastPublishRouter = new UnicastPublishRouter(b.Build <MessageMetadataRegistry>(), i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)), b.Build <ISubscriptionStorage>());
                    return(new UnicastPublishConnector(unicastPublishRouter, distributionPolicy));
                }, "Determines how the published messages should be routed");

                var authorizer = context.Settings.GetSubscriptionAuthorizer();
                if (authorizer == null)
                {
                    authorizer = _ => true;
                }
                context.Container.RegisterSingleton(authorizer);
                context.Pipeline.Register <SubscriptionReceiverBehavior.Registration>();
            }
            else
            {
                context.Pipeline.Register(typeof(DisabledPublishingTerminator), "Throws an exception when trying to publish with publishing disabled");
            }

            var canReceive = !context.Settings.GetOrDefault <bool>("Endpoint.SendOnly");

            if (canReceive)
            {
                var subscriberAddress  = context.Receiving.LocalAddress;
                var subscriptionRouter = new SubscriptionRouter(publishers, endpointInstances, i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)));

                context.Pipeline.Register(b => new MessageDrivenSubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends subscription requests when message driven subscriptions is in use");
                context.Pipeline.Register(b => new MessageDrivenUnsubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends requests to unsubscribe when message driven subscriptions is in use");
            }
            else
            {
                context.Pipeline.Register(new SendOnlySubscribeTerminator(), "Throws an exception when trying to subscribe from a send-only endpoint");
                context.Pipeline.Register(new SendOnlyUnsubscribeTerminator(), "Throws an exception when trying to unsubscribe from a send-only endpoint");
            }
        }
Example #3
0
        /// <summary>
        /// Creates a new instance of a router based on the provided configuration.
        /// </summary>
        /// <param name="config">Router configuration.</param>
        public static IRouter Create(RouterConfiguration config)
        {
            if (config.RoutingProtocol == null)
            {
                throw new Exception("Routing protocol must be configured.");
            }

            config.EnableFeature(typeof(NativePubSubFeature));

            foreach (var featureType in config.Features)
            {
                var feature = (IFeature)Activator.CreateInstance(featureType);
                feature.Configure(config);
            }

            var interfaces = config.InterfaceFactories.Select(x => x()).ToArray();

            var chains = config.Chains;

            chains.AddChain(cb => cb.Begin <RawContext>().AddSection <PreroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <SubscribePreroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <UnsubscribePreroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <SendPreroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <PublishPreroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <ReplyPreroutingContext>().Terminate());

            chains.AddChain(cb => cb.Begin <ForwardSubscribeContext>().Terminate());
            chains.AddChain(cb => cb.Begin <ForwardUnsubscribeContext>().Terminate());
            chains.AddChain(cb => cb.Begin <ForwardSendContext>().Terminate());
            chains.AddChain(cb => cb.Begin <ForwardPublishContext>().Terminate());
            chains.AddChain(cb => cb.Begin <ForwardReplyContext>().Terminate());

            chains.AddChain(cb => cb.Begin <AnycastContext>().AddSection <PostroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <MulticastContext>().AddSection <PostroutingContext>().Terminate());
            chains.AddChain(cb => cb.Begin <PostroutingContext>().Terminate());

            chains.AddRule(_ => new RawToPreroutingConnector());
            chains.AddRule(_ => new PreroutingToSubscribePreroutingFork());
            chains.AddRule(_ => new PreroutingToSendPreroutingFork());
            chains.AddRule(_ => new PreroutingToPublishPreroutingFork());
            chains.AddRule(_ => new PreroutingToReplyPreroutingFork());

            chains.AddRule(c => new DetectCyclesRule(c.Endpoint.EndpointName));

            chains.AddRule(c => new SubscribePreroutingTerminator(config.RoutingProtocol, c.TypeGenerator));
            chains.AddRule(c => new UnsubscribePreroutingTerminator(config.RoutingProtocol, c.TypeGenerator));
            chains.AddRule(_ => new SendPreroutingTerminator(config.RoutingProtocol));
            chains.AddRule(c => new PublishPreroutingTerminator(interfaces.Select(i => i.Name).ToArray(), c.TypeGenerator));
            chains.AddRule(_ => new ReplyPreroutingTerminator());

            chains.AddRule(_ => new FindSubscribeDestinationsByHeadersRule());
            chains.AddRule(_ => new FindUnsubscribeDestinationsByHeadersRule());
            chains.AddRule(_ => new FindSendDestinationsByHeadersRule());

            chains.AddRule(c => new ForwardSendRule());
            chains.AddRule(c => new ForwardSendGatewayRule());
            chains.AddRule(_ => new ForwardReplyRule());
            chains.AddRule(c => new SendReplyTraceRule(c.Endpoint.TransportAddress, c.Endpoint.EndpointName));
            chains.AddRule(c => new PublishReplyTraceRule(c.Endpoint.TransportAddress, c.Endpoint.EndpointName));
            chains.AddRule(c => new ForwardSubscribeGatewayRule(c.Endpoint.TransportAddress, c.Endpoint.EndpointName));
            chains.AddRule(c => new ForwardUnsubscribeGatewayRule(c.Endpoint.TransportAddress, c.Endpoint.EndpointName));

            chains.AddRule(c => new AnycastToPostroutingConnector(c.EndpointInstances, c.DistributionPolicy, instance => c.Endpoint.ToTransportAddress(LogicalAddress.CreateRemoteAddress(instance))));
            chains.AddRule(c => new MulticastToPostroutingConnector(c.EndpointInstances, instance => c.Endpoint.ToTransportAddress(LogicalAddress.CreateRemoteAddress(instance))));
            chains.AddRule(c => new PostroutingTerminator(c.Endpoint));

            return(new RouterImpl(config.Name, interfaces, config.Modules.ToArray(), config.RoutingProtocol, chains, config.Settings));
        }
Example #4
0
        protected internal override void Setup(FeatureConfigurationContext context)
        {
            var canReceive = !context.Settings.GetOrDefault <bool>("Endpoint.SendOnly");
            var transportInfrastructure = context.Settings.Get <TransportInfrastructure>();

            var unicastRoutingTable = context.Settings.Get <UnicastRoutingTable>();
            var endpointInstances   = context.Settings.Get <EndpointInstances>();
            var publishers          = context.Settings.Get <Publishers>();

            var distributionPolicy      = context.Settings.Get <DistributionPolicy>();
            var configuredUnicastRoutes = context.Settings.Get <ConfiguredUnicastRoutes>();
            var configuredPublishers    = context.Settings.Get <ConfiguredPublishers>();
            var conventions             = context.Settings.Get <Conventions>();
            var unicastBusConfig        = context.Settings.GetConfigSection <UnicastBusConfig>();
            var distributorAddress      = context.Settings.GetOrDefault <string>("LegacyDistributor.Address");

            var enforceBestPractices = context.Settings.Get <bool>(EnforceBestPracticesSettingsKey);

            if (enforceBestPractices)
            {
                EnableBestPracticeEnforcement(context);
            }

            unicastBusConfig?.MessageEndpointMappings.Apply(publishers, unicastRoutingTable, transportInfrastructure.MakeCanonicalForm, conventions);
            configuredUnicastRoutes.Apply(unicastRoutingTable, conventions);
            configuredPublishers.Apply(publishers, conventions, enforceBestPractices);

            var outboundRoutingPolicy = transportInfrastructure.OutboundRoutingPolicy;

            context.Pipeline.Register(b =>
            {
                var unicastSendRouter = new UnicastSendRouter(unicastRoutingTable, endpointInstances, i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)));
                return(new UnicastSendRouterConnector(context.Settings.LocalAddress(), context.Settings.InstanceSpecificQueue(), distributorAddress, unicastSendRouter, distributionPolicy, i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i))));
            }, "Determines how the message being sent should be routed");

            context.Pipeline.Register(new UnicastReplyRouterConnector(), "Determines how replies should be routed");
            if (outboundRoutingPolicy.Publishes == OutboundRoutingType.Unicast)
            {
                context.Pipeline.Register(b =>
                {
                    var unicastPublishRouter = new UnicastPublishRouter(b.Build <MessageMetadataRegistry>(), b.Build <ISubscriptionStorage>());
                    return(new UnicastPublishRouterConnector(unicastPublishRouter, distributionPolicy));
                }, "Determines how the published messages should be routed");
            }
            else
            {
                context.Pipeline.Register(new MulticastPublishRouterBehavior(), "Determines how the published messages should be routed");
            }

            if (canReceive)
            {
                var publicReturnAddress = context.Settings.GetOrDefault <string>("PublicReturnAddress");
                context.Pipeline.Register(new ApplyReplyToAddressBehavior(context.Settings.LocalAddress(), context.Settings.InstanceSpecificQueue(), publicReturnAddress, distributorAddress), "Applies the public reply to address to outgoing messages");

                if (outboundRoutingPolicy.Publishes == OutboundRoutingType.Unicast)
                {
                    var subscriberAddress  = distributorAddress ?? context.Settings.LocalAddress();
                    var subscriptionRouter = new SubscriptionRouter(publishers, endpointInstances, i => transportInfrastructure.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)));

                    context.Pipeline.Register(b => new MessageDrivenSubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends subscription requests when message driven subscriptions is in use");
                    context.Pipeline.Register(b => new MessageDrivenUnsubscribeTerminator(subscriptionRouter, subscriberAddress, context.Settings.EndpointName(), b.Build <IDispatchMessages>()), "Sends requests to unsubscribe when message driven subscriptions is in use");
                }
                else
                {
                    var transportSubscriptionInfrastructure = transportInfrastructure.ConfigureSubscriptionInfrastructure();
                    var subscriptionManager = transportSubscriptionInfrastructure.SubscriptionManagerFactory();

                    context.Pipeline.Register(new NativeSubscribeTerminator(subscriptionManager), "Requests the transport to subscribe to a given message type");
                    context.Pipeline.Register(new NativeUnsubscribeTerminator(subscriptionManager), "Requests the transport to unsubscribe to a given message type");
                }
            }
        }