コード例 #1
0
        public async Task LoadAsync(IAggregate domainObject, long?expectedVersion = null)
        {
            var streamName = nameResolver.GetStreamName(domainObject.GetType(), domainObject.Id);

            var events = await eventStore.GetEventsAsync(streamName);

            if (events.Count == 0)
            {
                throw new DomainObjectNotFoundException(domainObject.Id.ToString(), domainObject.GetType());
            }

            foreach (var storedEvent in events)
            {
                var envelope = ParseKnownCommand(storedEvent);

                if (envelope != null)
                {
                    domainObject.ApplyEvent(envelope);
                }
            }

            if (expectedVersion != null && domainObject.Version != expectedVersion.Value)
            {
                throw new DomainObjectVersionException(domainObject.Id.ToString(), domainObject.GetType(), domainObject.Version, expectedVersion.Value);
            }
        }
コード例 #2
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();
        }
コード例 #3
0
 private NoSqlEventData(IAggregate aggregate)
 {
     this.Id            = aggregate.Id.ToString();
     this.AggregateType = $"{aggregate.GetType().Name}";
     this.StreamName    = $"{char.ToLower(aggregate.GetType().Name[0])}{aggregate.GetType().Name.Substring(1)}Events-{aggregate.Id}";
     this.EventStream   = Enumerable.Empty <NoSqlEvent>();
 }
コード例 #4
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);
                }
            }
        }
        /// <summary>
        /// Gets an IRouteEvents for a given aggregate
        /// </summary>
        /// <param name="aggregate"></param>
        /// <returns></returns>
        public IRouteEvents GetRoutesFor(IAggregate aggregate)
        {
            var mbRoute = routes.Get(aggregate.GetType());

            var route = mbRoute.GetOrElse(() => {// Note: performs side effect on the routes table
                var innerRoute = BuildRoutesFor(aggregate);
                routes[aggregate.GetType()] = innerRoute;
                return(innerRoute);
            });

            return(new RouteEventsAdapter(route, aggregate));
        }
コード例 #6
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();
        }
コード例 #7
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();
        }
コード例 #8
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();
        }
コード例 #9
0
        public static void ThrowHandlerNotFound(this IAggregate aggregate, object eventMessage)
        {
            var exceptionMessage = "Aggregate of type '{0}' raised an event of type '{1}' but not handler could be found to handle the message."
                                   .FormatWith(aggregate.GetType().Name, eventMessage.GetType().Name);

            throw new HandlerForDomainEventNotFoundException(exceptionMessage);
        }
コード例 #10
0
 private static IDictionary <string, string> CreateCommitHeaders(IAggregate aggregate) =>
 new Dictionary <string, string>
 {
     { CommitIdHeader, Guid.NewGuid().ToString() },
     { AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName },
     { ServerClockHeader, DateTime.UtcNow.ToString("o") }
 };
コード例 #11
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++));
                }
            }
        }
コード例 #12
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);
        }
コード例 #13
0
        public void Save(IAggregate aggregate)
        {
            Db4oAggregate dbAggregate = (from Db4oAggregate a in _database
                                         where a.Id == aggregate.Id
                                         select a).FirstOrDefault();

            int version = 0;
            if (dbAggregate == null)
            {
                dbAggregate = new Db4oAggregate { Id = aggregate.Id, Type = aggregate.GetType().Name, Version = 0 };
            }
            else
            {
                version = dbAggregate.Version;
            }

            IEnumerable<IDomainEvent> events = aggregate.GetChanges();

            foreach (IDomainEvent e in events)
            {
                version++;
                var db4oEvent = new Db4oEvent
                                    {
                                        AggregateId = dbAggregate.Id,
                                        Event = e,
                                        Version = version
                                    };
                _database.Store(db4oEvent);
            }

            dbAggregate.Version = version;
            _database.Store(dbAggregate);
        }
