Exemple #1
0
        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();
                }
            }
        }
Exemple #2
0
        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();
        }