public Configuration(LogicalAddress logicalAddress,
                      string queueNameBase,
                      string localAddress,
                      string instanceSpecificQueue,
                      TransportTransactionMode transactionMode,
                      PushRuntimeSettings pushRuntimeSettings,
                      bool purgeOnStartup,
                      Notification <ReceivePipelineCompleted> pipelineCompletedSubscribers,
                      bool isSendOnlyEndpoint,
                      List <Type> executeTheseHandlersFirst,
                      MessageHandlerRegistry messageHandlerRegistry,
                      bool createQueues, TransportSeam transportSeam)
 {
     LogicalAddress               = logicalAddress;
     QueueNameBase                = queueNameBase;
     LocalAddress                 = localAddress;
     InstanceSpecificQueue        = instanceSpecificQueue;
     TransactionMode              = transactionMode;
     PushRuntimeSettings          = pushRuntimeSettings;
     PurgeOnStartup               = purgeOnStartup;
     IsSendOnlyEndpoint           = isSendOnlyEndpoint;
     PipelineCompletedSubscribers = pipelineCompletedSubscribers;
     ExecuteTheseHandlersFirst    = executeTheseHandlersFirst;
     satelliteDefinitions         = new List <SatelliteDefinition>();
     this.messageHandlerRegistry  = messageHandlerRegistry;
     CreateQueues                 = createQueues;
     this.transportSeam           = transportSeam;
 }
        public static Configuration PrepareConfiguration(Settings settings, TransportSeam transportSeam)
        {
            var isSendOnlyEndpoint = settings.IsSendOnlyEndpoint;

            if (isSendOnlyEndpoint && settings.CustomLocalAddressProvided)
            {
                throw new Exception($"Specifying a base name for the input queue using `{nameof(ReceiveSettingsExtensions.OverrideLocalAddress)}(baseInputQueueName)` is not supported for send-only endpoints.");
            }

            var endpointName   = settings.EndpointName;
            var discriminator  = settings.EndpointInstanceDiscriminator;
            var queueNameBase  = settings.CustomLocalAddress ?? endpointName;
            var purgeOnStartup = settings.PurgeOnStartup;

            var transportInfrastructure = transportSeam.TransportInfrastructure;

            //note: This is an old hack, we are passing the endpoint name to bind but we only care about the properties
            var mainInstanceProperties = transportInfrastructure.BindToLocalEndpoint(new EndpointInstance(endpointName)).Properties;

            var logicalAddress = LogicalAddress.CreateLocalAddress(queueNameBase, mainInstanceProperties);

            var localAddress = transportInfrastructure.ToTransportAddress(logicalAddress);

            string instanceSpecificQueue = null;

            if (discriminator != null)
            {
                instanceSpecificQueue = transportInfrastructure.ToTransportAddress(logicalAddress.CreateIndividualizedAddress(discriminator));
            }

            var transactionMode = GetRequiredTransactionMode(settings, transportInfrastructure);

            var pushRuntimeSettings = settings.PushRuntimeSettings;

            var receiveConfiguration = new Configuration(
                logicalAddress,
                queueNameBase,
                localAddress,
                instanceSpecificQueue,
                transactionMode,
                pushRuntimeSettings,
                purgeOnStartup,
                settings.PipelineCompletedSubscribers ?? new Notification <ReceivePipelineCompleted>(),
                isSendOnlyEndpoint,
                settings.ExecuteTheseHandlersFirst,
                settings.MessageHandlerRegistry,
                settings.ShouldCreateQueues,
                transportSeam);

            settings.RegisterReceiveConfigurationForBackwardsCompatibility(receiveConfiguration);

            return(receiveConfiguration);
        }
