コード例 #1
0
        public void Save(IAggregate aggregate)
        {
            var commitId = Guid.NewGuid();
            var events   = aggregate.GetUncommittedEvents().ToArray();

            if (events.Any() == false)
            {
                return;
            }
            var streamName      = GetStreamName(aggregate.GetType(), aggregate.Id);
            var originalVersion = aggregate.Version - events.Count();
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var commitHeaders   = new Dictionary <string, object>
            {
                { "CommitId", commitId },
                { "AggregateClrType", aggregate.GetType().AssemblyQualifiedName }
            };
            var eventsToSave = events.Select(e => e.ToEventData(commitHeaders)).ToList();

            _connection.AppendToStreamAsync(streamName, expectedVersion, eventsToSave).Wait();
            aggregate.ClearUncommittedEvents();

            foreach (var evento in events)
            {
                if (evento.GetType().ToString().Equals("CantidadIncrementada"))
                {
                    new HandlerCantidadIncrementada().Hanlder((CantidadIncrementada)evento);
                }
                else if (evento.GetType().ToString().Equals("CantidadDecrementada"))
                {
                    new HandlerCantidadDecrementada().Hanlder((CantidadDecrementada)evento);
                }
            }
        }
コード例 #2
0
        public void Store(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commit = new Commit
            {
                CommitId    = commitId,
                AggregateId = aggregate.Id,
                CommitStamp = DateTimeOffset.UtcNow
            };


            using (var session = string.IsNullOrWhiteSpace(_databaseName)
                ? _store.OpenSession()
                : _store.OpenSession(_databaseName))
            {
                session.Advanced.UseOptimisticConcurrency         = true;
                session.Advanced.AllowNonAuthoritativeInformation = false;

                var stream = session.Load <EventStream>(aggregate.Id.ToStringId <EventStream>());
                if (stream == null)
                {
                    stream = new EventStream
                    {
                        Id            = aggregate.Id.ToStringId <EventStream>(),
                        AggregateType = aggregate.GetType().FullName
                    };
                    session.Store(stream);
                }

                commit.CommitSequence = stream.Commits.Count + 1;
                commit.Events         = aggregate.GetUncommittedEvents()
                                        .Cast <object>()
                                        .Select(x => new Event {
                    Body = x, Headers = PrepareHeaders(updateHeaders)
                })
                                        .ToList();

                stream.Version  = aggregate.Version;
                stream.Snapshot = aggregate;
                stream.Commits.Add(commitId, commit);

                //pre-commit hooks
                if (_pipelineHooks.All(hook => hook.PreCommit(commit)))
                {
                    try
                    {
                        session.SaveChanges();
                        aggregate.ClearUncommittedEvents();
                    }
                    catch (Exception exception)
                    {
                        throw;
                    }
                }
            }
            //post commit hooks
            foreach (var hook in _pipelineHooks)
            {
                hook.PostCommit(commit, _databaseName);
            }
        }
コード例 #3
0
        public async Task SaveAsync(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { this._aggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = this._aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var eventsToSave    = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();

            if (eventsToSave.Count < WritePageSize)
            {
                await this._eventDataFactory.AppendToStreamAsync(aggregate, expectedVersion, eventsToSave);
            }
            else
            {
                //TODO
            }

            aggregate.ClearUncommittedEvents();
        }
コード例 #4
0
        public OrderedEventPayload[] Save(IAggregate aggregate)
        {
            var events = aggregate.GetUncommittedEvents().ToArray();

            if (events.Any() == false)
            {
                return new OrderedEventPayload[] { }
            }
            ;                                         // Nothing to save

            var aggregateType = aggregate.GetType().Name;

            var originalVersion = aggregate.Version - events.Count() + 1;

            var eventsToSave = events
                               .Select(e => e.ToEventData(aggregateType, aggregate.Id, originalVersion++))
                               .ToArray();

            var storedAggregateVersion = _eventRepository.GetVersionByAggregateId(aggregate.Id);

            if (storedAggregateVersion.HasValue && storedAggregateVersion >= originalVersion)
            {
                throw new Exception("Concurrency exception");
            }

            var orderedEvents = _eventRepository.SaveEvents(eventsToSave);

            aggregate.ClearUncommittedEvents();

            return(orderedEvents);
        }
コード例 #5
0
        private IEventStream PrepareStream(string bucketId, IAggregate aggregate, Dictionary <string, object> headers)
        {
            IEventStream stream;
            var          streamId = bucketId + "+" + aggregate.Id;

            if (!_streams.TryGetValue(streamId, out stream))
            {
                _streams[streamId] = stream = _eventStore.CreateStream(bucketId, aggregate.Id);
            }

            foreach (var item in headers)
            {
                stream.UncommittedHeaders[item.Key] = item.Value;
            }

            aggregate.GetUncommittedEvents()
            .Cast <object>()
            .Where(x => x != null)             // Don't persist any null events.
            .Select(x => new EventMessage {
                Body = x
            })
            .ToList()
            .ForEach(stream.Add);

            return(stream);
        }
コード例 #6
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            EnsureConnected();

            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = aggregate.Id;
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? -1 : originalVersion;

            expectedVersion--;

            var transaction = _eventStoreConnection.StartTransaction(streamName, expectedVersion);

            var preparedEvents = _adapter.PrepareEvents(newEvents, commitHeaders).ToList();

            var position = 0;

            while (position < preparedEvents.Count)
            {
                var pageEvents = preparedEvents.Skip(position).Take(WritePageSize);
                transaction.Write(pageEvents);
                position += WritePageSize;
            }

            transaction.Commit();
        }
