I am not sure if this is related to the same issue but I am getting
Test method PortfolioValue.EventStore.Tests.EventStoreRepositoryTests.EventStoreRepository_SaveAndLoadEvents_ShouldPersistAndRetrieveEvents threw exception:
Grpc.Core.RpcException: Status(StatusCode="DeadlineExceeded", Detail=""
I am running docker for event store
#https://developers.eventstore.com/server/v23.10/quick-start/installation.html#use-docker-compose
eventstore.db:
image: eventstore/eventstore:23.10.0-bookworm-slim
container_name: eventstore.db
environment:
- EVENTSTORE_CLUSTER_SIZE=1
- EVENTSTORE_RUN_PROJECTIONS=All
- EVENTSTORE_START_STANDARD_PROJECTIONS=true
- EVENTSTORE_EXT_TCP_PORT=1113
- EVENTSTORE_HTTP_PORT=2113
- EVENTSTORE_INSECURE=true
- EVENTSTORE_ENABLE_EXTERNAL_TCP=true
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true
ports:
- "1113:1113"
- "2113:2113"
volumes:
- type: volume
source: eventstore-volume-data
target: /var/lib/eventstore
- type: volume
source: eventstore-volume-logs
target: /var/log/eventstore
My wrapper repository is
public class EventStoreRepository : IEventStore
{
private readonly EventStoreClient _client;
private const string EventClrTypeHeader = "EventClrTypeName";
public EventStoreRepository(string connectionString)
{
var settings = EventStoreClientSettings.Create(connectionString);
settings.ConnectivitySettings = new EventStoreClientConnectivitySettings
{
KeepAliveInterval = TimeSpan.FromSeconds(5),
KeepAliveTimeout = TimeSpan.FromSeconds(6000),
Insecure = true, // Disable TLS
TlsVerifyCert = false
};
settings.ChannelCredentials = ChannelCredentials.Insecure;
_client = new EventStoreClient(settings);
}
public IEnumerable<Event> LoadEventsFor<TAggregate>(Guid id)
{
var streamName = GetStreamName<TAggregate>(id);
var result = _client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start);
var resolvedEvents = new List<ResolvedEvent>();
try
{
// Synchronously wait for the asynchronous read operation to complete
resolvedEvents = result.ToListAsync().GetAwaiter().GetResult();
}
catch (Exception ex) when (IsStreamNotFoundException(ex))
{
// Stream does not exist
return Enumerable.Empty<Event>();
}
if (!resolvedEvents.Any())
{
// Stream exists but has no events
return Enumerable.Empty<Event>();
}
var events = resolvedEvents.Select(re => DeserializeEvent(re.Event));
return events;
}
public void SaveEventsFor<TAggregate>(Guid id, int eventsLoaded, IEnumerable<Event> newEvents)
{
var streamName = GetStreamName<TAggregate>(id);
var eventData = newEvents.Select(e => ToEventData(e));
if (eventsLoaded == 0)
{
// Synchronously wait for the asynchronous append operation to complete
_client.AppendToStreamAsync(streamName, StreamState.NoStream, eventData)
.GetAwaiter().GetResult();
}
else
{
var expectedRevision = StreamRevision.FromInt64(eventsLoaded - 1);
_client.AppendToStreamAsync(streamName, expectedRevision, eventData)
.GetAwaiter().GetResult();
}
}
public IEnumerable<Event> GetAllEvents()
{
var result = _client.ReadAllAsync(Direction.Forwards, Position.Start);
// Synchronously wait for the asynchronous read operation to complete
var resolvedEvents = result.ToListAsync().GetAwaiter().GetResult();
var events = resolvedEvents.Select(re => DeserializeEvent(re.Event));
return events;
}
private string GetStreamName<TAggregate>(Guid id)
{
return $"{typeof(TAggregate).Name}-{id}";
}
private Event DeserializeEvent(EventRecord eventRecord)
{
var metadataJson = Encoding.UTF8.GetString(eventRecord.Metadata.ToArray());
var metadata = JsonSerializer.Deserialize<Dictionary<string, string>>(metadataJson);
var eventClrTypeName = metadata[EventClrTypeHeader];
var eventType = Type.GetType(eventClrTypeName);
if (eventType == null)
throw new InvalidOperationException($"Unable to find type {eventClrTypeName}");
var dataJson = Encoding.UTF8.GetString(eventRecord.Data.ToArray());
var ev = JsonSerializer.Deserialize(dataJson, eventType) as Event;
return ev;
}
private EventData ToEventData(Event evnt)
{
var data = JsonSerializer.SerializeToUtf8Bytes(evnt);
var metadata = new Dictionary<string, string>
{
{ EventClrTypeHeader, evnt.GetType().AssemblyQualifiedName }
};
var metadataBytes = JsonSerializer.SerializeToUtf8Bytes(metadata);
var eventData = new EventData(
Uuid.NewUuid(),
evnt.GetType().Name,
data,
metadataBytes
);
return eventData;
}
private bool IsStreamNotFoundException(Exception ex)
{
// Adjust this method based on how exceptions are thrown in your version of the client
return ex is StreamNotFoundException ||
ex.InnerException is StreamNotFoundException;
}
}
and finally the test class I try to run that is causing the error
[TestClass]
public class EventStoreRepositoryTests
{
private string ConnectionString = $"esdb://admin:changeit@localhost:2113?tls=false&tlsVerifyCert=false";
private IEventStore eventStore;
[TestInitialize]
public void TestInit()
{
this.eventStore = new EventStoreRepository(ConnectionString);
}
[TestMethod]
public void EventStoreRepository_SaveAndLoadEvents_ShouldPersistAndRetrieveEvents()
{
// Arrange
var aggregateId = Guid.NewGuid();
var eventsLoaded = 0; // No events loaded initially
var newEvents = new List<Event>
{
new DealFxRateCapturedEvent(
aggregateId,
DateTime.Today,
new Rate(1 * Identifier.Currency("EUR"), 1.23M * Identifier.Currency("USD")))
};
// Act
// Save events to the event store
this.eventStore.SaveEventsFor<DealAggregate>(aggregateId, eventsLoaded, newEvents);
// Load events from the event store
var loadedEvents = this.eventStore.LoadEventsFor<DealAggregate>(aggregateId).ToList();
// Assert
Assert.AreEqual(newEvents.Count, loadedEvents.Count, "The number of loaded events should match the number of saved events.");
// Compare event data
for (int i = 0; i < newEvents.Count; i++)
{
var savedEvent = newEvents[i];
var loadedEvent = loadedEvents[i];
Assert.AreEqual(savedEvent.GetType(), loadedEvent.GetType(), $"Event types should match at index {i}.");
// Cast to specific event type
var savedDealEvent = savedEvent as DealFxRateCapturedEvent;
var loadedDealEvent = loadedEvent as DealFxRateCapturedEvent;
Assert.IsNotNull(savedDealEvent);
Assert.IsNotNull(loadedDealEvent);
// Compare properties
Assert.AreEqual(savedDealEvent.Id, loadedDealEvent.Id, "Event IDs should match.");
//Assert.AreEqual(savedDealEvent.DateTime, loadedDealEvent.DateTime, "Capture dates should match.");
Assert.AreEqual(savedDealEvent.FxRate, loadedDealEvent.FxRate, "Rates should match.");
}
}
}
The documentation seems a bit fragmented and although I’ve looked at the .net samples, I couldn’t get this work…
Thanks for any tips, pointers, or suggestions…