Example #1
0
        public IStream GetOrAdd(IEventSourced es)
        {
            var key    = Key(es);
            var stream = new Stream(key, es.Version, es.GetType());

            return(_streams.GetOrAdd(key, stream));
        }
Example #2
0
        public void Save(IEventSourced eventSourced, Envelope <ICommand> command)
        {
            Assertions.NotNull(eventSourced, "eventSourced");
            Assertions.NotNull(command, "command");

            var eventSourcedType = eventSourced.GetType();
            var sourceInfo       = new SourceInfo(eventSourced.Id, eventSourcedType);
            var changedEvents    = eventSourced.GetChanges();

            var saved = false;

            try
            {
                if (_eventStore.Save(sourceInfo, changedEvents, command.MessageId))
                {
                    if (LogManager.Default.IsDebugEnabled)
                    {
                        LogManager.Default.DebugFormat(
                            "Persistent domain events successfully. aggregateRootType:{0},aggregateRootId:{1},version:{2}~{3}.",
                            eventSourcedType.FullName, eventSourced.Id, changedEvents.Min(p => p.Version), changedEvents.Max(p => p.Version));
                    }
                    saved = true;
                }
            }
            catch (Exception ex)
            {
                LogManager.Default.Error(ex,
                                         "Persistent domain events failed. aggregateRootType:{0},aggregateRootId:{1},version:{2}~{3}.",
                                         eventSourcedType.FullName, eventSourced.Id, changedEvents.Min(p => p.Version), changedEvents.Max(p => p.Version));
                throw ex;
            }

            if (!saved)
            {
                //由该命令产生的事件如果已保存,则取出之前的事件重新发送
                changedEvents = _eventStore.Find(sourceInfo, command.MessageId);

                _eventBus.Publish(sourceInfo, changedEvents, command);
                return;
            }

            try
            {
                _cacheProvider.GetCache(GetCacheRegion(eventSourcedType)).Put(GetCacheKey(eventSourcedType, eventSourced.Id), eventSourced);
            }
            catch (Exception ex)
            {
                LogManager.Default.Warn(ex,
                                        "Failed to refresh aggregate root to memory cache. aggregateRootType:{0},aggregateRootId:{1}.",
                                        eventSourcedType.FullName, eventSourced.Id);
            }

            _eventBus.Publish(sourceInfo, changedEvents, command);
        }
Example #3
0
        public static IEventSourced AndAtLeastOne <TEvent>(this IEventSourced aggregate)
            where TEvent : IEvent
        {
            var hasEvents = aggregate.PendingEvents.OfType <TEvent>().Any();

            if (hasEvents)
            {
                return(aggregate);
            }
            else
            {
                throw new InvalidOperationException($"Aggregate of type {aggregate.GetType().Name} does not generated any event of type {typeof(TEvent).Name} so far.");
            }
        }
        private async Task <IEventSourced> GetBase(string bucket, string type, Id id, IEventSourced parent = null)
        {
            var entityType = Type.GetType(type, false, true);

            if (entityType == null)
            {
                Logger.Error($"Received conflicting events message for unknown type {type}");
                throw new ArgumentException($"Received conflicting events message for unknown type {type}");
            }

            // We have the type name, hack the generic parameters to build Entity
            if (parent == null)
            {
                var method = typeof(IUnitOfWork).GetMethod("For", new Type[] {}).MakeGenericMethod(entityType);

                var repo = method.Invoke(_uow, new object[] { });

                method = repo.GetType().GetMethod("Get", new Type[] { typeof(string), typeof(Id) });
                // Note: we can't just cast method.Invoke into Task<IEventSourced> because Task is not covariant
                // believe it or not this is the easiest solution
                var task = (Task)method.Invoke(repo, new object[] { bucket, id });
                await task.ConfigureAwait(false);

                return(task.GetType().GetProperty("Result").GetValue(task) as IEventSourced);
            }
            else
            {
                var method =
                    typeof(IUnitOfWork).GetMethods()
                    .Single(x => x.Name == "For" && x.GetParameters().Length == 1)
                    .MakeGenericMethod(parent.GetType(), entityType);

                var repo = method.Invoke(_uow, new object[] { parent });

                method = repo.GetType().GetMethod("Get", new Type[] { typeof(Id) });
                var task = (Task)method.Invoke(repo, new object[] { id });
                await task.ConfigureAwait(false);

                return(task.GetType().GetProperty("Result").GetValue(task) as IEventSourced);
            }
        }
