public async Task <long> SaveAsync(AggregateBase aggregate, params KeyValuePair <string, string>[] extraHeaders) { var streamName = aggregate.Identifier.ToString(); var pendingEvents = aggregate.GetPendingEvents(); var originalVersion = aggregate.Version - pendingEvents.Count; try { WriteResult result; var commitHeaders = CreateCommitHeaders(aggregate, extraHeaders); var eventsToSave = pendingEvents.Select(x => ToEventData(Guid.NewGuid(), x, commitHeaders)); var eventBatches = GetEventBatches(eventsToSave); if (eventBatches.Count == 1) { result = await _eventStoreConnection.AppendToStreamAsync(streamName, originalVersion, eventBatches[0]); } else { // If we have more events to save than can be done in one batch according to the WritePageSize, then we need to save them in a transaction to ensure atomicity using (var transaction = await _eventStoreConnection.StartTransactionAsync(streamName, originalVersion)) { foreach (var batch in eventBatches) { await transaction.WriteAsync(batch); } result = await transaction.CommitAsync(); } } aggregate.ClearPendingEvents(); return(result.NextExpectedVersion); } catch (Exception ex) { _logger.LogError($"Failed to write events for stream: {streamName}.", ex); ExceptionDispatchInfo.Capture(ex).Throw(); } return(originalVersion + 1); }
private static IDictionary <string, string> CreateCommitHeaders(AggregateBase aggregate, KeyValuePair <string, string>[] extraHeaders) { var commitId = Guid.NewGuid(); var commitHeaders = new Dictionary <string, string> { { MetadataKeys.CommitIdHeader, commitId.ToString() }, { MetadataKeys.AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }, { MetadataKeys.UserIdentityHeader, Thread.CurrentThread.Name }, // TODO - was Thread.CurrentPrincipal?.Identity?.Name { MetadataKeys.ServerNameHeader, "DefaultServerNameHEader" }, // TODO - was Environment.MachineName { MetadataKeys.ServerClockHeader, DateTime.UtcNow.ToString("o") } }; foreach (var extraHeader in extraHeaders) { commitHeaders[extraHeader.Key] = extraHeader.Value; } return(commitHeaders); }