Beispiel #1
0
        /// <summary>
        /// Finishes the setup of the bus, using default implementations for the options that have not explicitly been set.
        /// The only requirement, is that you must call <see cref="Transport"/> and select which transport to use - everything
        /// else can run with a default option. It should be noted though, that several of the defaults (e.g. in-mem persistence
        /// options for saga storage, subscriptions, and timeouts) are not meant for production use, and should probably be
        /// replaced by something that is actually persistent.
        /// </summary>
        public IBus Start()
        {
#if HAS_CONFIGURATION_MANAGER
            // force the silly configuration subsystem to initialize itself as a service to users, thus
            // avoiding the oft-encountered stupid Entity Framework initialization exception
            // complaining that something in Rebus' transaction context is not serializable
            System.Configuration.ConfigurationManager.GetSection("system.xml/xmlReader");
            // if you want to know more about this issue, check this out: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/mitigation-deserialization-of-objects-across-app-domains
#endif

            VerifyRequirements();

            _injectionist.Register(c => _options);
            _injectionist.Register(c => new CancellationTokenSource());
            _injectionist.Register(c => c.Get <CancellationTokenSource>().Token);

            PossiblyRegisterDefault <IRebusLoggerFactory>(c => new ConsoleLoggerFactory(true));

            PossiblyRegisterDefault <IRebusTime>(c => new DefaultRebusTime());

            //PossiblyRegisterDefault<IAsyncTaskFactory>(c => new TimerAsyncTaskFactory(c.Get<IRebusLoggerFactory>()));
            PossiblyRegisterDefault <IAsyncTaskFactory>(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new TplAsyncTaskFactory(rebusLoggerFactory));
            });

            PossiblyRegisterDefault <IRouter>(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new TypeBasedRouter(rebusLoggerFactory));
            });

            PossiblyRegisterDefault <ISubscriptionStorage>(c => new DisabledSubscriptionStorage());

            PossiblyRegisterDefault <ISagaStorage>(c => new DisabledSagaStorage());

            PossiblyRegisterDefault <ITimeoutManager>(c => new DisabledTimeoutManager());

            PossiblyRegisterDefault <ISerializer>(c => new JsonSerializer());

            PossiblyRegisterDefault <IPipelineInvoker>(c =>
            {
                var pipeline = c.Get <IPipeline>();
                return(new DefaultPipelineInvokerNew(pipeline));
            });

            PossiblyRegisterDefault <IBackoffStrategy>(c =>
            {
                var backoffTimes = new[]
                {
                    // 10 s
                    Enumerable.Repeat(TimeSpan.FromMilliseconds(100), 10),

                    // on and on
                    Enumerable.Repeat(TimeSpan.FromMilliseconds(250), 1)
                };

                return(new DefaultBackoffStrategy(backoffTimes.SelectMany(e => e)));
            });

            PossiblyRegisterDefault <IWorkerFactory>(c =>
            {
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var pipelineInvoker    = c.Get <IPipelineInvoker>();
                var options            = c.Get <Options>();
                var busLifetimeEvents  = c.Get <BusLifetimeEvents>();
                var backoffStrategy    = c.Get <IBackoffStrategy>();
                return(new ThreadPoolWorkerFactory(transport, rebusLoggerFactory, pipelineInvoker, options, c.Get <RebusBus>, busLifetimeEvents, backoffStrategy));
            });

            //PossiblyRegisterDefault<IWorkerFactory>(c =>
            //{
            //    var transport = c.Get<ITransport>();
            //    var loggerFactory = c.Get<IRebusLoggerFactory>();
            //    var pipelineInvoker = c.Get<IPipelineInvoker>();
            //    var options = c.Get<Options>();
            //    var busLifetimeEvents = c.Get<BusLifetimeEvents>();
            //    var backoffStrategy = c.Get<IBackoffStrategy>();
            //    return new TplWorkerFactory(transport, loggerFactory, pipelineInvoker, options, c.Get<RebusBus>, busLifetimeEvents, backoffStrategy);
            //});

            PossiblyRegisterDefault <IErrorTracker>(c =>
            {
                var transport          = c.Get <ITransport>();
                var settings           = c.Get <SimpleRetryStrategySettings>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                var rebusTime          = c.Get <IRebusTime>();
                return(new InMemErrorTracker(settings, rebusLoggerFactory, asyncTaskFactory, transport, rebusTime));
            });

            PossiblyRegisterDefault <IErrorHandler>(c =>
            {
                var settings           = c.Get <SimpleRetryStrategySettings>();
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new PoisonQueueErrorHandler(settings, transport, rebusLoggerFactory));
            });

            PossiblyRegisterDefault <IFailFastChecker>(c => new FailFastChecker());

            PossiblyRegisterDefault <IRetryStrategy>(c =>
            {
                var simpleRetryStrategySettings = c.Get <SimpleRetryStrategySettings>();
                var errorTracker = c.Get <IErrorTracker>();
                var errorHandler = c.Get <IErrorHandler>();
                return(new SimpleRetryStrategy(simpleRetryStrategySettings, errorTracker, errorHandler));
            });

            PossiblyRegisterDefault(c => new SimpleRetryStrategySettings());

            PossiblyRegisterDefault(c =>
            {
                var transport          = c.Get <ITransport>();
                var timeoutManager     = c.Get <ITimeoutManager>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                return(new HandleDeferredMessagesStep(timeoutManager, transport, _options, rebusLoggerFactory, asyncTaskFactory));
            });

            PossiblyRegisterDefault(c => c.Get <IRetryStrategy>().GetRetryStep());

            PossiblyRegisterDefault <IPipeline>(c =>
            {
                var serializer         = c.Get <ISerializer>();
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var options            = c.Get <Options>();
                var rebusTime          = c.Get <IRebusTime>();

                return(new DefaultPipeline()
                       .OnReceive(c.Get <IRetryStrategyStep>())
                       .OnReceive(new FailFastStep(c.Get <IErrorTracker>(), c.Get <IFailFastChecker>()))
                       .OnReceive(c.Get <HandleDeferredMessagesStep>())
                       .OnReceive(new HydrateIncomingMessageStep(c.Get <IDataBus>()))
                       .OnReceive(new DeserializeIncomingMessageStep(serializer))
                       .OnReceive(new HandleRoutingSlipsStep(transport, serializer))
                       .OnReceive(new ActivateHandlersStep(c.Get <IHandlerActivator>()))
                       .OnReceive(new LoadSagaDataStep(c.Get <ISagaStorage>(), rebusLoggerFactory))
                       .OnReceive(new DispatchIncomingMessageStep(rebusLoggerFactory))

                       .OnSend(new AssignDefaultHeadersStep(transport, rebusTime, options.DefaultReturnAddressOrNull))
                       .OnSend(new FlowCorrelationIdStep())
                       .OnSend(new AutoHeadersOutgoingStep())
                       .OnSend(new SerializeOutgoingMessageStep(serializer))
                       .OnSend(new ValidateOutgoingMessageStep())
                       .OnSend(new SendOutgoingMessageStep(transport, rebusLoggerFactory)));
            });

            RegisterDecorator <IPipeline>(c => new PipelineCache(c.Get <IPipeline>()));

            PossiblyRegisterDefault(c => new BusLifetimeEvents());

            PossiblyRegisterDefault <IDataBus>(c => new DisabledDataBus());

            PossiblyRegisterDefault <ITopicNameConvention>(c => new DefaultTopicNameConvention());

            // configuration hack - keep these two bad boys around to have them available at the last moment before returning the built bus instance...
            Action startAction = null;

            PossiblyRegisterDefault(c => new RebusBus(
                                        c.Get <IWorkerFactory>(),
                                        c.Get <IRouter>(),
                                        c.Get <ITransport>(),
                                        c.Get <IPipelineInvoker>(),
                                        c.Get <ISubscriptionStorage>(),
                                        _options,
                                        c.Get <IRebusLoggerFactory>(),
                                        c.Get <BusLifetimeEvents>(),
                                        c.Get <IDataBus>(),
                                        c.Get <ITopicNameConvention>(),
                                        c.Get <IRebusTime>()
                                        ));

            // since an error during resolution does not give access to disposable instances, we need to do this
            var disposableInstancesTrackedFromInitialResolution = new ConcurrentStack <IDisposable>();

            PossiblyRegisterDefault <IBus>(c =>
            {
                try
                {
                    var bus = c.Get <RebusBus>();
                    var cancellationTokenSource = c.Get <CancellationTokenSource>();

                    bus.Disposed += () =>
                    {
                        cancellationTokenSource.Cancel();

                        var disposableInstances = c.TrackedInstances.OfType <IDisposable>().Reverse();

                        foreach (var disposableInstance in disposableInstances)
                        {
                            disposableInstance.Dispose();
                        }
                    };

                    var initializableInstances = c.TrackedInstances.OfType <IInitializable>();

                    foreach (var initializableInstance in initializableInstances)
                    {
                        initializableInstance.Initialize();
                    }

                    // and then we set the startAction
                    startAction = () => bus.Start(_options.NumberOfWorkers);

                    return(bus);
                }
                catch
                {
                    // stash'em here quick!
                    foreach (var disposable in c.TrackedInstances.OfType <IDisposable>())
                    {
                        disposableInstancesTrackedFromInitialResolution.Push(disposable);
                    }
                    throw;
                }
            });

            _injectionist.Decorate <IHandlerActivator>(c =>
            {
                var handlerActivator            = c.Get <IHandlerActivator>();
                var subscriptionStorage         = c.Get <ISubscriptionStorage>();
                var internalHandlersContributor = new InternalHandlersContributor(handlerActivator, subscriptionStorage);
                return(internalHandlersContributor);
            });

            _injectionist.Decorate <ISerializer>(c =>
            {
                var serializer = c.Get <ISerializer>();
                var zipper     = new Zipper();
                var unzippingSerializerDecorator = new UnzippingSerializerDecorator(serializer, zipper);
                return(unzippingSerializerDecorator);
            });

            try
            {
                var busResolutionResult = _injectionist.Get <IBus>();
                var busInstance         = busResolutionResult.Instance;

                // if there is a container adapter among the tracked instances, hand it the bus instance
                var containerAdapter = busResolutionResult.TrackedInstances
                                       .OfType <IContainerAdapter>()
                                       .FirstOrDefault();

                containerAdapter?.SetBus(busInstance);

                // and NOW we are ready to start the bus if there is a startAction
                startAction?.Invoke();

                _hasBeenStarted = true;

                return(busInstance);
            }
            catch
            {
                while (disposableInstancesTrackedFromInitialResolution.TryPop(out var disposable))
                {
                    try
                    {
                        disposable.Dispose();
                    }
                    catch { } //< disposables must never throw, but sometimes they do
                }
                throw;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Finishes the setup of the bus, using default implementations for the options that have not explicitly been set.
        /// The only requirement, is that you must call <see cref="Transport"/> and select which transport to use - everything
        /// else can run with a default option. It should be noted though, that several of the defaults (e.g. in-mem persistence
        /// options for saga storage, subscriptions, and timeouts) are not meant for production use, and should probably be
        /// replaced by something that is actually persistent.
        /// </summary>
        public IBus Start()
        {
            VerifyRequirements();

            _injectionist.Register(c => _options);

            PossiblyRegisterDefault <IRebusLoggerFactory>(c => new ConsoleLoggerFactory(true));

            //PossiblyRegisterDefault<IAsyncTaskFactory>(c => new TimerAsyncTaskFactory(c.Get<IRebusLoggerFactory>()));
            PossiblyRegisterDefault <IAsyncTaskFactory>(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new TplAsyncTaskFactory(rebusLoggerFactory));
            });

            PossiblyRegisterDefault <IRouter>(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new TypeBasedRouter(rebusLoggerFactory));
            });

            PossiblyRegisterDefault <ISubscriptionStorage>(c => new InMemorySubscriptionStorage());

            PossiblyRegisterDefault <ISagaStorage>(c => new InMemorySagaStorage());

            PossiblyRegisterDefault <ISerializer>(c => new JsonSerializer());

            PossiblyRegisterDefault <IPipelineInvoker>(c => new DefaultPipelineInvoker());

            PossiblyRegisterDefault <IBackoffStrategy>(c => new SimpleConstantPollingBackoffStrategy());

            //PossiblyRegisterDefault<IWorkerFactory>(c =>
            //{
            //    var transport = c.Get<ITransport>();
            //    var pipeline = c.Get<IPipeline>();
            //    var pipelineInvoker = c.Get<IPipelineInvoker>();
            //    var backoffStrategy = c.Get<IBackoffStrategy>();
            //    var rebusLoggerFactory = c.Get<IRebusLoggerFactory>();
            //    return new ThreadWorkerFactory(transport, pipeline, pipelineInvoker, backoffStrategy, rebusLoggerFactory, _options, c.Get<RebusBus>);
            //});

            PossiblyRegisterDefault <ISyncBackoffStrategy>(c =>
            {
                var backoffTimes = new[]
                {
                    // 10 s
                    Enumerable.Repeat(TimeSpan.FromMilliseconds(100), 10),

                    // on and on
                    Enumerable.Repeat(TimeSpan.FromMilliseconds(250), 1)
                };

                return(new DefaultSyncBackoffStrategy(backoffTimes.SelectMany(e => e)));
            });

            PossiblyRegisterDefault <IWorkerFactory>(c =>
            {
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var pipeline           = c.Get <IPipeline>();
                var pipelineInvoker    = c.Get <IPipelineInvoker>();
                var options            = c.Get <Options>();
                var busLifetimeEvents  = c.Get <BusLifetimeEvents>();
                var backoffStrategy    = c.Get <ISyncBackoffStrategy>();
                return(new ThreadPoolWorkerFactory(transport, rebusLoggerFactory, pipeline, pipelineInvoker, options, c.Get <RebusBus>, busLifetimeEvents, backoffStrategy));
            });

            PossiblyRegisterDefault <IErrorTracker>(c =>
            {
                var settings           = c.Get <SimpleRetryStrategySettings>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                return(new InMemErrorTracker(settings.MaxDeliveryAttempts, rebusLoggerFactory, asyncTaskFactory));
            });

            PossiblyRegisterDefault <IErrorHandler>(c =>
            {
                var settings           = c.Get <SimpleRetryStrategySettings>();
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new PoisonQueueErrorHandler(settings, transport, rebusLoggerFactory));
            });

            PossiblyRegisterDefault <IRetryStrategy>(c =>
            {
                var simpleRetryStrategySettings = c.Get <SimpleRetryStrategySettings>();
                var errorTracker = c.Get <IErrorTracker>();
                var errorHandler = c.Get <IErrorHandler>();
                return(new SimpleRetryStrategy(simpleRetryStrategySettings, errorTracker, errorHandler));
            });

            PossiblyRegisterDefault(c => new SimpleRetryStrategySettings());

            PossiblyRegisterDefault <ITimeoutManager>(c => new InMemoryTimeoutManager());

            PossiblyRegisterDefault(c =>
            {
                var transport          = c.Get <ITransport>();
                var timeoutManager     = c.Get <ITimeoutManager>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                return(new HandleDeferredMessagesStep(timeoutManager, transport, _options, rebusLoggerFactory, asyncTaskFactory));
            });

            PossiblyRegisterDefault(c => c.Get <IRetryStrategy>().GetRetryStep());

            PossiblyRegisterDefault <IPipeline>(c =>
            {
                var serializer         = c.Get <ISerializer>();
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();

                return(new DefaultPipeline()
                       .OnReceive(c.Get <IRetryStrategyStep>())
                       .OnReceive(c.Get <HandleDeferredMessagesStep>())
                       .OnReceive(new DeserializeIncomingMessageStep(serializer))
                       .OnReceive(new ActivateHandlersStep(c.Get <IHandlerActivator>()))
                       .OnReceive(new LoadSagaDataStep(c.Get <ISagaStorage>(), rebusLoggerFactory))
                       .OnReceive(new DispatchIncomingMessageStep())

                       .OnSend(new AssignGuidMessageIdStep())
                       .OnSend(new AssignReturnAddressStep(transport))
                       .OnSend(new AssignDateTimeOffsetHeader())
                       .OnSend(new FlowCorrelationIdStep())
                       .OnSend(new AutoHeadersOutgoingStep())
                       .OnSend(new AssignTypeHeaderStep())
                       .OnSend(new SerializeOutgoingMessageStep(serializer))
                       .OnSend(new ValidateOutgoingMessageStep())
                       .OnSend(new SendOutgoingMessageStep(transport, rebusLoggerFactory)));
            });

            RegisterDecorator <IPipeline>(c => new PipelineCache(c.Get <IPipeline>()));

            PossiblyRegisterDefault(c => new BusLifetimeEvents());

            PossiblyRegisterDefault <IDataBus>(c => new DisabledDataBus());

            // configuration hack - keep these two bad boys around to have them available at the last moment before returning the built bus instance...
            Action startAction = null;

            PossiblyRegisterDefault(c => new RebusBus(
                                        c.Get <IWorkerFactory>(),
                                        c.Get <IRouter>(),
                                        c.Get <ITransport>(),
                                        c.Get <IPipeline>(),
                                        c.Get <IPipelineInvoker>(),
                                        c.Get <ISubscriptionStorage>(),
                                        _options,
                                        c.Get <IRebusLoggerFactory>(),
                                        c.Get <BusLifetimeEvents>(),
                                        c.Get <IDataBus>()));

            PossiblyRegisterDefault <IBus>(c =>
            {
                var bus = c.Get <RebusBus>();

                bus.Disposed += () =>
                {
                    var disposableInstances = c.TrackedInstances.OfType <IDisposable>().Reverse();

                    foreach (var disposableInstance in disposableInstances)
                    {
                        disposableInstance.Dispose();
                    }
                };

                var initializableInstances = c.TrackedInstances.OfType <IInitializable>();

                foreach (var initializableInstance in initializableInstances)
                {
                    initializableInstance.Initialize();
                }

                // and then we set the startAction
                startAction = () => bus.Start(_options.NumberOfWorkers);

                return(bus);
            });

            _injectionist.Decorate <IHandlerActivator>(c =>
            {
                var handlerActivator            = c.Get <IHandlerActivator>();
                var subscriptionStorage         = c.Get <ISubscriptionStorage>();
                var internalHandlersContributor = new InternalHandlersContributor(handlerActivator, subscriptionStorage);
                return(internalHandlersContributor);
            });

            var busResolutionResult = _injectionist.Get <IBus>();
            var busInstance         = busResolutionResult.Instance;

            // if there is a container adapter among the tracked instances, hand it the bus instance
            var containerAdapter = busResolutionResult.TrackedInstances
                                   .OfType <IContainerAdapter>()
                                   .FirstOrDefault();

            containerAdapter?.SetBus(busInstance);

            // and NOW we are ready to start the bus if there is a startAction
            startAction?.Invoke();

            _hasBeenStarted = true;

            return(busInstance);
        }
