Ejemplo n.º 1
0
 public static void UseApplicationInsight(this OptionsConfigurer configurer, Container container)
 {
     configurer.Decorate <IPipeline>(c =>
     {
         var pipeline = c.Get <IPipeline>();
         var step     = new ApplicationInsightsStep(container);
         return(new PipelineStepInjector(pipeline)
                .OnReceive(step, PipelineRelativePosition.Before, typeof(SimpleRetryStrategyStep))
                );
     });
 }
        /// <summary>
        /// Configures Rebus to encrypt outgoing messages and be able to decrypt incoming messages using custom encryption provider.
        /// Please note that it's only the message bodies that are encrypted, thus everything included in the message headers will be visible to eavesdroppers.
        /// Custom encrypotion providers are configured by building on the returned configurer, e.g. like so:
        /// <code>
        /// Configure.With(...)
        ///     .(...)
        ///     .Options(o => {
        ///         o.EnableCustomEncryption()
        ///             .Use***();
        ///     })
        ///     .Start();
        /// </code>
        /// </summary>
        public static StandardConfigurer <IEncryptor> EnableCustomEncryption(this OptionsConfigurer configurer)
        {
            configurer.Register(c => new EncryptMessagesOutgoingStep(c.Get <IEncryptor>()));
            configurer.Register(c => new DecryptMessagesIncomingStep(c.Get <IEncryptor>()));

            configurer.Decorate <IPipeline>(c => new PipelineStepInjector(c.Get <IPipeline>())
                                            .OnReceive(c.Get <DecryptMessagesIncomingStep>(), PipelineRelativePosition.Before, typeof(DeserializeIncomingMessageStep))
                                            .OnSend(c.Get <EncryptMessagesOutgoingStep>(), PipelineRelativePosition.After, typeof(SerializeOutgoingMessageStep)));

            return(StandardConfigurer <IEncryptor> .GetConfigurerFrom(configurer));
        }
Ejemplo n.º 3
0
 public static void AutomaticallyFlowUserContext(this OptionsConfigurer configurer, Container container)
 {
     configurer.Decorate <IPipeline>(c =>
     {
         var pipeline = c.Get <IPipeline>();
         var step     = new UserFlowStep(container);
         return(new PipelineStepInjector(pipeline)
                .OnReceive(step, PipelineRelativePosition.After, typeof(DeserializeIncomingMessageStep))
                .OnSend(step, PipelineRelativePosition.Before, typeof(SerializeOutgoingMessageStep)));
     });
 }
            public void When_configuring_instance_without_configurer_it_should_throw()
            {
                OptionsConfigurer configurer = null;
                // ReSharper disable once ExpressionIsAlwaysNull
                Action act = () => configurer.EnableCorrelate(new DependencyResolverAdapter(_ => null));

                // Assert
                act.Should()
                .Throw <ArgumentNullException>()
                .Where(exception => exception.ParamName == nameof(configurer));
            }
            public void When_configuring_instance_without_configurer_it_should_throw()
            {
                OptionsConfigurer configurer = null;
                // ReSharper disable once ExpressionIsAlwaysNull
                Action act = () => configurer.EnableCorrelate(new ServiceCollection().BuildServiceProvider());

                // Assert
                act.Should()
                .Throw <ArgumentNullException>()
                .Where(exception => exception.ParamName == nameof(configurer));
            }
        public static void Apply(this OptionsConfigurer configurer, ServiceBusOptions options)
        {
            if (options.NumberOfWorkers != null)
            {
                configurer.SetNumberOfWorkers(options.NumberOfWorkers.Value);
            }

            if (options.MaxParallelism != null)
            {
                configurer.SetMaxParallelism(options.MaxParallelism.Value);
            }
        }