コード例 #7
0
        private static void ExtractEvents(IAggregate aggregate, out List <Event> eventsToSave, out List <Event> snapshotsToSave, out int version)
        {
            eventsToSave    = new List <Event>();
            snapshotsToSave = new List <Event>();

            var allEvents = aggregate
                            .GetUncommittedEvents()
                            .ToArray();

            var numberOfNonSnapshotEvents = allEvents
                                            .Count(x => !(x is SnapshotOffer));

            var aggregateType = aggregate.GetType().Name;

            version = aggregate.Version - numberOfNonSnapshotEvents + 1;

            foreach (var @event in allEvents)
            {
                // A snapshot offer has the same "version" as the last events it covers.
                // So we do not increment the version.
                if (@event is SnapshotOffer offer)
                {
                    snapshotsToSave.Add(@event.ToEventData(aggregateType, aggregate.Id, offer.Version));
                }
                else
                {
                    eventsToSave.Add(@event.ToEventData(aggregateType, aggregate.Id, version++));
                }
            }
        }
コード例 #8
0
        private IEventStream PrepareStream(IAggregate aggregate, Dictionary <string, object> headers)
        {
            IEventStream stream;

            if (!this.streams.TryGetValue(aggregate.Id, out stream))
            {
                this.streams[aggregate.Id] = stream = this.eventStore.CreateStream(aggregate.Id);
            }

            foreach (var item in headers)
            {
                stream.UncommittedHeaders[item.Key] = item.Value;
            }

            aggregate.GetUncommittedEvents()
            .Cast <object>()
            .Select(x => new EventMessage {
                Body = x
            })
            .ToList()
            .ForEach(stream.Add);

            aggregate.ClearUncommittedEvents();

            return(stream);
        }
コード例 #9
0
        public static TEvent GetEvent <TEvent>(this IAggregate aggregate) where TEvent : DomainEvent
        {
            var @event = aggregate.GetUncommittedEvents().OfType <TEvent>().FirstOrDefault();

            if (@event == null)
            {
                throw new CannotFindRequestedEventException();
            }
            return(@event);
        }
コード例 #10
0
 static void OnAggregateSaved(CommandHandlerBase sender, IAggregate aggr, DomainCommand by)
 {
     if (by != null && aggr != null)
     {
         Console.WriteLine("[AGGR] {0} -> {1} -> {2}",
                           by.GetType().FullName,
                           aggr.GetType().FullName,
                           string.Join(", ", aggr.GetUncommittedEvents().OfType <object>().Select(e => e.GetType().FullName)));
     }
 }
コード例 #11
0
 protected virtual void Save(IAggregate aggr, DomainEvent by)
 {
     foreach (DomainEvent evt in aggr.GetUncommittedEvents())
     {
         if (!evt.TenantId.HasValue) evt.TenantId = @by.TenantId;
         if (!evt.IssuedBy.HasValue) evt.IssuedBy = @by.IssuedBy;
         if (!evt.SagaId.HasValue) evt.SagaId = @by.SagaId;
         evt.Version = aggr.Version;
     }
     repo.Save(aggr, Guid.NewGuid());
 }