Example #5
0
 public static string GetEventStoreStream <TKey>(this IEventSourced <TKey> aggregate)
 {
     return(string.Format("{0}-{1}", aggregate.GetType().Name, aggregate.Id));
 }
Example #6
0
File: Stream.cs Project: zedr0n/ZES
 /// <summary>
 /// Initializes a new instance of the <see cref="Stream"/> class.
 /// </summary>
 /// <param name="es">Event sourced instance</param>
 /// <param name="timeline">Target timeline</param>
 public Stream(IEventSourced es, string timeline = "")
     : this(es.Id, es.GetType().Name, ExpectedVersion.NoStream, timeline)
 {
 }
Example #7
0
        /// <summary>
        /// 保存聚合事件。
        /// </summary>
        public void Save(IEventSourced aggregateRoot, string correlationId)
        {
            if (string.IsNullOrWhiteSpace(correlationId)) {
                if (_logger.IsWarnEnabled)
                    _logger.Warn("Not use command to modify the state of the aggregate root.");
            }

            var aggregateRootType = aggregateRoot.GetType();
            var aggregateRootId = aggregateRoot.Id;
            var events = aggregateRoot.GetEvents();
            var key = new SourceKey(aggregateRootId, aggregateRootType);

            if (_eventStore.Save(key, correlationId, () => events.Select(Serialize))) {
                if (_logger.IsDebugEnabled)
                    _logger.DebugFormat("Domain events persistent completed. aggregateRootId:{0}, aggregateRootType:{1}, commandId:{2}.",
                        aggregateRootId, aggregateRootType.FullName, correlationId);

                _cache.Set(aggregateRoot, aggregateRoot.Id);
            }
            else {
                events = _eventStore.FindAll(key, correlationId).Select(Deserialize).OfType<IVersionedEvent>().OrderBy(p => p.Version);

                if (_logger.IsDebugEnabled)
                    _logger.DebugFormat("The command generates events have been saved, load from storage. aggregateRootId:{0}, aggregateRootType:{1}, commandId:{2}.",
                        aggregateRootId, aggregateRootType.FullName, correlationId);
            }

            List<IEvent> pendingEvents = new List<IEvent>();
            if (string.IsNullOrWhiteSpace(correlationId)) {
                pendingEvents.AddRange(events);
            }
            else {
                pendingEvents.Add(Convert(key, correlationId, events));
            }

            var eventPublisher = aggregateRoot as IEventPublisher;
            if (eventPublisher != null) {
                var otherEvents = eventPublisher.Events.Where(p => !(p is IVersionedEvent));
                pendingEvents.AddRange(otherEvents);
            }
            _eventBus.Publish(pendingEvents);

            var snapshot = Serialize(key, aggregateRoot);
            if (!_snapshotPolicy.ShouldbeCreateSnapshot(snapshot))
                return;

            try {
                if (_snapshotStore.Save(snapshot) && _logger.IsDebugEnabled)
                    _logger.DebugFormat("make snapshot completed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.",
                       aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
            }
            catch (Exception ex) {
                if (_logger.IsWarnEnabled)
                    _logger.Warn(ex,
                        "snapshot persistent failed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.",
                        aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
            }
        }
Example #8
0
 /// <summary>
 /// 删除该聚合根下的溯源事件
 /// </summary>
 public void Delete(IEventSourced aggregateRoot)
 {
     this.Delete(aggregateRoot.GetType(), aggregateRoot.Id);
 }
Example #9
0
        /// <summary>
        /// 保存聚合事件。
        /// </summary>
        public void Save(IEventSourced aggregateRoot, string correlationId)
        {
            if (string.IsNullOrWhiteSpace(correlationId)) {
                if (_logger.IsWarnEnabled)
                    _logger.Warn("Not use command to modify the state of the aggregate root.");
            }

            var aggregateRootType = aggregateRoot.GetType();
            var aggregateRootId = aggregateRoot.Id;
            var events = aggregateRoot.GetEvents();
            var key = new SourceKey(aggregateRootId, aggregateRootType);            

            if (!_eventStore.EventPersisted(key, correlationId)) {
                _eventStore.Save(key, correlationId, events.Select(Serialize));

                if (_logger.IsInfoEnabled)
                    _logger.InfoFormat("sourcing events persistent completed. aggregateRootId:{0},aggregateRootType:{1}.",
                        aggregateRootId, aggregateRootType.FullName);
            }
            else {
                events = _eventStore.FindAll(key, correlationId).Select(Deserialize).OfType<IVersionedEvent>().OrderBy(p => p.Version);

                if (_logger.IsInfoEnabled)
                    _logger.InfoFormat("the command generates events have been saved, load from storage. command id:{0}", 
                        correlationId);
            }

            if (string.IsNullOrWhiteSpace(correlationId)) {
                _eventBus.Publish(events);
            }
            else {
                _eventBus.Publish(Convert(key, correlationId, events));
            }

            var eventPublisher = aggregateRoot as IEventPublisher;
            if (eventPublisher != null) {
                eventPublisher.Events.ForEach(item => {
                    if (item is IVersionedEvent)
                        return;
                });
            }

            //if (_logger.IsInfoEnabled)
            //    _logger.InfoFormat("publish all events. event:{0}", _textSerializer.Serialize(events));

            _cache.Set(aggregateRoot, aggregateRoot.Id);

            var snapshot = Serialize(key, aggregateRoot);
            if (!_snapshotPolicy.ShouldbeCreateSnapshot(snapshot))
                return;

            try {
                if (_snapshotStore.Save(snapshot) && _logger.IsInfoEnabled)
                    _logger.InfoFormat("make snapshot completed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.",
                       aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
            }
            catch (Exception ex) {
                if (_logger.IsWarnEnabled)
                    _logger.Warn(ex,
                        "snapshot persistent failed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.",
                        aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
            }
        }
Example #10
0
        /// <summary>
        /// 保存聚合事件。
        /// </summary>
        public void Save(IEventSourced aggregateRoot, string correlationId = null)
        {
            var events = aggregateRoot.GetEvents();

            if (events.IsEmpty())
            {
                return;
            }

            var    aggregateRootType     = aggregateRoot.GetType();
            int    aggregateRootTypeCode = _typeCodeProvider.GetTypeCode(aggregateRootType);
            string aggregateRootId       = aggregateRoot.Id.ToString();

            if (!_eventStore.IsExist(correlationId))
            {
                var sourcedEvents = events.Select(@event => new EventData()
                {
                    AggregateRootId       = aggregateRootId,
                    AggregateRootTypeCode = aggregateRootTypeCode,
                    Version       = @event.Version,
                    CorrelationId = correlationId,
                    Payload       = _serializer.Serialize(@event)
                }).ToArray();
                _eventStore.Append(sourcedEvents);

                _logger.Info("sourcing events persistent completed. aggregateRootId:{0},aggregateRootType:{1}.",
                             aggregateRootId, aggregateRootType.FullName);

                _cache.Set(aggregateRoot, aggregateRoot.Id);
            }
            else
            {
                events = _eventStore.FindAll(correlationId).Select(Deserialize);
                _logger.Info("the command generates events have been saved, load from storage. command id:{0}", correlationId);
            }

            _eventBus.Publish(new EventStream {
                AggregateRootId       = aggregateRootId,
                AggregateRootTypeCode = aggregateRootTypeCode,
                CommandId             = correlationId,
                StartVersion          = events.Min(item => item.Version),
                EndVersion            = events.Max(item => item.Version),
                Events = events.OfType <IEvent>().ToArray()
            });
            _logger.Info("publish all events. event ids: [{0}]", string.Join(",", events.Select(@event => @event.Id).ToArray()));

            if (_snapshotStore.StorageEnabled)
            {
                var snapshot = new SnapshotData(aggregateRootTypeCode, aggregateRootId)
                {
                    Data    = _serializer.Serialize(aggregateRoot),
                    Version = aggregateRoot.Version
                };

                _snapshotStore.Save(snapshot).ContinueWith(task => {
                    if (task.Status == TaskStatus.Faulted)
                    {
                        _logger.Error(task.Exception, "snapshot persistent failed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.", aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
                    }
                });
                //Task.Factory.StartNew(() => {
                //    try {
                //        _snapshotStore.Save(snapshot);
                //    }
                //    catch (Exception ex) {
                //        _logger.Error(ex, "snapshot persistent failed. aggregateRootId:{0},aggregateRootType:{1},version:{2}.", aggregateRootId, aggregateRootType.FullName, aggregateRoot.Version);
                //    }
                //});
            }
        }
Example #11
0
 /// <summary>
 /// 删除聚合相关的事件。
 /// </summary>
 public void Remove(IEventSourced aggregate)
 {
     this.Remove(aggregate.GetType(), aggregate.Id);
 }