public async Task <IEventSourcedAggregateRoot> GetAsync <TAggregateRootId>(
            TAggregateRootId aggregateRootId,
            Type aggregateRootType,
            CancellationToken token = default)
        {
            var aggregateStringId        = aggregateRootId?.ToString();
            var defaultAggregateStringId = default(TAggregateRootId)?.ToString();

            if (string.IsNullOrWhiteSpace(aggregateStringId) ||
                aggregateStringId == defaultAggregateStringId)
            {
                throw new ArgumentNullException(nameof(aggregateRootId));
            }

            // 1. 从检查点还原聚合根
            var checkPoint = await _checkpointManager.GetLatestCheckpointAsync(aggregateStringId, aggregateRootType, token);

            var aggregateRoot = checkPoint?.Payload ?? _aggregateRootFactory.CreateAggregateRoot(aggregateRootId, aggregateRootType);

            var aggregateRootFullName = aggregateRootType.FullName;

            _logger.LogInformation($"Got latest checkpoint of the aggregate root, id: {aggregateStringId}, Type: {aggregateRootFullName}, Generation: {aggregateRoot.Generation}, Version: {aggregateRoot.Version}.");

            // 2. 获取从检查点开始产生的事件流
            var eventStream = await _eventStateBackend.GetEventStreamAsync(
                aggregateRoot.Id,
                aggregateRoot.Version,
                token);

            _logger.LogInformation($"Got domain event stream of the aggregate root, id: {aggregateStringId}, Type: {aggregateRootFullName}, Generation: {aggregateRoot.Generation}, Version: {aggregateRoot.Version}.");

            if (eventStream.IsEmpty())
            {
                CacheAndCheckpoint(aggregateRoot, token);

                return(aggregateRoot);
            }

            // 3.2 重放事件
            try
            {
                aggregateRoot.ReplayDomainEvents(eventStream);
            }
            catch (Exception e)
            {
                _logger.LogError($"Replaying domain event stream for aggregateRoot, Id: {aggregateStringId}, Type: {aggregateRootFullName}, Generation: {aggregateRoot.Generation}, Version: {aggregateRoot.Version} has a unknown exception: {e}.");

                return(null);
            }

            _logger.LogInformation($"Replayed domain event stream of the aggregate root, id: {aggregateStringId}, Type: {aggregateRootFullName}, Generation: {aggregateRoot.Generation}, Version: {aggregateRoot.Version}.");

            CacheAndCheckpoint(aggregateRoot, token);

            return(aggregateRoot);
        }
Пример #2
0
        /// <summary>
        /// 通过事件溯源的方式重建聚合根
        /// </summary>
        private AggregateRoot BuildAggregateRoot(Type aggregateRootType, IEnumerable <SourcableEvent> evnts)
        {
            AggregateRoot aggregateRoot = null;

            if (evnts != null && evnts.Count() > 0)
            {
                aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                aggregateRoot.ReplaySourcableEvents(evnts);
            }

            return(aggregateRoot);
        }
Пример #3
0
        /// <summary>
        /// 通过事件溯源的方式重建聚合根
        /// </summary>
        private T BuildAggregateRootFromCommittedEvents(IEnumerable <AggregateRootEvent> evnts)
        {
            T aggregateRoot = null;

            if (evnts != null && evnts.Count() > 0)
            {
                aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(typeof(T)) as T;
                aggregateRoot.ReplayEvents(evnts);
            }

            return(aggregateRoot);
        }
        /// <summary>Rebuild the aggregate root using the event sourcing pattern.
        /// </summary>
        private AggregateRoot BuildAggregateRoot(string aggregateRootId, Type aggregateRootType, IEnumerable <EventStream> streams)
        {
            AggregateRoot aggregateRoot = null;

            if (streams != null && streams.Count() > 0)
            {
                aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                aggregateRoot.ReplayEventStreams(streams);
            }

            return(aggregateRoot);
        }
Пример #5
0
        private IAggregateRoot RebuildAggregateRoot(Type aggregateRootType, IEnumerable <DomainEventStream> eventStreams)
        {
            if (eventStreams == null || !eventStreams.Any())
            {
                return(null);
            }

            var aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);

            aggregateRoot.ReplayEvents(eventStreams);

            return(aggregateRoot);
        }
Пример #6
0
        /// <summary>Rebuild the aggregate root using the event sourcing pattern.
        /// </summary>
        private AggregateRoot BuildAggregateRoot(Type aggregateRootType, IEnumerable <EventStream> streams)
        {
            var eventStreams = streams.ToList();

            if (streams == null || !eventStreams.Any())
            {
                return(null);
            }

            var aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);

            aggregateRoot.ReplayEventStreams(eventStreams);

            return(aggregateRoot);
        }