コード例 #12
0
 protected virtual void Save(IAggregate aggr, DomainCommand by, string bucketId)
 {
     if (OnSavedHook != null) OnSavedHook(this, aggr, by);
     foreach (DomainEvent evt in aggr.GetUncommittedEvents())
     {
         if (!evt.TenantId.HasValue) evt.TenantId = @by.TenantId;
         if (!evt.IssuedBy.HasValue) evt.IssuedBy = @by.IssuedBy;
         if (!evt.SagaId.HasValue) evt.SagaId = @by.SagaId;
         evt.Version = aggr.Version;
     }
     repo.Save(bucketId, aggr, @by.CommitId);
 }
コード例 #13
0
        public async void Save(IAggregate aggregate, Guid commitId, IDictionary <string, object> updateHeaders = null)
        {
            // standard data for metadata portion of persisted event
            var commitHeaders = new Dictionary <string, object>
            {
                // handy tracking id
                { CommitIdHeader, commitId },
                // type of aggregate being persisted
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            // add extra data to metadata portion of presisted event
            commitHeaders = (updateHeaders ?? new Dictionary <string, object>())
                            .Concat(commitHeaders)
                            .GroupBy(d => d.Key)
                            .ToDictionary(d => d.Key, d => d.First().Value);

            // streamname is created by func, by default agg type concat to agg id
            var streamName = _aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            // get all uncommitted events
            var newEvents = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            // process events so they fit the expectations of GES
            var eventsToSave = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();
            // calculate the expected version of the agg root in event store to detirmine if concurrency conflict
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;

            // if numberr of events to save is small enough it can happen in one call
            if (eventsToSave.Count < WritePageSize)
            {
                await _eventStoreConnection.AppendToStreamAsync(streamName, expectedVersion, eventsToSave);
            }
            // otherwise batch events and start transaction
            else
            {
                var transaction = await _eventStoreConnection.StartTransactionAsync(streamName, expectedVersion);

                var position = 0;
                while (position < eventsToSave.Count)
                {
                    var pageEvents = eventsToSave.Skip(position).Take(WritePageSize);
                    await transaction.WriteAsync(pageEvents);

                    position += WritePageSize;
                }

                await transaction.CommitAsync();
            }

            aggregate.ClearUncommittedEvents();
        }
コード例 #14
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { COMMIT_ID_HEADER, commitId },
                { AGGREGATE_CLR_TYPE_HEADER, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = m_AggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion;
            var eventsToSave    = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();


            var transaction = m_EventStoreConnection.StartTransaction(streamName, expectedVersion);

            try
            {
                if (eventsToSave.Count < WRITE_PAGE_SIZE)
                {
                    transaction.Write(eventsToSave);
                }
                else
                {
                    var position = 0;
                    while (position < eventsToSave.Count)
                    {
                        var pageEvents = eventsToSave.Skip(position).Take(WRITE_PAGE_SIZE);
                        transaction.Write(pageEvents);
                        position += WRITE_PAGE_SIZE;
                    }
                }
                //TODO: not prod code. Need to arrange serialization, data saved to ES should be same as sent to queue
                foreach (var @event in newEvents)
                {
                    m_EventsPublisher.PublishEvent(@event);
                }
                transaction.Commit();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //TODO:logging
                transaction.Rollback();
            }
            aggregate.ClearUncommittedEvents();
        }
コード例 #15
0
        public Task Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            Events = aggregate.GetUncommittedEvents().Cast <DomainEvent>();

            var originalVersion = aggregate.Version - Events.Count();
            var expectedVersion = originalVersion + 1;

            if (aggregate.Version == expectedVersion)
            {
                return(Task.CompletedTask);
            }

            throw new Exception($"Aggregate has a wrong Version. Expected: {expectedVersion} - Current: {aggregate.Version}");
        }
コード例 #16
0
        public void TrackEvents(IAggregate aggregate)
        {
            var evt = new EventTelemetry
            {
                Name = aggregate.GetType().Name
            };

            foreach (var @event in aggregate.GetUncommittedEvents())
            {
                evt.Properties.Add("EventType", @event.GetType().Name);
            }

            _telemetryClient.TrackEvent(evt);
        }