コード例 #14
0
        public virtual void Register(IAggregate aggregate)
        {
            if (aggregate == null)
            {
                throw new ArgumentNullException("aggregate");
            }

            this.registered = aggregate;

            // Get instance methods named Apply with one parameter returning void
            var applyMethods = aggregate.GetType()
                               .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                               .Where(m => m.Name == "Apply" && m.GetParameters().Length == 1 && m.ReturnParameter.ParameterType == typeof(void))
                               .Select(m => new
            {
                Method      = m,
                MessageType = m.GetParameters().Single().ParameterType
            });

            foreach (var apply in applyMethods)
            {
                var applyMethod = apply.Method;
                this.handlers.Add(apply.MessageType, m => applyMethod.Invoke(aggregate, new[] { m as object }));
            }
        }
コード例 #15
0
        private IEnumerable<IEvent> SaveEvents(IDatabase db, IAggregate aggregate)
        {
            if (!aggregate.UncommitedEvents().Any())
            {
                return new List<IEvent>();
            }

            var key = MakeKey(aggregate.GetType(), aggregate.Id);

            var evtsToSave = aggregate.UncommitedEvents().ToList();

            var expected = CalculateExpectedVersion(aggregate, evtsToSave);
            var current = db.HashGetAll(key).Length - 1;

            if (expected != current)
            {
                throw new AggregateConflictException(aggregate.Id, expected, current);
            }

            foreach (var e in evtsToSave)
            {
                var version = e.Version.ToString();
                var json = _serializer.Serialize(e);

                var success = db.HashSet(key, version, json, When.NotExists);

                if (!success)
                {
                    throw new AggregateConflictException(aggregate.Id, expected, current);
                }
            }

            return aggregate.UncommitedEvents();
        }
コード例 #16
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);
            }
        }
コード例 #17
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();
        }
コード例 #18
0
        public override bool ShouldMakeSnapshot(IAggregate aggregate)
        {
            if (!CheckSnapshotSupport(aggregate.GetType()))
            {
                return(false);
            }

            return(aggregate.Sequence % SnapshotInterval == 0);
        }
コード例 #19
0
        public void Add(IAggregate aggregate)
        {
            var result = _all.GetOrAdd(aggregate.Id, aggregate);

            if(!Object.ReferenceEquals(aggregate, result))
            {
                throw new AggregateVersionException(aggregate.Id, aggregate.GetType(), aggregate.Version, 0);
            }
        }
コード例 #20
0
        public void Save(IAggregate aggregate, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var jsonText = JsonConvert.SerializeObject(aggregate, SerializerSettings);

            File.WriteAllText(
                _fileFullName(aggregate.GetType(), aggregate.Id),
                jsonText
                );
        }
コード例 #21
0
 public async Task Save(MessageContext messageContext, IAggregate aggregate)
 {
     var stream = new Stream(Categories.Events, aggregate.GetType(), messageContext.AggregateId);
     await messageStore.Store(stream, StreamVersion.Any,
                              aggregate.Events.Select(evt =>
                                                      new StorableMessage(
                                                          metadataFactory.Create(messageContext),
                                                          evt)));
 }
コード例 #22
0
        public virtual bool ShouldMakeSnapshot(IAggregate aggregate)
        {
            if (!CheckSnapshotSupport(aggregate.GetType()))
            {
                return(false);
            }

            return(true);
        }
コード例 #23
0
        internal static void ThrowHandlerNotFound(this IAggregate aggregate, object eventMessage)
        {
            string exceptionMessage = string.Format("Aggregate of type '{0}' raised an event of type '{1}' but no" +
                                                    " handler could be found to handle the message.",
                                                    aggregate.GetType().Name,
                                                    eventMessage.GetType().Name);

            throw new InvalidOperationException(exceptionMessage);
        }
コード例 #24
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)));
     }
 }
コード例 #25
0
        public void Invoke(IAggregate aggregate, object eventData)
        {
            var handlers = AllHandlers.GetOrAdd(aggregate.GetType(), type => ScanAggregate(type));

            Action<IAggregate, object> handler;
            if (handlers.TryGetValue(eventData.GetType(), out handler))
            {
                handler(aggregate, eventData);
            }
        }
コード例 #26
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();
        }