Ejemplo n.º 7
0
        public void Apply(OptionsConfigurer configurer)
        {
            if (NumberOfWorkers != null)
            {
                configurer.SetNumberOfWorkers(NumberOfWorkers.Value);
            }

            if (MaxParallelism != null)
            {
                configurer.SetMaxParallelism(MaxParallelism.Value);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Enables compression of outgoing messages if the size exceeds the specified number of bytes
        /// (defaults to <see cref="DefaultBodyThresholdBytes"/>)
        /// </summary>
        public static OptionsConfigurer EnableCompression(this OptionsConfigurer configurer,
                                                          int bodySizeThresholdBytes = DefaultBodyThresholdBytes)
        {
            configurer.Register(c => new Zipper());
            configurer.Register(c => new UnzipMessagesIncomingStep(c.Get <Zipper>()));
            configurer.Register(c => new ZipMessagesOutgoingStep(c.Get <Zipper>(), bodySizeThresholdBytes));

            configurer.Decorate <IPipeline>(c => new PipelineStepInjector(c.Get <IPipeline>())
                                            .OnReceive(c.Get <UnzipMessagesIncomingStep>(), PipelineRelativePosition.Before, typeof(DeserializeIncomingMessageStep))
                                            .OnSend(c.Get <ZipMessagesOutgoingStep>(), PipelineRelativePosition.After, typeof(SerializeOutgoingMessageStep)));

            return(configurer);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Configures the timespans to wait when backing off polling the transport during idle times. <paramref name="backoffTimes"/>
        /// must be a sequence of timespans, which indicates the time to wait for each second elapsed being idle. When the idle time
        /// exceeds the number of timespans, the last timespan will be used.
        /// </summary>
        public static OptionsConfigurer SetBackoffTimes(this OptionsConfigurer configurer, IEnumerable <TimeSpan> backoffTimes)
        {
            var list = backoffTimes.ToList();

            if (!list.Any())
            {
                throw new ArgumentException("Please specify at least one TimeSpan when you customize the backoff times! You could for example specify new[] { TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5) } in order to wait 0.5s and 1s during the first two seconds of inactivity, and then 5 seconds poll interval forever thereafter");
            }

            configurer.Register <IBackoffStrategy>(c => new SimpleCustomizedBackoffStrategy(list));

            return(configurer);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Configures Rebus to execute handlers inside a <see cref="TransactionScope"/>
        /// </summary>
        public static OptionsConfigurer HandleMessagesInsideTransactionScope(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline     = c.Get <IPipeline>();
                var stepToInject = new TransactionScopeIncomingStep();

                return(new PipelineStepInjector(pipeline)
                       .OnReceive(stepToInject, PipelineRelativePosition.Before, typeof(DispatchIncomingMessageStep)));
            });

            return(configurer);
        }
        /// <summary>
        /// Configures the timespans to wait when backing off polling the transport during idle times. <paramref name="backoffTimes"/>
        /// must be a sequence of timespans, which indicates the time to wait for each second elapsed being idle. When the idle time
        /// exceeds the number of timespans, the last timespan will be used.
        /// </summary>
        public static void SetBackoffTimes(this OptionsConfigurer configurer, params TimeSpan[] backoffTimes)
        {
            if (configurer == null)
            {
                throw new ArgumentNullException(nameof(configurer));
            }
            if (backoffTimes == null)
            {
                throw new ArgumentNullException(nameof(backoffTimes));
            }

            SetBackoffTimes(configurer, (IEnumerable <TimeSpan>)backoffTimes);
        }
        /// <summary>
        /// Makes Rebus "legacy compatible", i.e. enables wire-level compatibility with older Rebus versions. WHen this is enabled,
        /// all endpoints need to be old Rebus endpoints or new Rebus endpoints with this feature enabled
        /// </summary>
        public static void EnableLegacyCompatibility(this OptionsConfigurer configurer)
        {
            configurer.Register <ISerializer>(c =>
            {
                var specialSettings = LegacySubscriptionMessagesBinder.JsonSerializerSettings;
                var legacyEncoding  = Encoding.UTF7;
                var jsonSerializer  = new JsonSerializer(specialSettings, legacyEncoding);
                return(jsonSerializer);
            });

            configurer.Decorate(c =>
            {
                var pipeline = c.Get <IPipeline>();

                // map headers of incoming message from v1 to v2
                pipeline = new PipelineStepConcatenator(pipeline)
                           .OnReceive(new MapLegacyHeadersIncomingStep(), PipelineAbsolutePosition.Front);

                // unpack object[] of transport message
                pipeline = new PipelineStepInjector(pipeline)
                           .OnReceive(new UnpackLegacyMessageIncomingStep(), PipelineRelativePosition.After, typeof(DeserializeIncomingMessageStep));

                // pack into object[]
                pipeline = new PipelineStepInjector(pipeline)
                           .OnSend(new PackLegacyMessageOutgoingStep(), PipelineRelativePosition.Before, typeof(SerializeOutgoingMessageStep));

                pipeline = new PipelineStepInjector(pipeline)
                           .OnSend(new MapLegacyHeadersOutgoingStep(), PipelineRelativePosition.Before, typeof(SendOutgoingMessageStep));

                //pipeline = new PipelineStepInjector(pipeline)
                //    .OnReceive(new HandleLegacySubscriptionRequestIncomingStep(c.Get<ISubscriptionStorage>(), c.Get<LegacySubscriptionMessageSerializer>()), PipelineRelativePosition.Before, typeof(MapLegacyHeadersIncomingStep));

                return(pipeline);
            });

            configurer.Decorate(c =>
            {
                var transport = c.Get <ITransport>();

                if (transport is MsmqTransport)
                {
                    c.Get <IRebusLoggerFactory>()
                    .GetCurrentClassLogger()
                    .Info("MSMQ transport detected - changing to UTF7 for serialized message header encoding");

                    ((MsmqTransport)transport).UseLegacyHeaderSerialization();
                }

                return(transport);
            });
        }
Ejemplo n.º 13
0
            public void With_null_configurer_it_should_throw()
            {
                OptionsConfigurer configurer = null;

                // ReSharper disable once ExpressionIsAlwaysNull
                // ReSharper disable once ObjectCreationAsStatement
                Action act = () => configurer.ValidateMessages(Mock.Of <IValidatorFactory>(), _ => { });

                // Assert
                act.Should()
                .Throw <ArgumentNullException>()
                .Which.ParamName.Should()
                .Be(nameof(configurer));
            }
Ejemplo n.º 14
0
        /// <summary>
        /// Decorates the current <see cref="IFailFastChecker"/> with a filter that causes Rebus to fail fast on exceptions of type
        /// <typeparamref name="TException"/> (optionally also requiring it to satisfy the when <paramref name="when"/>)
        /// </summary>
        public static void FailFastOn <TException>(this OptionsConfigurer configurer, Func <TException, bool> when = null) where TException : Exception
        {
            if (configurer == null)
            {
                throw new ArgumentNullException(nameof(configurer));
            }

            configurer.Decorate <IFailFastChecker>(c =>
            {
                var failFastChecker = c.Get <IFailFastChecker>();

                return(new FailFastOnSpecificExceptionTypeAndPredicate <TException>(failFastChecker, when));
            });
        }
Ejemplo n.º 15
0
        private static OptionsConfigurer ConfigurePipeline(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(ctx =>
            {
                IPipeline pipeline = ctx.Get <IPipeline>();
                CorrelateOutgoingMessageStep outgoingStep = ctx.Get <CorrelateOutgoingMessageStep>();
                CorrelateIncomingMessageStep incomingStep = ctx.Get <CorrelateIncomingMessageStep>();
                return(new PipelineStepInjector(pipeline)
                       .OnSend(outgoingStep, PipelineRelativePosition.Before, typeof(FlowCorrelationIdStep))
                       .OnReceive(incomingStep, PipelineRelativePosition.After, typeof(DeserializeIncomingMessageStep)));
            });

            return(configurer);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Enables message auditing whereby Rebus will forward to the audit queue a copy of each properly handled message and
        /// each published message
        /// </summary>
        public static StandardConfigurer <ISagaSnapshotStorage> EnableSagaAuditing(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline            = c.Get <IPipeline>();
                var sagaSnapshotStorage = GetSagaSnapshotStorage(c);
                var transport           = GetTransport(c);

                return(new PipelineStepInjector(pipeline)
                       .OnReceive(new SaveSagaDataSnapshotStep(sagaSnapshotStorage, transport), PipelineRelativePosition.Before, typeof(LoadSagaDataStep)));
            });

            return(configurer.GetConfigurer <ISagaSnapshotStorage>());
        }
        public static void UseDistributeTracingFlow(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(c =>
            {
                var outgoingStep = new SetTraceParentOutgoingStep();
                var incomingStep = new GetTraceParentIncomingStep();

                var pipeline = c.Get <IPipeline>();

                return(new PipelineStepInjector(pipeline)
                       .OnReceive(incomingStep, PipelineRelativePosition.After, typeof(DeserializeIncomingMessageStep))
                       .OnSend(outgoingStep, PipelineRelativePosition.Before, typeof(SerializeOutgoingMessageStep)));
            });
        }
Ejemplo n.º 18
0
        public static OptionsConfigurer RegisterOutgoingStep(this OptionsConfigurer configurer,
                                                             IOutgoingStep stepToInject,
                                                             PipelineRelativePosition position = PipelineRelativePosition.Before,
                                                             Type anchorStep = null)
        {
            anchorStep = anchorStep ?? typeof(SendOutgoingMessageStep);
            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline = c.Get <IPipeline>();

                return(new PipelineStepInjector(pipeline)
                       .OnSend(stepToInject, position, anchorStep));
            });

            return(configurer);
        }
        /// <summary>
        /// Configures Rebus to execute handlers inside a <see cref="TransactionScope"/>, using the transaction options
        /// given by <paramref name="transactionOptions"/> for the transaction scope
        /// </summary>
        public static void HandleMessagesInsideTransactionScope(this OptionsConfigurer configurer, TransactionOptions transactionOptions)
        {
            if (configurer == null)
            {
                throw new ArgumentNullException(nameof(configurer));
            }

            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline     = c.Get <IPipeline>();
                var stepToInject = new TransactionScopeIncomingStep(transactionOptions);

                return(new PipelineStepInjector(pipeline)
                       .OnReceive(stepToInject, PipelineRelativePosition.Before, typeof(DispatchIncomingMessageStep)));
            });
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Initiates the configuration of the handler ordering - call <see cref="ReorderingConfiguration.First{THandler}"/> in
        /// order to specify the handler that will be put first in the pipeline if it is present
        /// </summary>
        public static ReorderingConfiguration SpecifyOrderOfHandlers(this OptionsConfigurer configurer)
        {
            var configuration = new ReorderingConfiguration();

            configurer.Register(c => new HandlerReorderingStep(configuration));

            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline = c.Get <IPipeline>();
                var step     = c.Get <HandlerReorderingStep>();

                return(new PipelineStepInjector(pipeline)
                       .OnReceive(step, PipelineRelativePosition.Before, typeof(DispatchIncomingMessageStep)));
            });

            return(configuration);
        }
        /// <summary>
        /// Enables message auditing whereby Rebus will forward to the audit queue a copy of each properly handled message and
        /// each published message
        /// </summary>
        public static void EnableMessageAuditing(this OptionsConfigurer configurer, string auditQueue)
        {
            if (configurer == null)
            {
                throw new ArgumentNullException("configurer");
            }
            if (string.IsNullOrWhiteSpace(auditQueue))
            {
                throw new ArgumentNullException("auditQueue");
            }

            configurer.Register(c => new AuditingSteps(auditQueue, c.Get <ITransport>()));

            configurer.Decorate <IPipeline>(c => new PipelineStepInjector(c.Get <IPipeline>())
                                            .OnReceive(c.Get <AuditingSteps>(), PipelineRelativePosition.After, typeof(DispatchIncomingMessageStep))
                                            .OnSend(c.Get <AuditingSteps>(), PipelineRelativePosition.After, typeof(SendOutgoingMessageStep)));
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Configures Rebus to use Correlate as the Correlation ID provider by resolving Correlate dependencies using the specified <paramref name="dependencyResolverAdapter"/>.
        /// </summary>
        /// <param name="configurer">The options configurer.</param>
        /// <param name="dependencyResolverAdapter">The dependency resolver adapter to resolve Correlate dependencies with.</param>
        /// <returns>The <see cref="OptionsConfigurer"/> instance.</returns>
        public static OptionsConfigurer EnableCorrelate(this OptionsConfigurer configurer, DependencyResolverAdapter dependencyResolverAdapter)
        {
            if (configurer == null)
            {
                throw new ArgumentNullException(nameof(configurer));
            }

            if (dependencyResolverAdapter == null)
            {
                throw new ArgumentNullException(nameof(dependencyResolverAdapter));
            }

            // Register Correlate steps using custom resolver.
            return(configurer
                   .RegisterSteps(dependencyResolverAdapter)
                   .ConfigurePipeline());
        }
Ejemplo n.º 23
0
        public static void EnableOpenTelemetry(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline = c.Get <IPipeline>();
                var step     = new OutgoingDiagnosticsStep();
                return(new PipelineStepInjector(pipeline).OnSend(step, PipelineRelativePosition.Before,
                                                                 typeof(SerializeOutgoingMessageStep)));
            });

            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline = c.Get <IPipeline>();
                var step     = new IncomingDiagnosticsStep();
                return(new PipelineStepInjector(pipeline).OnReceive(step, PipelineRelativePosition.Before,
                                                                    typeof(DeserializeIncomingMessageStep)));
            });
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Enables idempotent sagas. When enabled, sagas derived from <see cref="IdempotentSaga{TSagaData}"/> can be truly idempotent.
        /// This means that the saga instance stores the IDs of all handled messages, including all outgoing messages send when handling
        /// each incoming message - this way, the saga instance can guard itself against handling the same message twice, while still
        /// preserving externally visible behavior even when a message gets handled more than once.
        /// </summary>
        public static void EnableIdempotentSagas(this OptionsConfigurer configurer)
        {
            configurer.Decorate <IPipeline>(c =>
            {
                var transport = c.Get <ITransport>();
                var pipeline  = c.Get <IPipeline>();

                var incomingStep = new IdempotentSagaIncomingStep(transport);

                var outgoingStep = new IdempotentSagaOutgoingStep();

                var injector = new PipelineStepInjector(pipeline)
                               .OnReceive(incomingStep, PipelineRelativePosition.Before, typeof(DispatchIncomingMessageStep))
                               .OnSend(outgoingStep, PipelineRelativePosition.After, typeof(SendOutgoingMessageStep));

                return(injector);
            });
        }