コード例 #17
0
        public void Save(IAggregate aggregate)
        {
            //Open file stream
            var aggregateName = aggregate.GetType().Name;

            string aggregateFileName = string.Format("{0}-{1}.evt", aggregateName, aggregate.Id);

            var pathToFile = Path.Combine(_path, aggregateFileName);

            var uncommittedEvents = aggregate.GetUncommittedEvents();
            foreach (var uncommittedEvent in uncommittedEvents)
            {
                var serializeObject = JsonConvert.SerializeObject(uncommittedEvent);
                File.AppendAllText(pathToFile, serializeObject);
            }
        }
コード例 #18
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = _aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var eventsToSave    = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();

            if (eventsToSave.Count < WritePageSize)
            {
                _eventStoreConnection.AppendToStreamAsync(streamName, expectedVersion, eventsToSave).Wait();
            }
            else
            {
                var transaction = _eventStoreConnection.StartTransactionAsync(streamName, expectedVersion).Result;

                var position = 0;
                while (position < eventsToSave.Count)
                {
                    var pageEvents = eventsToSave.Skip(position).Take(WritePageSize);
                    transaction.WriteAsync(pageEvents).Wait();
                    position += WritePageSize;
                }

                transaction.CommitAsync().Wait();
            }
            if (_outBus != null)
            {
                foreach (var evt in newEvents)
                {
                    try
                    {
                        _outBus.Publish((Message)evt);
                    }
                    catch { }//TODO: see if we need to do something here
                }
            }
            aggregate.ClearUncommittedEvents();
        }
コード例 #19
0
        private IEventStream PrepareStream(string bucketId, IAggregate aggregate, Dictionary <string, object> headers)
        {
            IEventStream stream = _eventStore.CreateStream(bucketId, aggregate.Id);

            foreach (var item in headers)
            {
                stream.UncommittedHeaders[item.Key] = item.Value;
            }
            aggregate.GetUncommittedEvents()
            .Cast <object>()
            .Select(x => new EventMessage {
                Body = x
            })
            .ToList()
            .ForEach(stream.Add);
            return(stream);
        }
コード例 #20
0
        public void Write(IAggregate aggregate, Guid commitId, Action<IDictionary<string, object>> updateHeaders)
        {
            var streamName = _aggregateIdToStreamName(aggregate.Category, aggregate.Id);
            var newEvents = aggregate.GetUncommittedEvents().Cast<object>().ToList();

            var eventsToSave = newEvents
                .Select(e => e.AsJsonEvent())
                .ToList();

            foreach (var eventData in eventsToSave)
            {
                var data = new StreamData(streamName, eventData);

                FakeDatabase.Events.Add(Guid.NewGuid(), data);
            }

            aggregate.ClearUncommittedEvents();
        }
コード例 #21
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = _aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var eventsToSave    = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();

            if (eventsToSave.Count < WritePageSize)
            {
                _eventStoreConnection.AppendToStream(streamName, expectedVersion, eventsToSave);
            }
            else
            {
                var transaction = _eventStoreConnection.StartTransaction(streamName, expectedVersion);

                var position = 0;
                while (position < eventsToSave.Count)
                {
                    var pageEvents = eventsToSave.Skip(position).Take(WritePageSize);
                    transaction.Write(pageEvents);
                    position += WritePageSize;
                }

                transaction.Commit();
            }

            foreach (var newEvent in newEvents)
            {
                _bus.Publish(newEvent);
            }

            aggregate.ClearUncommittedEvents();
        }
コード例 #22
0
 protected virtual void Save(IAggregate aggr, DomainEvent by)
 {
     foreach (DomainEvent evt in aggr.GetUncommittedEvents())
     {
         if (!evt.TenantId.HasValue)
         {
             evt.TenantId = @by.TenantId;
         }
         if (!evt.IssuedBy.HasValue)
         {
             evt.IssuedBy = @by.IssuedBy;
         }
         if (!evt.SagaId.HasValue)
         {
             evt.SagaId = @by.SagaId;
         }
         evt.Version = aggr.Version;
     }
     repo.Save(aggr, Guid.NewGuid());
 }
