/// <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>(); } }
/// <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"); } }
/// <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)); }
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"); } } }