Ejemplo n.º 25
0
        private static OptionsConfigurer RegisterSteps(this OptionsConfigurer configurer, IResolutionContext?resolver = null)
        {
            configurer.Register(ctx =>
                                new CorrelateOutgoingMessageStep(
                                    (resolver ?? ctx).Get <ICorrelationContextAccessor>(),
                                    (resolver ?? ctx).Get <ICorrelationIdFactory>(),
                                    ctx.Get <IRebusLoggerFactory>()
                                    )
                                );
            configurer.Register(ctx =>
                                new CorrelateIncomingMessageStep(
                                    (resolver ?? ctx).Get <IAsyncCorrelationManager>(),
                                    ctx.Get <IRebusLoggerFactory>()
                                    )
                                );

            return(configurer);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Replaces the worker factory with one based on TPL
        /// </summary>
        public static void UseTplToReceiveMessages(this OptionsConfigurer configurer)
        {
            configurer.Register <IWorkerFactory>(c =>
            {
                var transport     = c.Get <ITransport>();
                var loggerFactory = c.Get <IRebusLoggerFactory>();

                return(new TplWorkerFactory(
                           transport,
                           loggerFactory,
                           c.Get <IPipelineInvoker>(),
                           c.Get <Options>(),
                           c.Get <RebusBus>,
                           c.Get <BusLifetimeEvents>(),
                           c.Get <IBackoffStrategy>()
                           ));
            });
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Enables async/await-based request/reply whereby a request can be sent using the <see cref="SendRequest{TReply}"/> method
        /// which can be awaited for a corresponding reply.
        /// </summary>
        public static void EnableSynchronousRequestReply(this OptionsConfigurer configurer, int replyMaxAgeSeconds = 10)
        {
            configurer.Register(c =>
            {
                var rebusLoggerFactory = c.Get <IRebusLoggerFactory>();
                var asyncTaskFactory   = c.Get <IAsyncTaskFactory>();
                var replyMaxAge        = TimeSpan.FromSeconds(replyMaxAgeSeconds);
                var step = new ReplyHandlerStep(Messages, rebusLoggerFactory, asyncTaskFactory, replyMaxAge);
                return(step);
            });

            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline = c.Get <IPipeline>();
                var step     = c.Get <ReplyHandlerStep>();
                return(new PipelineStepInjector(pipeline)
                       .OnReceive(step, PipelineRelativePosition.Before, typeof(ActivateHandlersStep)));
            });
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Enables message validation for incoming messages using FluentValidation.
        /// <para>
        /// When an incoming message fails to validate, by default it is wrapped in a <see cref="IValidationFailed{TMessage}"/> message and dispatched to handlers implementing this wrapped message type. Use the <paramref name="onFailed"/> builder to configure if messages should be handled differently (f.ex. move to error queue, drop, etc.).
        /// </para>
        /// </summary>
        /// <param name="configurer">The options configurer.</param>
        /// <param name="validatorFactory">The FluentValidation validator factory to resolve message validators from.</param>
        /// <param name="onFailed">A builder to configure how messages should be handled when validation fails.</param>
        public static void ValidateIncomingMessages(this OptionsConfigurer configurer, IValidatorFactory validatorFactory, Action <ValidationConfigurer>?onFailed = null)
        {
            if (configurer is null)
            {
                throw new ArgumentNullException(nameof(configurer));
            }

            if (validatorFactory is null)
            {
                throw new ArgumentNullException(nameof(validatorFactory));
            }

            var opts = new ValidationConfigurer(configurer);

            onFailed?.Invoke(opts);

            configurer.Register(ctx =>
            {
                IRebusLoggerFactory loggerFactory = ctx.Get <IRebusLoggerFactory>();
                return(new ValidateIncomingStep(
                           loggerFactory.GetLogger <ValidateIncomingStep>(),
                           validatorFactory,
                           ctx.Get <IReadOnlyDictionary <Type, IValidationFailedStrategy> >(),
                           // By default, handle as IValidationFailed<>
                           ctx.Get <WrapAsValidationFailed>()
                           ));
            });

            configurer.Decorate <IPipeline>(ctx =>
            {
                IPipeline pipeline   = ctx.Get <IPipeline>();
                var pipelineInjector = new PipelineStepInjector(pipeline);

                ValidateIncomingStep incomingStep = ctx.Get <ValidateIncomingStep>();
                pipelineInjector.OnReceive(
                    incomingStep,
                    PipelineRelativePosition.After,
                    typeof(DeserializeIncomingMessageStep)
                    );

                return(pipelineInjector);
            });
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Propagates the ClaimsPrincipal through the message bus so that its there during message evaluation
        /// </summary>
        public static void AutomaticallyPropagateCurrentClaimsPrincipal(this OptionsConfigurer configurer)
        {
            if (!configurer.Has <IClaimsPrinicpalSerializer>())
            {
                configurer.Register <IClaimsPrinicpalSerializer>(c => new DefaultClaimsPrinicpalSerializer());
            }

            configurer.Decorate <IPipeline>(c =>
            {
                var pipeline     = c.Get <IPipeline>();
                var serializer   = c.Get <IClaimsPrinicpalSerializer>();
                var outgoingStep = new CapturePrincipalInOutgoingMessage(serializer);
                var incomingStep = new RestorePrincipalFromIncomingMessage(serializer);

                return(new PipelineStepInjector(pipeline)
                       .OnSend(outgoingStep, PipelineRelativePosition.After, typeof(AssignTypeHeaderStep))
                       .OnReceive(incomingStep, PipelineRelativePosition.Before, typeof(ActivateHandlersStep)));
            });
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Configures the simple retry strategy, using the specified error queue address and number of delivery attempts
        /// </summary>
        /// <param name="optionsConfigurer">(extension method target)</param>
        /// <param name="errorQueueAddress">Specifies the name of the error queue</param>
        /// <param name="maxDeliveryAttempts">Specifies how many delivery attempts should be made before forwarding a failed message to the error queue</param>
        /// <param name="secondLevelRetriesEnabled">Specifies whether second level retries should be enabled - when enabled, the message will be dispatched wrapped in an <see cref="IFailed{TMessage}"/> after the first <paramref name="maxDeliveryAttempts"/> delivery attempts, allowing a different handler to handle the message. Dispatch of the <see cref="IFailed{TMessage}"/> is subject to the same <paramref name="maxDeliveryAttempts"/> delivery attempts</param>
        /// <param name="errorDetailsHeaderMaxLength">Specifies a MAX length of the error details to be enclosed as the <see cref="Headers.ErrorDetails"/> header. As the enclosed error details can sometimes become very long (especially when using many delivery attempts), depending on the transport's capabilities it might sometimes be necessary to truncate the error details</param>
        /// <param name="errorTrackingMaxAgeMinutes">Specifies the max age of in-mem error trackings, for tracked messages that have not had any activity registered on them.</param>
        public static void SimpleRetryStrategy(this OptionsConfigurer optionsConfigurer,
                                               string errorQueueAddress        = SimpleRetryStrategySettings.DefaultErrorQueueName,
                                               int maxDeliveryAttempts         = SimpleRetryStrategySettings.DefaultNumberOfDeliveryAttempts,
                                               bool secondLevelRetriesEnabled  = false,
                                               int errorDetailsHeaderMaxLength = int.MaxValue,
                                               int errorTrackingMaxAgeMinutes  = SimpleRetryStrategySettings.DefaultErrorTrackingMaxAgeMinutes
                                               )
        {
            if (optionsConfigurer == null)
            {
                throw new ArgumentNullException(nameof(optionsConfigurer));
            }

            optionsConfigurer.Register(c =>
            {
                var settings = new SimpleRetryStrategySettings(
                    errorQueueAddress,
                    maxDeliveryAttempts,
                    secondLevelRetriesEnabled,
                    errorDetailsHeaderMaxLength,
                    errorTrackingMaxAgeMinutes
                    );

                return(settings);
            });

            if (secondLevelRetriesEnabled)
            {
                optionsConfigurer.Decorate <IPipeline>(c =>
                {
                    var pipeline     = c.Get <IPipeline>();
                    var errorTracker = c.Get <IErrorTracker>();

                    var incomingStep = new FailedMessageWrapperStep(errorTracker);
                    var outgoingStep = new VerifyCannotSendFailedMessageWrapperStep();

                    return(new PipelineStepInjector(pipeline)
                           .OnReceive(incomingStep, PipelineRelativePosition.After, typeof(DeserializeIncomingMessageStep))
                           .OnSend(outgoingStep, PipelineRelativePosition.Before, typeof(SerializeOutgoingMessageStep)));
                });
            }
        }