コード例 #23
0
        public void Update(IAggregate match)
        {
            var takeSnapshot = match.GetUncommittedEvents().Cast <IEvent>().Any(p => p.Version > 0 && p.Version % _settings.SnapshotEvery == 0);

            _repository.Save(match, Guid.NewGuid());
            if (!takeSnapshot)
            {
                return;
            }

            var matchCopy = ((Match)match).Clone() as IAggregate;

            if (matchCopy == null)
            {
                throw new ApplicationException("Something wrong while cloning the aggregate");
            }
            Task.Run(() =>
            {
                _store.Advanced.AddSnapshot(new Snapshot(matchCopy.Id.ToString(), matchCopy.Version, MatchMemento.Create(matchCopy)));
            });
        }
コード例 #24
0
        public void Save(IAggregate aggregate)
        {
            var takeSnapshot = aggregate.GetUncommittedEvents().Cast <IEvent>().Any(p => p.Version > 0 && p.Version % 5 == 0);

            _repository.Save(aggregate, Guid.NewGuid());
            if (!takeSnapshot)
            {
                return;
            }

            var aggregateCopy = ((RobotWarAggregate)aggregate).Clone() as IAggregate;

            if (aggregateCopy == null)
            {
                throw new ApplicationException("Something wrong while cloning the aggregate");
            }
            Task.Run(() =>
            {
                _store.Advanced.AddSnapshot(new Snapshot(aggregateCopy.Id.ToString(), aggregateCopy.Version, RobotWarMemento.Create(aggregateCopy)));
            });
        }
コード例 #25
0
        public async Task <AggregateCommit> SaveAsync(IAggregate aggregate)
        {
            if (aggregate.Id == Guid.Empty)
            {
                throw new Exception(
                          $"The aggregate {aggregate.GetType().FullName} has tried to be saved with an empty id");
            }

            var uncommittedEvents = aggregate.GetUncommittedEvents().Cast <IEventData>().ToArray();
            var count             = 0;

            var metadata = string.Empty;

            try
            {
                var col = _db.GetCollection <LocalEventTable>();
                col.EnsureIndex(x => x.StreamId, false);

                col.InsertBulk(uncommittedEvents.Select(x => new LocalEventTable {
                    StreamId      = aggregate.Id,
                    Version       = x.Version,
                    TransactionId = _commandContext.Transaction.Id,
                    AppVersion    = _commandContext.AppVersion,
                    When          = x.TimeStamp,
                    Body          = JsonConvert.SerializeObject(x.Event, SerializerSettings),
                    Category      = aggregate.GetType().FullName,
                    Who           = _commandContext.ImpersonatorBy?.GuidId ?? _commandContext.By.GuidId,
                    BodyType      = x.Type.FullName
                }));
            }
            catch (Exception e)
            {
                throw new Exception(
                          $"The aggregate {aggregate.GetType().FullName} has tried to save events to an old version of an aggregate");
            }

            aggregate.ClearUncommittedEvents();
            return(new AggregateCommit(aggregate.Id, _commandContext.By.GuidId, metadata, uncommittedEvents));
        }
コード例 #26
0
        public void Save(IAggregate aggregate)
        {
            var commitId = Guid.NewGuid();
            var events   = aggregate.GetUncommittedEvents().ToArray();

            if (events.Any() == false)
            {
                return;
            }
            var streamName      = GetTheStreamName(aggregate.GetType(), aggregate.Id);
            var originalVersion = aggregate.Version - events.Count();
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var commitHeaders   = new Dictionary <string, object>
            {
                { "CommitId", commitId },
                { "AggregateClrType", aggregate.GetType().AssemblyQualifiedName }
            };
            var eventsToSave = events.Select(e => e.ToEventData(commitHeaders)).ToList();

            connection.AppendToStreamAsync(streamName, expectedVersion, eventsToSave).Wait();
            aggregate.ClearUncommittedEvents();
        }
コード例 #27
0
        public async Task Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { CommitDateHeader, DateTime.UtcNow },
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName      = aggregateIdToStreamName(aggregate.GetType(), aggregate.Id.Value);
            var newEvents       = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion = aggregate.Version - newEvents.Count;
            var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var eventsToSave    = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();

            if (eventsToSave.Count < WritePageSize)
            {
                eventStoreConnection.AppendToStreamAsync(streamName, expectedVersion, eventsToSave).Wait();
            }
            else
            {
                var transaction = eventStoreConnection.StartTransactionAsync(streamName, expectedVersion).Result;

                var position = 0;
                while (position < eventsToSave.Count)
                {
                    var pageEvents = eventsToSave.Skip(position).Take(WritePageSize);
                    await transaction.WriteAsync(pageEvents);

                    position += WritePageSize;
                }
                await transaction.CommitAsync();

                transaction.Dispose();
            }
            aggregate.ClearUncommittedEvents();
        }