コード例 #27
0
        public void Invoke(IAggregate aggregate, object eventData)
        {
            var handlers = AllHandlers.GetOrAdd(aggregate.GetType(), type => ScanAggregate(type));

            Action <IAggregate, object> handler;

            if (handlers.TryGetValue(eventData.GetType(), out handler))
            {
                handler(aggregate, eventData);
            }
        }
コード例 #28
0
        public async Task SaveAsync(IAggregate domainObject, ICollection <Envelope <IEvent> > events, Guid commitId)
        {
            Guard.NotNull(domainObject, nameof(domainObject));

            var streamName = nameResolver.GetStreamName(domainObject.GetType(), domainObject.Id);

            var versionCurrent  = domainObject.Version;
            var versionExpected = versionCurrent - events.Count;

            var eventsToSave = events.Select(x => formatter.ToEventData(x, commitId)).ToList();

            try
            {
                await eventStore.AppendEventsAsync(commitId, streamName, versionExpected, eventsToSave);
            }
            catch (WrongEventVersionException)
            {
                throw new DomainObjectVersionException(domainObject.Id.ToString(), domainObject.GetType(), versionCurrent, versionExpected);
            }
        }
コード例 #29
0
ファイル: AggregateRepository.cs プロジェクト: philoUK/MyES
        private async Task EnsureNoConcurrencyProblems(IAggregate aggregate, List <IAggregateEvent> events)
        {
            var latestVersion = await this.eventStore.GetLatestVersionOf(aggregate.Id);

            var firstVersion = events.First().Version;

            if (latestVersion != (firstVersion - 1))
            {
                throw new EventStoreConcurrencyException(
                          $"Aggregate of type {aggregate.GetType().Name} with an Id of {aggregate.Id} already has an event with that same version.  Reload the aggregate and retry the operation");
            }
        }
コード例 #30
0
        private static Dictionary <string, object> PrepareHeaders(IAggregate aggregate, Action <IDictionary <string, object> > updateHeaders)
        {
            var headers = new Dictionary <string, object>();

            headers[AggregateTypeHeader] = aggregate.GetType().FullName;
            if (updateHeaders != null)
            {
                updateHeaders(headers);
            }

            return(headers);
        }
コード例 #31
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();
        }
コード例 #32
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();
        }
コード例 #33
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));
        }
コード例 #34
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);
            }
        }
コード例 #35
0
ファイル: AggregateKey.cs プロジェクト: swizkon/Nuclear
 /// <summary>
 /// Inverted factory method.
 /// </summary>
 /// <param name="obj"></param>
 public AggregateKey(IAggregate obj)
     : this(obj.GetType(), obj.AggregateId)
 {
     // this.AggregateType = obj.GetType();
     // this.AggregateId = obj.AggregateId;
 }
コード例 #36
0
ファイル: XmlFile.cs プロジェクト: XiBeichuan/hydronumerics
		/// <summary>
		/// Reads the attributes of the current xml element and uses them to populute the target with
		/// </summary>
		/// <param name="target">The object which is populated with the xml attributes</param>
		/// <param name="reader">The xml stream</param>
		/// <param name="root">Top object of the xml stream</param>
		/// <exception cref="System.Exception">Cannot find class type</exception>
		/// <exception cref="System.Exception">Cannot instantiate object for known class type</exception>
		private static void ReadAttributes (IAggregate target, XmlReader reader, object root) 
		{
			// Read all attributes
			string[] properties = target.Properties;
			for (int i = 0; i < properties.Length; i++) 
			{
				string name = XmlFile.GetElementName (target.Source.GetType(), properties[i], false);
				if (name != null) 
				{
					string attributeValue = reader.GetAttribute(name);
					if (attributeValue != null) 
					{
						string classType = (string) MetaInfo.GetAttributeDefault (target.Source.GetType(), properties[i], "XmlType", target.GetType(properties[i]).FullName);
						Type type = ObjectSupport.GetType(classType);
						if (type == null) 
						{
							throw new Exception("Could not find class type " + classType);
						}

						if (type.Equals(typeof(FileInfo))) 
						{
							attributeValue = FileSupport.ExpandRelativePath (XmlFile.GetRegisteredFile(root).Directory, attributeValue).FullName;
						}

						if (type.Equals(typeof(DirectoryInfo))) 
						{
							attributeValue = FileSupport.ExpandRelativeDirectory (XmlFile.GetRegisteredFile(root).Directory, attributeValue).FullName;
						}

						object targetValue = ObjectSupport.GetInstance (type, attributeValue, _culture);
						if (targetValue == null) 
						{
							throw new Exception("Could not instantiate class type " + type.FullName);
						}

						if (target.CanWrite(properties[i])) 
						{
							target.SetValue(properties[i], targetValue);
						}
					}
				}
			}
		}