Beispiel #3
0
        public static RoutingComponent Initialize(
            Configuration configuration,
            TransportSeam transportSeam,
            ReceiveComponent.Configuration receiveConfiguration,
            Conventions conventions,
            PipelineSettings pipelineSettings)
        {
            var distributionPolicy  = configuration.DistributionPolicy;
            var unicastRoutingTable = configuration.UnicastRoutingTable;
            var endpointInstances   = configuration.EndpointInstances;

            foreach (var distributionStrategy in configuration.CustomDistributionStrategies)
            {
                distributionPolicy.SetDistributionStrategy(distributionStrategy);
            }

            configuration.ConfiguredUnicastRoutes?.Apply(unicastRoutingTable, conventions);

            var isSendOnlyEndpoint = receiveConfiguration.IsSendOnlyEndpoint;

            if (!isSendOnlyEndpoint)
            {
                pipelineSettings.Register(
                    new ApplyReplyToAddressBehavior(
                        receiveConfiguration.LocalAddress,
                        receiveConfiguration.InstanceSpecificQueue,
                        configuration.PublicReturnAddress),
                    "Applies the public reply to address to outgoing messages");
            }

            var sendRouter = new UnicastSendRouter(
                isSendOnlyEndpoint,
                receiveConfiguration?.QueueNameBase,
                receiveConfiguration?.InstanceSpecificQueue,
                distributionPolicy,
                unicastRoutingTable,
                endpointInstances,
                i => transportSeam.TransportDefinition.ToTransportAddress(new QueueAddress(i.Endpoint, i.Discriminator, i.Properties, null)));

            if (configuration.EnforceBestPractices)
            {
                EnableBestPracticeEnforcement(pipelineSettings, new Validations(conventions));
            }

            return(new RoutingComponent(
                       sendRouter,
                       configuration.EnforceBestPractices));
        }
Beispiel #4
0
        public static TransportSeam Create(Settings transportSeamSettings, HostingComponent.Configuration hostingConfiguration)
        {
            var transportDefinition = transportSeamSettings.TransportDefinition;

            transportSeamSettings.settings.Set(transportDefinition);

            var settings = new HostSettings(hostingConfiguration.EndpointName,
                                            hostingConfiguration.HostInformation.DisplayName, hostingConfiguration.StartupDiagnostics,
                                            hostingConfiguration.CriticalError.Raise, hostingConfiguration.ShouldRunInstallers,
                                            transportSeamSettings.settings);

            var transportSeam = new TransportSeam(transportDefinition, settings, transportSeamSettings.QueueBindings);

            hostingConfiguration.Services.ConfigureComponent(() => transportSeam.TransportInfrastructure.Dispatcher, DependencyLifecycle.SingleInstance);

            return(transportSeam);
        }