コード例 #28
0
 protected virtual void Save(IAggregate aggr, DomainCommand by, string bucketId)
 {
     if (OnSavedHook != null)
     {
         OnSavedHook(this, aggr, by);
     }
     foreach (DomainEvent evt in aggr.GetUncommittedEvents())
     {
         if (!evt.TenantId.HasValue)
         {
             evt.TenantId = @by.TenantId;
         }
         if (!evt.IssuedBy.HasValue)
         {
             evt.IssuedBy = @by.IssuedBy;
         }
         if (!evt.SagaId.HasValue)
         {
             evt.SagaId = @by.SagaId;
         }
         evt.Version = aggr.Version;
     }
     repo.Save(bucketId, aggr, @by.CommitId);
 }
コード例 #29
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var commitHeaders = new Dictionary <string, object>
            {
                { CommitIdHeader, commitId },
                { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName }
            };

            updateHeaders(commitHeaders);

            var streamName         = _aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
            var categoryStreamName = _aggregateTypeToCategoryStreamName(aggregate.GetType());
            var newEvents          = aggregate.GetUncommittedEvents().Cast <object>().ToList();
            var originalVersion    = aggregate.Version - newEvents.Count;
            var expectedVersion    = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;
            var eventsToSave       = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();

            List <EventData> stream;

            _store.TryGetValue(streamName, out stream);
            List <EventData> catStream;

            _store.TryGetValue(categoryStreamName, out catStream);



            if (stream == null)
            {
                if (expectedVersion == ExpectedVersion.Any || expectedVersion == ExpectedVersion.NoStream)
                {
                    stream = new List <EventData>();
                    _store.Add(streamName, stream);
                    if (catStream == null)
                    {
                        catStream = new List <EventData>();
                        _store.Add(categoryStreamName, catStream);
                    }
                }
                else
                {
                    throw new WrongExpectedVersionException("Stream " + streamName + " does not exist.");
                }
            }

            if (stream.Count != 0 && stream.Count - 1 != expectedVersion) // a new stream will be @ version 0
            {
                throw new AggregateException(new WrongExpectedVersionException(
                                                 $"Stream {streamName} at version {stream.Count}, expected version {expectedVersion}"));
            }


            stream.AddRange(eventsToSave);
            catStream?.AddRange(eventsToSave);

            foreach (var evt in eventsToSave)
            {
                var etName = _eventNameToEventTypeStreamName(evt.Type);
                List <EventData> etStream;
                if (!_store.TryGetValue(etName, out etStream))
                {
                    etStream = new List <EventData>();
                    _store.Add(etName, etStream);
                }
                etStream.Add(evt);
            }

            foreach (var @event in aggregate.GetUncommittedEvents().Cast <object>().Where(@event => (@event as Message) != null))
            {
                _bus.Publish(@event as Message);
                _history.Add(new Tuple <string, Message>(streamName, @event as Message));
            }
            aggregate.ClearUncommittedEvents();
        }
コード例 #30
0
        public Task SaveAsync(string bucketId, IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            this.Events = aggregate.GetUncommittedEvents().Cast <Event>().ToList();

            return(Task.CompletedTask);
        }
コード例 #31
0
ファイル: TestHelper.cs プロジェクト: poliset/nes-training
 public static bool HasRaised <TEvent>(this IAggregate aggregate)
 {
     return(aggregate.GetUncommittedEvents().OfType <TEvent>().Any());
 }
コード例 #32
0
ファイル: TestHelper.cs プロジェクト: poliset/nes-training
 public static TEvent LastEventOfType <TEvent>(this IAggregate aggregate)
 {
     return(aggregate.GetUncommittedEvents().OfType <TEvent>().Last());
 }
コード例 #33
0
 public void Save(string bucketId, IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
 {
     Events = aggregate.GetUncommittedEvents().Cast <IEvent>().ToList();
 }
コード例 #34
0
 public static IReadOnlyCollection <TEvent> GetEvents <TEvent>(this IAggregate aggregate) where TEvent : DomainEvent
 {
     return(aggregate.GetUncommittedEvents().OfType <TEvent>().ToArray());
 }