Beispiel #3
0
        /// <summary>
        /// Finishes the setup of the bus, using default implementations for the options that have not explicitly been set.
        /// The only requirement, is that you must call <see cref="Transport"/> and select which transport to use - everything
        /// else can run with a default option. It should be noted though, that several of the defaults (e.g. in-mem persistence
        /// options for saga storage, subscriptions, and timeouts) are not meant for production use, and should probably be
        /// replaced by something that is actually persistent.
        /// </summary>
        public IBus Start()
        {
            VerifyRequirements();

            PossiblyRegisterDefault <IRouter>(c => new TypeBasedRouter());

            PossiblyRegisterDefault <ISubscriptionStorage>(c => new InMemorySubscriptionStorage());

            PossiblyRegisterDefault <ISagaStorage>(c => new InMemorySagaStorage());

            PossiblyRegisterDefault <ISerializer>(c => new JsonSerializer());

            PossiblyRegisterDefault <IPipelineInvoker>(c => new DefaultPipelineInvoker());

            PossiblyRegisterDefault <IWorkerFactory>(c =>
            {
                var transport       = c.Get <ITransport>();
                var pipeline        = c.Get <IPipeline>();
                var pipelineInvoker = c.Get <IPipelineInvoker>();
                return(new ThreadWorkerFactory(transport, pipeline, pipelineInvoker, _options.MaxParallelism));
            });

            PossiblyRegisterDefault <IRetryStrategy>(c =>
            {
                var transport = c.Get <ITransport>();
                var simpleRetryStrategySettings = c.Get <SimpleRetryStrategySettings>();
                return(new SimpleRetryStrategy(transport, simpleRetryStrategySettings));
            });

            PossiblyRegisterDefault(c => new SimpleRetryStrategySettings());

            PossiblyRegisterDefault <ITimeoutManager>(c => new InMemoryTimeoutManager());

            PossiblyRegisterDefault(c =>
            {
                var transport      = c.Get <ITransport>();
                var timeoutManager = c.Get <ITimeoutManager>();
                return(new HandleDeferredMessagesStep(timeoutManager, transport));
            });

            PossiblyRegisterDefault(c => c.Get <IRetryStrategy>().GetRetryStep());

            PossiblyRegisterDefault <IPipeline>(c => new DefaultPipeline()

                                                .OnReceive(c.Get <IRetryStrategyStep>())
                                                .OnReceive(c.Get <HandleDeferredMessagesStep>())
                                                .OnReceive(new DeserializeIncomingMessageStep(c.Get <ISerializer>()))
                                                .OnReceive(new ActivateHandlersStep(c.Get <IHandlerActivator>()))
                                                .OnReceive(new LoadSagaDataStep(c.Get <ISagaStorage>()))
                                                .OnReceive(new DispatchIncomingMessageStep())

                                                .OnSend(new AssignGuidMessageIdStep())
                                                .OnSend(new AssignReturnAddressStep(c.Get <ITransport>()))
                                                .OnSend(new AssignDateTimeOffsetHeader())
                                                .OnSend(new FlowCorrelationIdStep())
                                                .OnSend(new SerializeOutgoingMessageStep(c.Get <ISerializer>()))
                                                .OnSend(new SendOutgoingMessageStep(c.Get <ITransport>()))
                                                );

            RegisterDecorator <IPipeline>(c => new PipelineCache(c.Get <IPipeline>()));

            PossiblyRegisterDefault <IBus>(c =>
            {
                var bus = new RebusBus(
                    c.Get <IWorkerFactory>(),
                    c.Get <IRouter>(),
                    c.Get <ITransport>(),
                    c.Get <IPipeline>(),
                    c.Get <IPipelineInvoker>(),
                    c.Get <ISubscriptionStorage>());

                bus.Disposed += () =>
                {
                    var disposableInstances = c.GetTrackedInstancesOf <IDisposable>().Reverse();

                    foreach (var disposableInstance in disposableInstances)
                    {
                        disposableInstance.Dispose();
                    }
                };

                var initializableInstances = c.GetTrackedInstancesOf <IInitializable>();

                foreach (var initializableInstance in initializableInstances)
                {
                    initializableInstance.Initialize();
                }

                if (_injectionist.Has <IContainerAdapter>())
                {
                    c.Get <IContainerAdapter>().SetBus(bus);
                }

                bus.Start(_options.NumberOfWorkers);

                return(bus);
            });

            _injectionist.Register <IHandlerActivator>(c =>
            {
                var handlerActivator            = c.Get <IHandlerActivator>();
                var subscriptionStorage         = c.Get <ISubscriptionStorage>();
                var internalHandlersContributor = new InternalHandlersContributor(handlerActivator, subscriptionStorage);
                return(internalHandlersContributor);
            }, isDecorator: true);

            var busInstance = _injectionist.Get <IBus>();

            return(busInstance);
        }
