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); }
/// <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); }
/// <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); }
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); }
/// <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); }
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); } }
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); } } } }
/// <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(); } } } }
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); } }