public void SaveChanges(IAggregate aggregate) { var uncommitedChanges = aggregate.GetUncommittedChanges(); if (!uncommitedChanges.Events.Any()) { return; } while (true) { var stream = OpenStream(aggregate.Id, int.MaxValue); var commitEventCount = stream.CommittedEvents.Count; foreach (var @event in uncommitedChanges.Events) { var evnt = @event; var eventMessage = new EventMessage { Body = evnt }; stream.Add(eventMessage); } try { stream.CommitChanges(Guid.NewGuid()); aggregate.ClearUncommittedChanges(); return; } catch (DuplicateCommitException) { stream.ClearChanges(); return; } catch (ConcurrencyException ex) { if (ThrowOnConflict(stream, commitEventCount)) { throw new ConflictingCommandException(ex.Message, ex); } stream.ClearChanges(); } } }
private async Task Save(IAggregate aggregate, string correlationId, string causationId) { var commitHeaders = new Dictionary <string, object>(); var metaData = _environment.GetMetaData().MetaData; foreach (var item in metaData) { commitHeaders[item.Key] = item.Value; } if (!string.IsNullOrEmpty(correlationId)) { commitHeaders[CorrelationIdKey] = correlationId; } if (!string.IsNullOrEmpty(causationId)) { commitHeaders[CausationIdKey] = causationId; } commitHeaders[AggregateClrTypeHeader] = aggregate.GetType().AssemblyQualifiedName; commitHeaders[AggregateIdHeader] = aggregate.Id; _environment.GetSettings <EventStoreSettings>().ModifyHeaders(commitHeaders); var streamName = aggregate.GetStreamName(_environment); var eventStream = aggregate.GetUncommittedChanges(); var newEvents = eventStream.Events.ToList(); var originalVersion = aggregate.Version - newEvents.Count; var versionToExpect = originalVersion == 0 ? ExpectedVersion.Any : originalVersion - 1; while (true) { try { await SaveEventsToStream(streamName, versionToExpect, newEvents, commitHeaders).ConfigureAwait(false); break; } catch (WrongExpectedVersionException ex) { _environment.Log(ex, "Events where added to aggregate with id: {0} since last load. Checking for conflicts and trying again...", LogLevel.Warn, aggregate.Id); } catch (AggregateException ae) { if (!(ae.InnerException is WrongExpectedVersionException)) { throw; } _environment.Log(ae.InnerException, "Events where added to aggregate with id: {0} since last load. Checking for conflicts and trying again...", LogLevel.Warn, aggregate.Id); } var storedEvents = (await LoadEventsFromStream(streamName, versionToExpect < 0 ? 0 : versionToExpect, int.MaxValue).ConfigureAwait(false)).ToList(); var currentVersion = storedEvents.Select(x => x.OriginalEventNumber).OrderByDescending(x => x).FirstOrDefault(); if (_checkConflicts.HasConflicts(newEvents, storedEvents, _environment)) { throw new ConflictingEventException(streamName, versionToExpect, currentVersion); } versionToExpect = currentVersion; } aggregate.ClearUncommittedChanges(); }