Beispiel #4
0
        /// <summary>
        /// Finishes the setup of the bus, using default implementations for the options that have not explicitly been set.
        /// The only requirement, is that you must call <see cref="Transport"/> and select which transport to use - everything
        /// else can run with a default option. It should be noted though, that several of the defaults (e.g. in-mem persistence
        /// options for saga storage, subscriptions, and timeouts) are not meant for production use, and should probably be
        /// replaced by something that is actually persistent.
        /// </summary>
        public IBus Start()
        {
            VerifyRequirements();

            PossiblyRegisterDefault <IRebusLoggerFactory>(c => new ConsoleLoggerFactory(true));

            PossiblyRegisterDefault <IAsyncTaskFactory>(c => new TplAsyncTaskFactory(c.Get <IRebusLoggerFactory>()));

            PossiblyRegisterDefault <IRouter>(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new TypeBasedRouter(rebusLoggerFactory));
            });

            PossiblyRegisterDefault <ISubscriptionStorage>(c => new InMemorySubscriptionStorage());

            PossiblyRegisterDefault <ISagaStorage>(c => new InMemorySagaStorage());

            PossiblyRegisterDefault <ISerializer>(c => new JsonSerializer());

            PossiblyRegisterDefault <IPipelineInvoker>(c => new DefaultPipelineInvoker());

            PossiblyRegisterDefault <IBackoffStrategy>(c => new SimpleConstantPollingBackoffStrategy());

            PossiblyRegisterDefault <IWorkerFactory>(c =>
            {
                var transport          = c.Get <ITransport>();
                var pipeline           = c.Get <IPipeline>();
                var pipelineInvoker    = c.Get <IPipelineInvoker>();
                var backoffStrategy    = c.Get <IBackoffStrategy>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new ThreadWorkerFactory(transport, pipeline, pipelineInvoker, _options.MaxParallelism, backoffStrategy, rebusLoggerFactory));
            });

            PossiblyRegisterDefault <IErrorTracker>(c =>
            {
                var settings           = c.Get <SimpleRetryStrategySettings>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                return(new InMemErrorTracker(settings.MaxDeliveryAttempts, rebusLoggerFactory, asyncTaskFactory));
            });

            PossiblyRegisterDefault <IRetryStrategy>(c =>
            {
                var transport = c.Get <ITransport>();
                var simpleRetryStrategySettings = c.Get <SimpleRetryStrategySettings>();
                var errorTracker       = c.Get <IErrorTracker>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                return(new SimpleRetryStrategy(transport, simpleRetryStrategySettings, errorTracker, rebusLoggerFactory));
            });

            PossiblyRegisterDefault(c => new SimpleRetryStrategySettings());

            PossiblyRegisterDefault <ITimeoutManager>(c => new InMemoryTimeoutManager());

            PossiblyRegisterDefault(c =>
            {
                var transport          = c.Get <ITransport>();
                var timeoutManager     = c.Get <ITimeoutManager>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                return(new HandleDeferredMessagesStep(timeoutManager, transport, _options, rebusLoggerFactory, asyncTaskFactory));
            });

            PossiblyRegisterDefault(c => c.Get <IRetryStrategy>().GetRetryStep());

            PossiblyRegisterDefault <IPipeline>(c =>
            {
                var serializer         = c.Get <ISerializer>();
                var transport          = c.Get <ITransport>();
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();

                return(new DefaultPipeline()
                       .OnReceive(c.Get <IRetryStrategyStep>())
                       .OnReceive(c.Get <HandleDeferredMessagesStep>())
                       .OnReceive(new DeserializeIncomingMessageStep(serializer))
                       .OnReceive(new ActivateHandlersStep(c.Get <IHandlerActivator>()))
                       .OnReceive(new LoadSagaDataStep(c.Get <ISagaStorage>(), rebusLoggerFactory))
                       .OnReceive(new DispatchIncomingMessageStep())

                       .OnSend(new AssignGuidMessageIdStep())
                       .OnSend(new AssignReturnAddressStep(transport))
                       .OnSend(new AssignDateTimeOffsetHeader())
                       .OnSend(new FlowCorrelationIdStep())
                       .OnSend(new AutoHeadersOutgoingStep())
                       .OnSend(new AssignTypeHeaderStep())
                       .OnSend(new SerializeOutgoingMessageStep(serializer))
                       .OnSend(new SendOutgoingMessageStep(transport, rebusLoggerFactory)));
            });

            RegisterDecorator <IPipeline>(c => new PipelineCache(c.Get <IPipeline>()));

            // configuration hack - keep these two bad boys around to have them available at the last moment before returning the built bus instance...
            IContainerAdapter containerAdapter = null;
            Action            startAction      = null;

            PossiblyRegisterDefault <IBus>(c =>
            {
                var bus = new RebusBus(
                    c.Get <IWorkerFactory>(),
                    c.Get <IRouter>(),
                    c.Get <ITransport>(),
                    c.Get <IPipeline>(),
                    c.Get <IPipelineInvoker>(),
                    c.Get <ISubscriptionStorage>(),
                    _options,
                    c.Get <IRebusLoggerFactory>());

                bus.Disposed += () =>
                {
                    var disposableInstances = c.GetTrackedInstancesOf <IDisposable>().Reverse();

                    foreach (var disposableInstance in disposableInstances)
                    {
                        disposableInstance.Dispose();
                    }
                };

                var initializableInstances = c.GetTrackedInstancesOf <IInitializable>();

                foreach (var initializableInstance in initializableInstances)
                {
                    initializableInstance.Initialize();
                }

                if (_injectionist.Has <IContainerAdapter>())
                {
                    containerAdapter = c.Get <IContainerAdapter>();
                }

                startAction = () => bus.Start(_options.NumberOfWorkers);

                return(bus);
            });

            _injectionist.Decorate <IHandlerActivator>(c =>
            {
                var handlerActivator            = c.Get <IHandlerActivator>();
                var subscriptionStorage         = c.Get <ISubscriptionStorage>();
                var internalHandlersContributor = new InternalHandlersContributor(handlerActivator, subscriptionStorage);
                return(internalHandlersContributor);
            });

            var busInstance = _injectionist.Get <IBus>();

            containerAdapter?.SetBus(busInstance);

            startAction?.Invoke();

            _hasBeenStarted = true;

            return(busInstance);
        }