Beispiel #5
0
 public StartableEndpoint(SettingsHolder settings,
                          FeatureComponent featureComponent,
                          ReceiveComponent receiveComponent,
                          TransportSeam transportSeam,
                          PipelineComponent pipelineComponent,
                          RecoverabilityComponent recoverabilityComponent,
                          HostingComponent hostingComponent,
                          SendComponent sendComponent,
                          IServiceProvider builder)
 {
     this.settings                = settings;
     this.featureComponent        = featureComponent;
     this.receiveComponent        = receiveComponent;
     this.transportSeam           = transportSeam;
     this.pipelineComponent       = pipelineComponent;
     this.recoverabilityComponent = recoverabilityComponent;
     this.hostingComponent        = hostingComponent;
     this.sendComponent           = sendComponent;
     this.builder = builder;
 }
        public void Initialize(ReceiveComponent.Configuration receiveConfiguration, HostingComponent.Configuration hostingConfiguration, TransportSeam transportSeam)
        {
            if (receiveConfiguration.IsSendOnlyEndpoint)
            {
                //Message recoverability is only relevant for endpoints receiving messages.
                return;
            }

            hostInformation    = hostingConfiguration.HostInformation;
            this.transportSeam = transportSeam;

            transactionsOn = transportSeam.TransportDefinition.TransportTransactionMode != TransportTransactionMode.None;

            var errorQueue = settings.ErrorQueueAddress();

            transportSeam.QueueBindings.BindSending(errorQueue);

            var immediateRetryConfig = GetImmediateRetryConfig();

            var delayedRetryConfig = GetDelayedRetryConfig();

            var failedConfig = new FailedConfig(errorQueue, settings.UnrecoverableExceptions());

            recoverabilityConfig = new RecoverabilityConfig(immediateRetryConfig, delayedRetryConfig, failedConfig);

            hostingConfiguration.AddStartupDiagnosticsSection("Recoverability", new
            {
                ImmediateRetries           = recoverabilityConfig.Immediate.MaxNumberOfRetries,
                DelayedRetries             = recoverabilityConfig.Delayed.MaxNumberOfRetries,
                DelayedRetriesTimeIncrease = recoverabilityConfig.Delayed.TimeIncrease.ToString("g"),
                recoverabilityConfig.Failed.ErrorQueue,
                UnrecoverableExceptions = recoverabilityConfig.Failed.UnrecoverableExceptionTypes.Select(t => t.FullName).ToArray()
            });
        }
        public static SendComponent Initialize(PipelineSettings pipelineSettings, HostingComponent.Configuration hostingConfiguration, RoutingComponent routingComponent, IMessageMapper messageMapper, TransportSeam transportSeam)
        {
            pipelineSettings.Register(new AttachSenderRelatedInfoOnMessageBehavior(), "Makes sure that outgoing messages contains relevant info on the sending endpoint.");
            pipelineSettings.Register("AuditHostInformation", new AuditHostInformationBehavior(hostingConfiguration.HostInformation, hostingConfiguration.EndpointName), "Adds audit host information");
            pipelineSettings.Register("AddHostInfoHeaders", new AddHostInfoHeadersBehavior(hostingConfiguration.HostInformation, hostingConfiguration.EndpointName), "Adds host info headers to outgoing headers");

            pipelineSettings.Register("UnicastSendRouterConnector", new SendConnector(routingComponent.UnicastSendRouter), "Determines how the message being sent should be routed");
            pipelineSettings.Register("UnicastReplyRouterConnector", new ReplyConnector(), "Determines how replies should be routed");


            pipelineSettings.Register(new OutgoingPhysicalToRoutingConnector(), "Starts the message dispatch pipeline");
            pipelineSettings.Register(new RoutingToDispatchConnector(), "Decides if the current message should be batched or immediately be dispatched to the transport");
            pipelineSettings.Register(new BatchToDispatchConnector(), "Passes batched messages over to the immediate dispatch part of the pipeline");
            pipelineSettings.Register(b => new ImmediateDispatchTerminator(b.GetService <IDispatchMessages>()), "Hands the outgoing messages over to the transport for immediate delivery");

            var sendComponent = new SendComponent(messageMapper, transportSeam.TransportInfrastructure);

            sendComponent.transportSendInfrastructure = sendComponent.transportInfrastructure.ConfigureSendInfrastructure();

            hostingConfiguration.Container.ConfigureComponent(() => sendComponent.GetDispatcher(), DependencyLifecycle.SingleInstance);

            return(sendComponent);
        }
        void Initialize()
        {
            ConfigureMessageTypes();

            var pipelineSettings = settings.Get <PipelineSettings>();

            hostingConfiguration.Container.RegisterSingleton <ReadOnlySettings>(settings);

            featureComponent = new FeatureComponent(settings);

            // This needs to happen here to make sure that features enabled state is present in settings so both
            // IWantToRunBeforeConfigurationIsFinalized implementations and transports can check access it
            featureComponent.RegisterFeatureEnabledStatusInSettings(hostingConfiguration);

            transportSeam = TransportSeam.Create(settings.Get <TransportSeam.Settings>(), hostingConfiguration);

            var receiveConfiguration = ReceiveComponent.PrepareConfiguration(
                settings.Get <ReceiveComponent.Settings>(),
                transportSeam);

            var routingConfiguration = RoutingComponent.Configure(settings.Get <RoutingComponent.Settings>());

            var messageMapper = new MessageMapper();

            settings.Set <IMessageMapper>(messageMapper);

            recoverabilityComponent = new RecoverabilityComponent(settings);

            var featureConfigurationContext = new FeatureConfigurationContext(settings, hostingConfiguration.Container, pipelineSettings, routingConfiguration, receiveConfiguration);

            featureComponent.Initalize(featureConfigurationContext);

            recoverabilityComponent.Initialize(receiveConfiguration, hostingConfiguration, transportSeam);

            var routingComponent = RoutingComponent.Initialize(
                routingConfiguration,
                transportSeam,
                receiveConfiguration,
                settings.Get <Conventions>(),
                pipelineSettings);

            sendComponent = SendComponent.Initialize(pipelineSettings, hostingConfiguration, routingComponent, messageMapper, transportSeam);

            hostingConfiguration.Container.ConfigureComponent(b => settings.Get <Notifications>(), DependencyLifecycle.SingleInstance);

            receiveComponent = ReceiveComponent.Initialize(
                receiveConfiguration,
                settings.ErrorQueueAddress(),
                hostingConfiguration,
                pipelineSettings);

            pipelineComponent = PipelineComponent.Initialize(pipelineSettings, hostingConfiguration);

            // The settings can only be locked after initializing the feature component since it uses the settings to store & share feature state.
            // As well as all the other components have been initialized
            settings.PreventChanges();

            // The pipeline settings can be locked after the endpoint is configured. It prevents end users from modyfing pipeline after an endpoint has started.
            pipelineSettings.PreventChanges();

            settings.AddStartupDiagnosticsSection("Endpoint",
                                                  new
            {
                Name               = settings.EndpointName(),
                SendOnly           = settings.Get <bool>("Endpoint.SendOnly"),
                NServiceBusVersion = GitVersionInformation.MajorMinorPatch
            }
                                                  );
        }
        public static Configuration PrepareConfiguration(HostingComponent.Configuration hostingConfiguration, Settings settings, TransportSeam transportSeam)
        {
            var isSendOnlyEndpoint = settings.IsSendOnlyEndpoint;

            if (isSendOnlyEndpoint && settings.CustomLocalAddressProvided)
            {
                throw new Exception($"Specifying a base name for the input queue using `{nameof(ReceiveSettingsExtensions.OverrideLocalAddress)}(baseInputQueueName)` is not supported for send-only endpoints.");
            }

            var endpointName   = settings.EndpointName;
            var discriminator  = settings.EndpointInstanceDiscriminator;
            var queueNameBase  = settings.CustomLocalAddress ?? endpointName;
            var purgeOnStartup = settings.PurgeOnStartup;

            var transportDefinition = transportSeam.TransportDefinition;
            var localAddress        = transportDefinition.ToTransportAddress(new QueueAddress(queueNameBase, null, null, null));

            string instanceSpecificQueue = null;

            if (discriminator != null)
            {
                instanceSpecificQueue = transportDefinition.ToTransportAddress(new QueueAddress(queueNameBase, discriminator, null, null));
            }

            var pushRuntimeSettings = settings.PushRuntimeSettings;

            var receiveConfiguration = new Configuration(
                queueNameBase,
                localAddress,
                instanceSpecificQueue,
                pushRuntimeSettings,
                purgeOnStartup,
                settings.PipelineCompletedSubscribers ?? new Notification <ReceivePipelineCompleted>(),
                isSendOnlyEndpoint,
                settings.ExecuteTheseHandlersFirst,
                settings.MessageHandlerRegistry,
                settings.ShouldCreateQueues,
                transportSeam,
                settings.Conventions);

            settings.RegisterReceiveConfigurationForBackwardsCompatibility(receiveConfiguration);

            return(receiveConfiguration);
        }