使用自动命名时状态机不一致
State machine inconsistency while using Automatonymous
我是微服务的新手,使用自动命名的公共交通工具。目前我的状态机在执行时显示不一致。 Initially 中的代码按预期工作,但控制流在第二个事件完成后不执行 During 中的代码。这只发生在 1 个状态机上,所有其他状态机都按预期工作。当我将 During 中的代码移动到 Initially(最初的注释代码)时,它工作正常。
下面是我的状态机的样子:
InstanceState(x => x.CurrentState);
Event(() => ServiceRequest1Registered, x => x.CorrelateById(context => context.Message.AggregateId));
Event(() => ServiceRequest2Registered, x => x.CorrelateById(context => context.Message.AggregateId));
Initially(
When(ServiceRequest1Registered,
context => context.Data.ServiceTypeId != (int)ServiceType.IndividualService)
.Then(context => _logger.LogInformation($"When Initially, ServiceRequest1Registered and wrong condition"))
.Finalize(),
When(ServiceRequest1Registered,
context => context.Data.ServiceTypeId == (int)ServiceType.IndividualService)
.Then(context => _logger.LogInformation($"When Initially and ServiceRequest1Registered"))
.Send(url,
x => new ServiceRequest2RegisteredCommand
{
InitiatedBy = x.Instance.InitiatedBy,
ServiceRequestId = x.Instance.Id,
Schedules = _mapper.Map<List<ScheduleDTO>>(x.Data.ServiceRequest1Schedules)
})
.Then(context => _logger.LogInformation($"Send ServiceRequest2RegisteredCommand")
.TransitionTo(ServiceRequest1RegisterCompleted)
////When(ServiceRequest2Registered)
////.Then(context => _logger.LogInformation($"When ServiceRequestRegister2Completed and ServiceRequest2Registered"))
//// .Finalize())
);
During(ServiceRequestRegister1Completed,
Ignore(ServiceRequest1Registered),
When(ServiceRequest2Registered)
.Then(context => _logger.LogInformation($"When ServiceRequestRegister1Completed and ServiceRequest2Registered"))
.Finalize());
SetCompleted(async instance =>
{
State<ServiceRequestState> currentState = await this.GetState(instance);
_logger.LogInformation($"Final state : {ServiceRequest2Registered.Equals(currentState)}");
return ServiceRequest2Registered.Equals(currentState);
});
下面使用 RabbitMQ 的公共交通系统设置
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 =>
{
e.UseInMemoryOutbox();
AddConsumers(e, provider);
e.ConfigureSaga<ServiceRequestRegisterState>(provider);
});
}));
x.AddSagaStateMachine<ServiceRequestRegisterStateMachine, ServiceRequestRegisterState>()
.InMemoryRepository();
});
services.AddSingleton<IHostedService, MassTransitBusService>();
我尝试了 SetCompleted 和 SetCompletedWhenFinalized()。我们使用 Masstransit v6.2.1 和 automatonymous v4.2.1。需要帮助来确定我们遇到此问题的原因或实施是否存在问题?
如果您正在观察在 Initially 事件完成之前传送到状态机的事件,您应该将 UseInMemoryOutbox
添加到接收端点(在状态机配置之前)。这将延迟出站消息,直到状态机实例被持久化。我怀疑您正在使用乐观锁定策略,并且第二个事件在初始事件持久性完成之前到达。
第二个事件的关联 ID 不同。这导致第 2 个事件最初发生。更正了该问题,其余一切正常。确保状态机中的所有事件都具有相同的 correlationid,并且此 correlationid 在编排期间不会更改。
我是微服务的新手,使用自动命名的公共交通工具。目前我的状态机在执行时显示不一致。 Initially 中的代码按预期工作,但控制流在第二个事件完成后不执行 During 中的代码。这只发生在 1 个状态机上,所有其他状态机都按预期工作。当我将 During 中的代码移动到 Initially(最初的注释代码)时,它工作正常。 下面是我的状态机的样子:
InstanceState(x => x.CurrentState);
Event(() => ServiceRequest1Registered, x => x.CorrelateById(context => context.Message.AggregateId));
Event(() => ServiceRequest2Registered, x => x.CorrelateById(context => context.Message.AggregateId));
Initially(
When(ServiceRequest1Registered,
context => context.Data.ServiceTypeId != (int)ServiceType.IndividualService)
.Then(context => _logger.LogInformation($"When Initially, ServiceRequest1Registered and wrong condition"))
.Finalize(),
When(ServiceRequest1Registered,
context => context.Data.ServiceTypeId == (int)ServiceType.IndividualService)
.Then(context => _logger.LogInformation($"When Initially and ServiceRequest1Registered"))
.Send(url,
x => new ServiceRequest2RegisteredCommand
{
InitiatedBy = x.Instance.InitiatedBy,
ServiceRequestId = x.Instance.Id,
Schedules = _mapper.Map<List<ScheduleDTO>>(x.Data.ServiceRequest1Schedules)
})
.Then(context => _logger.LogInformation($"Send ServiceRequest2RegisteredCommand")
.TransitionTo(ServiceRequest1RegisterCompleted)
////When(ServiceRequest2Registered)
////.Then(context => _logger.LogInformation($"When ServiceRequestRegister2Completed and ServiceRequest2Registered"))
//// .Finalize())
);
During(ServiceRequestRegister1Completed,
Ignore(ServiceRequest1Registered),
When(ServiceRequest2Registered)
.Then(context => _logger.LogInformation($"When ServiceRequestRegister1Completed and ServiceRequest2Registered"))
.Finalize());
SetCompleted(async instance =>
{
State<ServiceRequestState> currentState = await this.GetState(instance);
_logger.LogInformation($"Final state : {ServiceRequest2Registered.Equals(currentState)}");
return ServiceRequest2Registered.Equals(currentState);
});
下面使用 RabbitMQ 的公共交通系统设置
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 =>
{
e.UseInMemoryOutbox();
AddConsumers(e, provider);
e.ConfigureSaga<ServiceRequestRegisterState>(provider);
});
}));
x.AddSagaStateMachine<ServiceRequestRegisterStateMachine, ServiceRequestRegisterState>()
.InMemoryRepository();
});
services.AddSingleton<IHostedService, MassTransitBusService>();
我尝试了 SetCompleted 和 SetCompletedWhenFinalized()。我们使用 Masstransit v6.2.1 和 automatonymous v4.2.1。需要帮助来确定我们遇到此问题的原因或实施是否存在问题?
如果您正在观察在 Initially 事件完成之前传送到状态机的事件,您应该将 UseInMemoryOutbox
添加到接收端点(在状态机配置之前)。这将延迟出站消息,直到状态机实例被持久化。我怀疑您正在使用乐观锁定策略,并且第二个事件在初始事件持久性完成之前到达。
第二个事件的关联 ID 不同。这导致第 2 个事件最初发生。更正了该问题,其余一切正常。确保状态机中的所有事件都具有相同的 correlationid,并且此 correlationid 在编排期间不会更改。