Hi,
I have run into an issue where our application was hanging on some operations.
When hanging we would see something similar to this from EventStore.SingleNode.exe:
[11928,11,09:10:01.937] [09:10:01.937: N127.0.0.1:51427, L127.0.0.1:1113, {8563e2e4-7cbe-421e-afc4-0687bd4ab5eb}]:
Received bytes: 211, Sent bytes: 124
Send calls: 4, callbacks: 4
Receive calls: 4, callbacks: 3
Close reason: [Success] HEARTBEAT TIMEOUT at msgNum 3
[11928,11,09:10:01.937] Connection ‘external-normal’ [127.0.0.1:51427, {8563e2e4-7cbe-421e-afc4-0687bd4ab5eb}] closed: Success.
After some experimentation I have come up with a minimal test case that exhibits this behavior. The key to the error seems to be synchronous calls inside of an async block mixed with await calls. The test below will hang on this line:
connection.ReadStreamEventsForward(“NonExistantStream1”, 0, 100, false);
I have replicated this using EventStore 2.0.1 for .Net.
My test was .Net 4.5 using the 2.0.2 EventStore.Client package.
[TestFixture]
public class EventStoreClientLockup
{
private readonly EventData _eventData =
new EventData(eventId: Guid.NewGuid(),
type: “ignore”,
isJson: false,
data: null,
metadata: null);
[Test]
public void EventstoreLockupTest()
{
var userCredentials = new UserCredentials(“admin”, “changeit”);
ConnectionSettings connectionSettings =
ConnectionSettings.Create()
.SetDefaultUserCredentials(userCredentials)
.KeepReconnecting()
.KeepRetrying();
var ipAddress = IPAddress.Parse(“127.0.0.1”);
var ipEndPoint = new IPEndPoint(ipAddress, 1113);
var connection = EventStoreConnection.Create(connectionSettings, ipEndPoint);
connection.Connect();
Lockup(connection).Wait();
}
public async Task Lockup(IEventStoreConnection connection)
{
// await the first read
await connection.ReadStreamEventsForwardAsync(“NonExistantStream1”, 0, 100, false);
string randomStreamIdToWriteTo = “LockTestStream-” + Guid.NewGuid().ToString();
// await a random write
await connection.AppendToStreamAsync(randomStreamIdToWriteTo, -1, _eventData);
// this read would succeed if awaited but not if called synchronously
// instead the code will hang
connection.ReadStreamEventsForward(“NonExistantStream1”, 0, 100, false);
}
}
Now that I understand the issue we should be able to avoid it in the future but from my understanding of the way async and await works this should not cause problems even if the code is a sub-optimal.
cheers
Andrew