Корреляция Masstransit Saga от Natural Key не работает
Я хотел бы использовать уникальный природный ключ вместо встроенного Guid CorrelationId в Masstransit Sagas. Однако это, похоже, не очень работает. Если я дважды отправляю событие Initial с одним и тем же значением ключа, в хранилище создаются две саги - ожидается один экземпляр. Тот же сценарий с использованием CorrelationId создает один экземпляр Saga в репозитории.
Есть идеи, почему второй экземпляр Saga создан с тем же ключом, игнорируя оператор корреляции?
Вот краткий пример с модульным тестом:
[TestFixture]
public class SagaTests
{
[Test]
public void TestSagaInitialization()
{
var testSaga = new TestSaga();
var testSagaRepository = new InMemorySagaRepository<TestSagaState>();
var busControl = Bus.Factory.CreateUsingInMemory(
cfg =>
{
cfg.ReceiveEndpoint("test_queue",
e =>
{
e.StateMachineSaga(testSaga, testSagaRepository);
});
});
busControl.Start();
busControl.Publish(new TestSagaInitEvent() { UniqueNaturalKey = 1 }).Wait();
busControl.Publish(new TestSagaInitEvent() { UniqueNaturalKey = 2 }).Wait();
// Message with same natural key published again
busControl.Publish(new TestSagaInitEvent() { UniqueNaturalKey = 1 }).Wait();
// Wait till all messges consumed
var till = DateTime.Now.AddSeconds(1);
while (DateTime.Now < till) { System.Threading.Thread.Sleep(50); }
busControl.Stop();
var sagaInstances = testSagaRepository.Where(x => x.UniqueNaturalKey == 1).Result.ToList();
Assert.AreEqual(1, sagaInstances.Count, "Dublicate initial events with same Natural Key value must not create new Saga instance");
}
}
public class TestSagaState : Automatonymous.SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public int CurrentState { get; set; }
public long UniqueNaturalKey { get; set; }
}
public class TestSaga : MassTransitStateMachine<TestSagaState>
{
public TestSaga()
{
InstanceState(x => x.CurrentState);
Event(() => SagaInitiated, x => x.CorrelateById(state => state.UniqueNaturalKey, context => context.Message.UniqueNaturalKey)
.SelectId(context => Guid.NewGuid()));
Initially(
When(SagaInitiated)
.Then(context =>
{
context.Instance.UniqueNaturalKey = context.Data.UniqueNaturalKey;
})
.TransitionTo(Initiated)
);
}
public State Initiated { get; private set; }
public Event<TestSagaInitEvent> SagaInitiated { get; private set; }
}
public class TestSagaInitEvent
{
public long UniqueNaturalKey { get; set; }
}