Exemplo n.º 1
0
        private void LoadEventIndexData()
        {
            var chunks         = _eventIndexChunkManager.GetAllChunks();
            var count          = 0L;
            var stopWatch      = new Stopwatch();
            var totalStopWatch = new Stopwatch();

            totalStopWatch.Start();
            foreach (Chunk chunk in chunks)
            {
                stopWatch.Restart();
                _logger.Info(chunk);
                var dataPosition = chunk.ChunkHeader.ChunkDataStartPosition;
                var recordQueue  = new Queue <IndexRecord>();
                while (true)
                {
                    var record = _eventIndexChunkReader.TryReadAt(dataPosition, ReadIndexRecord, false);
                    if (record == null)
                    {
                        break;
                    }
                    if (string.IsNullOrEmpty(record.IndexInfo))
                    {
                        continue;
                    }
                    var indexArray = record.IndexInfo.Split(IndexSeparator);
                    foreach (var index in indexArray)
                    {
                        if (string.IsNullOrEmpty(index))
                        {
                            continue;
                        }
                        var itemArray       = index.Split(IndexContentSeparator);
                        var aggregateRootId = itemArray[0];
                        _aggregateLatestVersionDict[aggregateRootId] = new AggregateLatestVersionData
                        {
                            Version     = int.Parse(itemArray[1]),
                            LogPosition = long.Parse(itemArray[2])
                        };
                        count++;
                        if (count % 1000000 == 0)
                        {
                            _logger.Info("Event index loaded: " + count);
                        }
                    }
                    dataPosition += record.RecordSize + 4 + 4;
                }
                _logger.Info("Event index chunk read complete, timeSpent: " + stopWatch.Elapsed.TotalSeconds);
            }
            _logger.Info("Event index chunk read all complete, total timeSpent: " + totalStopWatch.Elapsed.TotalSeconds);
            _isEventIndexLoaded = true;
            if (_isCommandIndexLoaded)
            {
                _loadIndexWaitHandle.Set();
            }
        }
Exemplo n.º 2
0
        private void RefreshMemoryCache(string aggregateRootId, ref AggregateLatestVersionData aggregateLatestVersionData, EventStreamRecord record)
        {
            if (aggregateLatestVersionData != null)
            {
                var oldLastActiveTimestamp = aggregateLatestVersionData.LastActiveTimestamp;
                aggregateLatestVersionData.Update(record.LogPosition, record.Version);
                var newLastActiveTimestamp = aggregateLatestVersionData.LastActiveTimestamp;
                _aggregateIndexCacheDict.UpdateTimeKeyDict(aggregateRootId, oldLastActiveTimestamp, newLastActiveTimestamp);
            }
            else
            {
                aggregateLatestVersionData = new AggregateLatestVersionData(record.LogPosition, record.Version);
                _aggregateIndexCacheDict.AddOrUpdate(aggregateRootId, aggregateLatestVersionData);
            }

            _commandIndexCacheDict.AddOrUpdate(record.CommandId, new CommandIndexData(record.CommandCreateTimestamp));
        }
Exemplo n.º 3
0
 private bool CheckAggregateRootLatestVersionMatch(string aggregateRootId, long firstInputEventVersion, out AggregateLatestVersionData aggregateLatestVersionData)
 {
     aggregateLatestVersionData = GetAggregateRootLatestVersionData(aggregateRootId);
     if (aggregateLatestVersionData != null)
     {
         if (aggregateLatestVersionData.Version + 1 != firstInputEventVersion)
         {
             return(false);
         }
     }
     else if (firstInputEventVersion != 1)
     {
         return(false);
     }
     return(true);
 }
Exemplo n.º 4
0
        private bool CheckAggregateEvents(string aggregateRootId, IList <IEventStream> eventStreamList, EventAppendResult eventAppendResult, out AggregateLatestVersionData aggregateLatestVersionData)
        {
            aggregateLatestVersionData = null;

            //检查版本号是否连续
            if (!IsEventStreamVersionSequential(aggregateRootId, eventStreamList))
            {
                eventAppendResult.DuplicateEventAggregateRootIdList.Add(aggregateRootId);
                return(false);
            }

            //检查命令是否重复
            var duplicatedCommandIdList = CheckDuplicatedCommands(eventStreamList);

            if (duplicatedCommandIdList.Count > 0)
            {
                eventAppendResult.DuplicateCommandAggregateRootIdList.Add(aggregateRootId, duplicatedCommandIdList);
                return(false);
            }

            //检查版本号是否是基于当前聚合根最新的版本号而进行的修改
            if (!CheckAggregateRootLatestVersionMatch(aggregateRootId, eventStreamList.First().Version, out aggregateLatestVersionData))
            {
                eventAppendResult.DuplicateEventAggregateRootIdList.Add(aggregateRootId);
                return(false);
            }

            return(true);
        }
Exemplo n.º 5
0
        public EventAppendResult AppendEventStream(IEventStream eventStream)
        {
            lock (_lockObj)
            {
                //判断命令是否重复
                var commandCacheKey = BuildCommandCacheKey(eventStream.CommandCreateTimestamp);
                if (_commandIndexDict.TryGetValue(commandCacheKey, out ConcurrentDictionary <string, byte> commandIndexDict))
                {
                    if (commandIndexDict.ContainsKey(eventStream.CommandId))
                    {
                        return(EventAppendResult.DuplicateCommand);
                    }
                }

                //判断版本号是否冲突,使用内存中仅保留每个聚合根最新版本的字典来实现
                if (_aggregateLatestVersionDict.TryGetValue(eventStream.AggregateRootId, out AggregateLatestVersionData aggregateLatestVersionData))
                {
                    if (eventStream.Version != (aggregateLatestVersionData.Version + 1))
                    {
                        return(EventAppendResult.InvalidEventVersion);
                    }
                }
                else if (eventStream.Version != 1)
                {
                    return(EventAppendResult.InvalidEventVersion);
                }

                //写入eventStream到文件
                var record = new EventStreamRecord
                {
                    AggregateRootId        = eventStream.AggregateRootId,
                    AggregateRootType      = eventStream.AggregateRootType,
                    Version                = eventStream.Version,
                    CommandId              = eventStream.CommandId,
                    Timestamp              = eventStream.Timestamp,
                    CommandCreateTimestamp = eventStream.CommandCreateTimestamp,
                    Events = eventStream.Events
                };
                if (aggregateLatestVersionData != null)
                {
                    record.PreviousRecordLogPosition = aggregateLatestVersionData.LogPosition;
                }
                _eventDataChunkWriter.Write(record);

                //更新聚合根最新的事件版本
                if (aggregateLatestVersionData != null)
                {
                    aggregateLatestVersionData.Version     = record.Version;
                    aggregateLatestVersionData.LogPosition = record.LogPosition;
                }
                else
                {
                    aggregateLatestVersionData = new AggregateLatestVersionData
                    {
                        Version     = record.Version,
                        LogPosition = record.LogPosition
                    };
                    _aggregateLatestVersionDict[eventStream.AggregateRootId] = aggregateLatestVersionData;
                }

                //添加命令索引到内存字典
                _commandIndexDict
                .GetOrAdd(commandCacheKey, k => new ConcurrentDictionary <string, byte>())
                .TryAdd(eventStream.CommandId, 1);

                //添加事件到事件队列,以便进行异步持久化事件索引和命令索引
                _eventStreamRecordQueue.Enqueue(record);

                return(EventAppendResult.Success);
            }
        }