Пример #7
0
 private void RefreshAggregateMemoryCache(DomainEventStream aggregateFirstEventStream)
 {
     try
     {
         var aggregateRootType = _aggregateRootTypeCodeProvider.GetType(aggregateFirstEventStream.AggregateRootTypeCode);
         var aggregateRoot     = _memoryCache.Get(aggregateFirstEventStream.AggregateRootId, aggregateRootType);
         if (aggregateRoot == null)
         {
             aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
             aggregateRoot.ReplayEvents(new DomainEventStream[] { aggregateFirstEventStream });
             _memoryCache.Set(aggregateRoot);
             _logger.DebugFormat("Aggregate added into memory, commandId:{0}, aggregateRootType:{1}, aggregateRootId:{2}, aggregateRootVersion:{3}", aggregateFirstEventStream.CommandId, aggregateRootType.Name, aggregateRoot.UniqueId, aggregateRoot.Version);
         }
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Refresh memory cache by aggregate first event stream failed, {0}", aggregateFirstEventStream), ex);
     }
 }
Пример #8
0
        public void RebuildMemoryCache()
        {
            var groups = _eventStore.QueryAll().GroupBy(x => x.AggregateRootId);

            foreach (var group in groups)
            {
                if (group.Count() == 0)
                {
                    continue;
                }

                var aggregateRootType = _aggregateRootTypeProvider.GetAggregateRootType(group.First().AggregateRootName);
                var aggregateRoot     = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);

                aggregateRoot.ReplayEventStreams(group);

                _memoryCache.Set(aggregateRoot);
            }
        }
        private void RefreshMemoryCache(EventStream eventStream)
        {
            var aggregateRootType = _aggregateRootTypeProvider.GetAggregateRootType(eventStream.AggregateRootName);

            if (aggregateRootType == null)
            {
                throw new Exception(string.Format("Could not find aggregate root type by aggregate root name {0}", eventStream.AggregateRootName));
            }

            if (eventStream.Version == 1)
            {
                var aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                aggregateRoot.ReplayEventStream(eventStream);
                _memoryCache.Set(aggregateRoot);
            }
            else if (eventStream.Version > 1)
            {
                var aggregateRoot = _memoryCache.Get(eventStream.AggregateRootId);
                if (aggregateRoot == null)
                {
                    aggregateRoot = _repository.Get(aggregateRootType, eventStream.AggregateRootId);
                    if (aggregateRoot != null)
                    {
                        _memoryCache.Set(aggregateRoot);
                    }
                }
                else if (aggregateRoot.Version + 1 == eventStream.Version)
                {
                    aggregateRoot.ReplayEventStream(eventStream);
                    _memoryCache.Set(aggregateRoot);
                }
                else if (aggregateRoot.Version + 1 < eventStream.Version)
                {
                    aggregateRoot = _repository.Get(aggregateRootType, eventStream.AggregateRootId);
                    if (aggregateRoot != null)
                    {
                        _memoryCache.Set(aggregateRoot);
                    }
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Save
        /// </summary>
        /// <param name="snapshotHeaders"></param>
        /// <returns></returns>
        public async Task SaveAsync(IEnumerable <AggregateSnapshotHeader> snapshotHeaders)
        {
            var queue = new ConcurrentQueue <AggregateSnapshotData>();

            foreach (var snapshotHeader in snapshotHeaders)
            {
                try
                {
                    var            aggregateRootType             = _typeNameProvider.GetType(snapshotHeader.AggregateRootTypeName);
                    IAggregateRoot aggregateRoot                 = null;
                    IEnumerable <DomainEventStream> eventStreams = null;
                    var lastSnapshotData = await _snapshotStore.FindLatestAsync(snapshotHeader.AggregateRootId, snapshotHeader.AggregateRootTypeName);

                    if (lastSnapshotData != null)
                    {
                        try
                        {
                            using (var ms = new MemoryStream())
                            {
                                await ms.WriteAsync(lastSnapshotData.Data, 0, lastSnapshotData.Data.Length);

                                await ms.FlushAsync();

                                ms.Position   = 0;
                                aggregateRoot = _binaryFormatter.Deserialize(ms) as IAggregateRoot;
                            }
                        }
                        catch
                        {
                            aggregateRoot = null;
                        }
                    }
                    if (aggregateRoot == null)
                    {
                        // 无快照
                        aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                        eventStreams  = await _eventStore.QueryAggregateEventsAsync(snapshotHeader.AggregateRootId, snapshotHeader.AggregateRootTypeName, 1, snapshotHeader.Version);
                    }
                    else
                    {
                        eventStreams = await _eventStore.QueryAggregateEventsAsync(snapshotHeader.AggregateRootId, snapshotHeader.AggregateRootTypeName, lastSnapshotData.Version + 1, snapshotHeader.Version);
                    }
                    if (eventStreams != null && eventStreams.Any())
                    {
                        aggregateRoot.ReplayEvents(eventStreams);
                        using (var ms = new MemoryStream())
                        {
                            _binaryFormatter.Serialize(ms, aggregateRoot);
                            await ms.FlushAsync();

                            ms.Position = 0;
                            byte[] buffer = new byte[ms.Length];
                            await ms.ReadAsync(buffer, 0, buffer.Length);

                            queue.Enqueue(new AggregateSnapshotData(snapshotHeader.AggregateRootId, snapshotHeader.AggregateRootTypeName, aggregateRoot.Version, buffer));
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error($"Save snapshot fail:{ex.Message}. AggregateRootId={snapshotHeader.AggregateRootId},AggregateRootTypeName={snapshotHeader.AggregateRootTypeName}", ex);
                }
            }

            var snapshotDataList = new List <AggregateSnapshotData>();

            while (queue.TryDequeue(out AggregateSnapshotData snapshotData))
            {
                snapshotDataList.Add(snapshotData);
                if (snapshotDataList.Count == _batchSaveSize)
                {
                    try
                    {
                        await _snapshotStore.BatchSaveAsync(snapshotDataList);
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"Save snapshot fail:{ex.Message}.", ex);
                    }
                    finally
                    {
                        snapshotDataList.Clear();
                    }
                }
            }
        }
Пример #11
0
        private bool TryGetFromCompatibleAggregateStore(string aggregateRootId, Type aggregateRootType,
                                                        ICompatibleStoreHandler aggregateInitHandler, CompatibleStyle compatibleStyle, out IAggregateRoot aggregateRoot)
        {
            aggregateRoot = null;
            var aggregateRootTypeCode = _aggregateRootTypeCodeProvider.GetTypeCode(aggregateRootType);

            if (compatibleStyle == CompatibleStyle.RepositoryOnly)
            {
                // Replay Repository Aggregate Init Event
                DomainEventStream aggregateInitEvent = aggregateInitHandler.GetAggregateRestoreEventStream(aggregateRootId);
                if (aggregateInitEvent != null)
                {
                    if (aggregateInitEvent.AggregateRootId != aggregateRootId)
                    {
                        throw new Exception(string.Format("DomainEventStream.AggregateRootId error: {0}, expected aggregate root id:{1}", aggregateInitEvent.AggregateRootId, aggregateRootId));
                    }
                    aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                    aggregateRoot.RestoreFromEvents(aggregateInitEvent);
                    return(true);
                }
                return(false);
            }
            else if (compatibleStyle == CompatibleStyle.RepositoryThenEventSourcing)
            {
                var versionStart = minVersion;

                // Replay Repository Aggregate Init Event
                //IDomainEvent aggregateInitEvent = _compatibleAggregateStore.GetAggregateInitEvent(aggregateRootType, aggregateRootId);
                DomainEventStream aggregateInitEvent = aggregateInitHandler.GetAggregateRestoreEventStream(aggregateRootId);
                if (aggregateInitEvent != null)
                {
                    if (aggregateInitEvent.AggregateRootId != aggregateRootId)
                    {
                        throw new Exception(string.Format("DomainEventStream.AggregateRootId error: {0}, expected aggregate root id:{1}", aggregateInitEvent.AggregateRootId, aggregateRootId));
                    }
                    aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                    aggregateRoot.RestoreFromEvents(aggregateInitEvent);
                    versionStart = aggregateInitEvent.Version + 1;
                }

                // Replay Event Sourcing Events
                var eventStreams = _eventStore.QueryAggregateEvents(aggregateRootId, aggregateRootTypeCode, versionStart, maxVersion);
                if (eventStreams == null || !eventStreams.Any())
                {
                    if (aggregateRoot != null)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                aggregateRoot.ReplayEvents(eventStreams);
                return(true);
            }
            else //if(compatibleStyle == CompatibleAggregateInitStyle.EventSourcingOnly)
            {
                // Replay Event Sourcing Events
                var versionStart = minVersion;
                var eventStreams = _eventStore.QueryAggregateEvents(aggregateRootId, aggregateRootTypeCode, versionStart, maxVersion);
                if (eventStreams == null || !eventStreams.Any())
                {
                    return(false);
                }
                aggregateRoot = _aggregateRootFactory.CreateAggregateRoot(aggregateRootType);
                aggregateRoot.ReplayEvents(eventStreams);
                return(true);
            }
        }