Мы используем Masstransit с автоматическим именем и InMemoryRepository для сохранения саги. У нас есть около 3-х конечных автоматов, настроенных и отлично работающих. Недавно мы перешли с InMemoryRepository на EFCore для сохранения. В результате только 1-й сконфигурированный конечный автомат работал безупречно. Остальные все машины состояний даже не входят в событие Initially. Нужна помощь, чтобы понять, правильная реализация или нет. Ниже приведены детали кода:
masstransit statemachine настройка
services.AddMassTransit(x =>
{
x.AddBus(provider => MassTransit.Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host(hostUri, hst =>
{
hst.Username(appSettings.RabbitMQ.Username);
hst.Password(appSettings.RabbitMQ.Password);
});
cfg.ReceiveEndpoint("microservice-response", e =>
{
AddConsumers(e, provider);
e.ConfigureSaga<ServiceRequest1RegisterState>(provider);
e.ConfigureSaga<ServiceRequest1UpdateState>(provider);
e.ConfigureSaga<ServiceRequest1ApproveState>(provider);
});
}));
////x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
//// .InMemoryRepository();
////x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
//// .InMemoryRepository();
////x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
//// .InMemoryRepository();
x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
.EntityFrameworkRepository(r =>
{
r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion
r.AddDbContext<DbContext, ServiceRequest1RegisterStateDbContext>((provider, builder) =>
{
builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
{
m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
m.MigrationsHistoryTable($"__{nameof(ServiceRequest1RegisterStateDbContext)}");
});
});
});
x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
.EntityFrameworkRepository(r =>
{
r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion
r.AddDbContext<DbContext, ServiceRequest1UpdateStateDbContext>((provider, builder) =>
{
builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
{
m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
m.MigrationsHistoryTable($"__{nameof(ServiceRequest1UpdateStateDbContext)}");
});
});
});
x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
.EntityFrameworkRepository(r =>
{
r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion
r.AddDbContext<DbContext, ServiceRequest1ApproveStateDbContext>((provider, builder) =>
{
builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
{
m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
m.MigrationsHistoryTable($"__{nameof(ServiceRequest1ApproveStateDbContext)}");
});
});
});
});
services.AddSingleton<IHostedService, MassTransitBusService>();
DBContext для всех трех машин состояний выглядит так, как показано ниже.
public class ServiceRequest1ApproveStateDbContext : SagaDbContext
{
public ServiceRequest1ApproveStateDbContext(DbContextOptions<ServiceRequest1ApproveStateDbContext> options)
: base(options)
{
}
/// <summary>
/// Gets the configurations.
/// </summary>
protected override IEnumerable<ISagaClassMap> Configurations
{
get { yield return new ServiceRequest1ApproveStateMap(); }
}
}
Карта штата ниже
public class ServiceRequest1ApproveStateMap : SagaClassMap<ServiceRequest1ApproveState>
{
protected override void Configure(EntityTypeBuilder<ServiceRequest1ApproveState> entity, ModelBuilder model)
{
entity.Property(x => x.CurrentState).HasMaxLength(64);
entity.Property(x => x.Id);
entity.Property(x => x.ServiceId);
entity.Property(x => x.ReadyEventStatus);
}
}
Из приведенного выше кода отлично работает только ServiceRequest1RegisterStateMachine, остальные машины состояний даже не входят в исходное состояние. Я могу подтвердить, что все миграции выполняются заранее, и все эти statemachine все работают нормально индивидуально, когда существует только 1 конфигурация репозитория, то есть, если только конфигурация репозитория для ServiceRequest1ApproveStateMachine, этот конечный автомат работает нормально. Но если все 3 конфигурации репо существуют, то работает только 1-й. Мне нужно руководство по правильной реализации сохранения саги с помощью EFCore. Стоит ли мне попробовать реализовать использование одного dbcontext, как указано в документации masstransit (https://masstransit-project.com/usage/sagas/efcore.html).
<DbContext, ServiceRequest1RegisterStateDbContext>
- выньтеDbContext,
и просто зарегистрируйте контекст db состояния для каждого из них. Приведение его обратно к DbContext приводит к регистрации одного контейнера для этого типа службы. - person Chris Patterson   schedule 30.10.2020void AddDbContext<TContext, TImplementation>(Action<IConfigurationServiceProvider, DbContextOptionsBuilder<TImplementation>> optionsAction = null) where TContext : DbContext
Если есть другой способ его реализации, не могли бы вы объяснить, что - person Rahul Jacob   schedule 30.10.2020AddDbContext
наExistingDbContext()
помогло. Для подтверждения необходимо провести раунд тестирования. Кроме того, преобразование было выполнено на основе примеров кода, представленных в документации по постоянству EFCore. Как вы думаете, эта реализация все еще в силе? - person Rahul Jacob   schedule 02.11.2020