When appending an event to a stream, if you set the expected version (of the stream) to something other than “Any” it appears to prevent any idempotency checks. The event will be appended to the stream even if it shares the same event ID with an event already in the stream.
In the code below “SerializeToJsonByteEncoded()” is an extension method to deal with JSON-ification and encoding.
This test is successful:
[Test]
public void IdempotencyTest1()
{
Guid eventIdToBeReused = Guid.NewGuid();
object msg = new object();
Dictionary<string, object> metadata = new Dictionary<string, object>();
IEventStoreConnection eventStoreConnection = EventStoreConnection.Create(new IPEndPoint(IPAddress.Loopback, 1113));
eventStoreConnection.ConnectAsync().Wait();
EventData eventData1 = new EventData(eventIdToBeReused, "object", true, msg.SerializeToJsonByteEncoded(), metadata.SerializeToJsonByteEncoded());
eventStoreConnection.AppendToStreamAsync(eventIdToBeReused.ToString("D"), ExpectedVersion.Any, eventData1).Wait();
EventData eventData2 = new EventData(eventIdToBeReused, "object", true, msg.SerializeToJsonByteEncoded(), metadata.SerializeToJsonByteEncoded());
eventStoreConnection.AppendToStreamAsync(eventIdToBeReused.ToString("D"), ExpectedVersion.Any, eventData2).Wait();
StreamEventsSlice streamEventsSlice = eventStoreConnection.ReadStreamEventsForwardAsync(eventIdToBeReused.ToString("D"), 0, 200, false).Result;
Assert.AreEqual(1, streamEventsSlice.Events.Length);
}
The number of events in the stream is 1. The second event was not appended because it has the same event ID as the first.
This test fails:
[Test]
public void IdempotencyTest2()
{
Guid eventIdToBeReused = Guid.NewGuid();
object msg = new object();
Dictionary<string, object> metadata = new Dictionary<string, object>();
IEventStoreConnection eventStoreConnection = EventStoreConnection.Create(new IPEndPoint(IPAddress.Loopback, 1113));
eventStoreConnection.ConnectAsync().Wait();
EventData eventData1 = new EventData(eventIdToBeReused, “object”, true, msg.SerializeToJsonByteEncoded(), metadata.SerializeToJsonByteEncoded());
eventStoreConnection.AppendToStreamAsync(eventIdToBeReused.ToString(“D”), ExpectedVersion.Any, eventData1).Wait();
EventData eventData2 = new EventData(eventIdToBeReused, “object”, true, msg.SerializeToJsonByteEncoded(), metadata.SerializeToJsonByteEncoded());
eventStoreConnection.AppendToStreamAsync(eventIdToBeReused.ToString(“D”), 0, eventData2).Wait();
StreamEventsSlice streamEventsSlice = eventStoreConnection.ReadStreamEventsForwardAsync(eventIdToBeReused.ToString(“D”), 0, 200, false).Result;
Assert.AreEqual(1, streamEventsSlice.Events.Length);
}
The number of events in the stream is 2. The second event is appended even though it has the same event ID as the first. The only difference between the tests is that on the second append the expected version is changed from "ExpectedVersion.Any" to "0".
Having "0" as the expected version is valid because there is one event in the stream (and Event Store uses zero-based indexes).
I would like to set the expected version to guard against concurrency.
Any help?
Thanks,
Callum