public When_using_EntityFrameworkConcurrencyFail()
        {
            _sagaDbContextFactory = new DelegateSagaDbContextFactory <ChoirStateOptimistic>(
                () => new SagaDbContext <ChoirStateOptimistic, EntityFrameworkChoirStateMap>(SagaDbContextFactoryProvider.GetLocalDbConnectionString()));

            _repository = new Lazy <ISagaRepository <ChoirStateOptimistic> >(() => EntityFrameworkSagaRepository <ChoirStateOptimistic> .CreateOptimistic(_sagaDbContextFactory));
        }
        public static void ConfigureBus(HostBuilderContext context, IServiceCollection services)
        {
            services.AddMassTransit(config =>
            {
                config.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(cfg =>
                {
                    var busConfig = context.Configuration.GetSection("Bus");
                    var host      = cfg.ConfigureHost(busConfig);

                    var connectionString = provider.GetRequiredService <IConfiguration>()["SagaStoreConnection"];

                    var optionsBuilder = new DbContextOptionsBuilder <SagaDbContext <SagaInstance, SagaInstanceMap> >();
                    optionsBuilder.UseSqlServer(connectionString, options => options.CommandTimeout(5));
                    DbContext contextFactory() => new SagaDbContext <SagaInstance, SagaInstanceMap>(optionsBuilder.Options);
                    var repository = EntityFrameworkSagaRepository <SagaInstance> .CreateOptimistic(contextFactory);

                    cfg.ReceiveEndpoint(host, "OrderWorkflow", e =>
                    {
                        e.UseRetry(x =>
                        {
                            x.Handle <DbUpdateConcurrencyException>();
                            // This is the SQLServer error code for duplicate key, if you are using another Relational Db, the code might be different
                            x.Handle <DbUpdateException>(y => y.InnerException is SqlException ex && ex.Number == 2627);
                            x.Interval(5, TimeSpan.FromMilliseconds(100));
                        });
                        e.UseFilter(new OperationContextFilter());
                        e.StateMachineSaga(new OrderSaga(provider.GetRequiredService <ILogger <OrderSaga> >()), repository);
                    });

                    EndpointConvention.Map <CompleteOrder>(new Uri(new Uri(busConfig["Host"]), nameof(CompleteOrder)));
                    EndpointConvention.Map <FailOrder>(new Uri(new Uri(busConfig["Host"]), nameof(FailOrder)));
                    EndpointConvention.Map <Delivery.Commands.PlaceOrder>(new Uri(new Uri(busConfig["Host"]), "CreateDelivery"));

                    contextFactory().Database.EnsureCreated();
                }));
            });

            services.AddSingleton <IHostedService, BusService>();
        }
Esempio n. 3
0
        public static void AddMassTransitWithRabbitMq(this IServiceCollection services, IConfiguration appConfig)
        {
            if (services == null)
            {
                throw new ArgumentNullException("services");
            }

            if (appConfig == null)
            {
                throw new ArgumentNullException("appConfig");
            }

            var cfgSection = appConfig.GetSection("RabbitMqHost");

            if (!cfgSection.Exists())
            {
                throw new InvalidOperationException("Appsettings: 'RabbitMqHost' section is not found");
            }

            services.Configure <RabbitMqHostOptions>(cfgSection);

            var epSection = appConfig.GetSection("MqEndpoints");

            if (!epSection.Exists())
            {
                throw new InvalidOperationException("Appsettings: 'MqEndpoints' section was not found");
            }

            services.Configure <MqEndpointOptions>(epSection);

            services.AddMassTransit(cfg =>
            {
                cfg.AddConsumer <RoutingSlipMetricsConsumer>();
                cfg.AddConsumer <RoutingSlipActivityConsumer>();
                cfg.AddSaga <RoutingSlipState>();
            });

            services.AddSingleton <RoutingSlipStateMachine>();

            services.AddSingleton(svcProv =>
            {
                var fact = svcProv.GetService <ILoggerFactory>();
                return(new RoutingSlipMetrics("Routing Slip", fact.CreateLogger <RoutingSlipMetrics>()));
            });

            services.AddSingleton <ValidateActivityMatrics>();

            services.AddScoped <RoutingSlipMetricsConsumer>(svcProv =>
            {
                var metrics = svcProv.GetService <RoutingSlipMetrics>();
                return(new RoutingSlipMetricsConsumer(metrics));
            });

            services.AddScoped(svcProv =>
            {
                var metrics = svcProv.GetService <ValidateActivityMatrics>();
                var epOpts  = svcProv.GetService <IOptions <MqEndpointOptions> >().Value;
                return(new RoutingSlipActivityConsumer(metrics, epOpts.ActivityMetrics.ActivityName));
            });

            services.AddSingleton(svcProv =>
            {
                var config = svcProv.GetService <IConfiguration>();
                var conStr = config.GetConnectionString("EfCoreRoutingSlip");
                return(new RoutingSlipDbContextFactory(conStr));
            });

            services.AddSingleton <ISagaRepository <RoutingSlipState>, EntityFrameworkSagaRepository <RoutingSlipState> >(svcProv =>
            {
                var ctxFactory = svcProv.GetService <RoutingSlipDbContextFactory>();
                return(EntityFrameworkSagaRepository <RoutingSlipState> .CreateOptimistic(() => ctxFactory.CreateDbContext(Array.Empty <string>())));
            });

            services.AddSingleton(svcProv =>
            {
                var hostOpts   = svcProv.GetService <IOptions <RabbitMqHostOptions> >().Value;
                var epOpts     = svcProv.GetService <IOptions <MqEndpointOptions> >().Value;
                var machine    = svcProv.GetService <RoutingSlipStateMachine>();
                var repository = svcProv.GetService <ISagaRepository <RoutingSlipState> >();

                return(Bus.Factory.CreateUsingRabbitMq(cfg =>
                {
                    var host = cfg.CreateHost(hostOpts);

                    cfg.ReceiveEndpoint(host, epOpts.Metrics.QueueName, e =>
                    {
                        e.PrefetchCount = epOpts.Metrics.PrefetchCount;
                        e.UseRetry(r => r.None());
                        //e.LoadFrom(svcProv);
                        e.Consumer <RoutingSlipMetricsConsumer>(svcProv);
                        e.Consumer <RoutingSlipActivityConsumer>(svcProv);
                    });

                    cfg.ReceiveEndpoint(host, epOpts.ActivityMetrics.QueueName, e =>
                    {
                        e.PrefetchCount = epOpts.ActivityMetrics.PrefetchCount;
                        e.UseRetry(r => r.None());
                    });

                    cfg.ReceiveEndpoint(host, epOpts.Saga.QueueName, e =>
                    {
                        e.UseInMemoryOutbox();
                        e.PrefetchCount = 1;
                        e.UseConcurrencyLimit(1);
                        e.StateMachineSaga(machine, repository);
                    });

                    cfg.UseSerilog();
                }));
            });
        }