コード例 #37
0
ファイル: XmlFile.cs プロジェクト: XiBeichuan/hydronumerics
		/// <summary>
		/// Gets the key from an object. 
		/// If the key isn't unique and the property allows for key generation, a unique key is generated.
		/// </summary>
		/// <param name="target"></param>
		/// <param name="root"></param>
		/// <returns></returns>
		private static string GetKeyFromObject(IAggregate target, object root) 
		{
			string key = null;
			int lastkey = 0;

			string[] property = target.Properties;
			int generatedProperty = -1;

			bool generationPossible = true;
			while (generationPossible) 
			{
				key = null;
				lastkey++;
				generationPossible = false;

				for (int i = 0; i < property.Length; i++) 
				{
					if ((Boolean) MetaInfo.GetAttributeDefault (target.Source.GetType(), property[i], "XmlKey", false))
					{
						object KeyObject  = target.GetValue(property[i]);
						if ((KeyObject != null) && (!KeyObject.ToString().Trim().Equals("")))
						{
							key += KeyObject.ToString() + ";"; 
						}
						else if ((Boolean) MetaInfo.GetAttributeDefault (target.Source.GetType(), property[i], "XmlAllowGeneration", true))
						{
							generationPossible = true;
							generatedProperty = i;
							key += lastkey + ";";
						}
					}
				}

				if (key != null) 
				{
					key += target.Source.GetType().FullName;

					object registeredObject = XmlFile.GetRegisteredTarget(root, key);
					if ((registeredObject == null) || (registeredObject == target)) 
					{
						if (generatedProperty != -1) 
						{
							Type PropertyType = target.GetType(property[generatedProperty]);
							if (PropertyType.Equals(typeof(string)))
							{
								target.SetValue(property[generatedProperty], Convert.ToString(lastkey));
							}
							else if (PropertyType.Equals(typeof(Int16)) || PropertyType.Equals(typeof(Int32)) || PropertyType.Equals(typeof(Int64))) 
							{
								target.SetValue(property[generatedProperty], lastkey);
							}
						}
						return key;
					} 
				}
			}

			return key;
		}
コード例 #38
0
        public override bool Equals(IAggregate other)
        {
            if (other.GetType() != typeof(ListAggregate))
            {
                return false;
            }

            ListAggregate toCheck = (ListAggregate)other;
            if (!(toCheck.id.Equals(this.id)))
                return false;
            if (!(toCheck.name.Equals(this.name)))
                return false;
            if(!(toCheck.todoItems.Count.Equals(this.todoItems.Count)))
                return false;
            for (int i = 0; i < toCheck.todoItems.Count; i++)
            {
                if (!(toCheck.todoItems.ElementAt(i).Equals(this.todoItems.ElementAt(i))))
                    return false;
            }
            return true;
        }
コード例 #39
0
        public override bool Equals(IAggregate other)
        {
            if (other.GetType() != typeof(TodoItemAggregate))
                return false;

            TodoItemAggregate toCheck = (TodoItemAggregate)other;

            if (!(toCheck.description.Equals(this.description)))
                return false;
            if (!(toCheck.id.Equals(this.id)))
                return false;
            if (!(toCheck.name.Equals(this.name)))
                return false;
            if (!(toCheck.priority.Equals(this.priority)))
                return false;
            if (!toCheck.index.Equals(this.index))
                return false;

            return true;
        }