예제 #1
0
        /// <summary>
        /// Compares the current snapshot with the expected snapshot and applies
        /// the compare rules of the compare actions.
        /// </summary>
        /// <param name="matchOptions">The compare actions, which will be used for special comparion.</param>
        /// <param name="expectedSnapshot">The original snapshot of the current result.</param>
        /// <param name="actualSnapshot">The actual (modifiable) snapshot of the current result.</param>
        public void CompareSnapshots(
            string expectedSnapshot,
            string actualSnapshot,
            Func <MatchOptions, MatchOptions> matchOptions)
        {
            JToken originalActualSnapshotToken = _snapshotSerializer.Deserialize(actualSnapshot);
            JToken actualSnapshotToken         = _snapshotSerializer.Deserialize(actualSnapshot);
            JToken expectedSnapshotToken       = _snapshotSerializer.Deserialize(expectedSnapshot);

            if (matchOptions != null)
            {
                ExecuteFieldMatchActions(
                    originalActualSnapshotToken,
                    actualSnapshotToken,
                    expectedSnapshotToken,
                    matchOptions);
            }

            string actualSnapshotToCompare = _snapshotSerializer
                                             .SerializeJsonToken(actualSnapshotToken);
            string expectedSnapshotToCompare = _snapshotSerializer
                                               .SerializeJsonToken(expectedSnapshotToken);

            _snapshotAssert.Assert(expectedSnapshotToCompare, actualSnapshotToCompare);
        }
예제 #2
0
        private Snapshot Deserialize(Models.Snapshot dto)
        {
            // Todo: Type cache?
            var snapshot = _snapshotSerializer.Deserialize(dto.Content, Type.GetType(dto.Type));

            snapshot.AggregateId = dto.AggregateId;
            snapshot.Version     = dto.Version;

            return(snapshot);
        }
예제 #3
0
                // version has 2 bytes
                //private const int _versionLen = 2;

                // buffer length 4 bytes
                //private const int _bufSizeLen = 4;

                public SnapshotStorageDate(string fileName, ISnapshotSerializer <TKey, TMessage> serializer)
                {
                    if (fileName.IsEmpty())
                    {
                        throw new ArgumentNullException(nameof(fileName));
                    }

                    _fileName   = fileName;
                    _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));

                    if (File.Exists(_fileName))
                    {
                        Debug.WriteLine($"Snapshot (Load): {_fileName}");

                        using (var stream = File.OpenRead(_fileName))
                        {
                            _version = new Version(stream.ReadByte(), stream.ReadByte());

                            while (stream.Position < stream.Length)
                            {
                                var size = stream.Read <int>();

                                var buffer = new byte[size];
                                stream.ReadBytes(buffer, buffer.Length);

                                //var offset = stream.Position;

                                TMessage message;

                                try
                                {
                                    message = _serializer.Deserialize(_version, buffer);
                                }
                                catch (Exception ex)
                                {
                                    ex.LogError();
                                    continue;
                                }

                                var key = _serializer.GetKey(message);

                                _snapshots.Add(key, message);
                                _buffers.Add(key, buffer);
                            }

                            //_currOffset = stream.Length;
                        }
                    }
                    else
                    {
                        _version = _serializer.Version;

                        //_currOffset = _versionLen;
                    }
                }
예제 #4
0
        /// <summary>
        /// 从给定的快照数据对象萃取得到快照对象。
        /// </summary>
        /// <param name="serializer"></param>
        /// <param name="dataObject">快照数据对象</param>
        /// <returns>快照对象</returns>
        public static ISnapshot <TAggregateRootId> ExtractSnapshot <TAggregateRootId>(this ISnapshotSerializer serializer, SnapshotDataObject <TAggregateRootId> dataObject)
        {
            var snapshotType = Type.GetType(dataObject.SnapshotType);

            if (snapshotType == null)
            {
                return(null);
            }

            return((ISnapshot <TAggregateRootId>)serializer.Deserialize(snapshotType, dataObject.SnapshotData));
        }
예제 #5
0
 /// <summary>
 /// Extracts the snapshot from the current snapshot data object.
 /// </summary>
 /// <returns>The snapshot instance.</returns>
 public ISnapshot ExtractSnapshot()
 {
     try
     {
         Type snapshotType = Type.GetType(SnapshotType);
         if (snapshotType == null)
         {
             return(null);
         }
         return((ISnapshot)serializer.Deserialize(snapshotType, this.SnapshotData));
     }
     catch
     {
         throw;
     }
 }
예제 #6
0
        void ISnapshotStorage.Init()
        {
            if (!Directory.Exists(_path))
            {
                Directory.CreateDirectory(_path);
            }

            var fileName = Path.Combine(_path, _serializer.FileName);

            byte[] buffer;

            Version version;

            if (File.Exists(fileName))
            {
                using (var stream = File.OpenRead(fileName))
                {
                    version = new Version(stream.ReadByte(), stream.ReadByte());

                    buffer = new byte[_serializer.GetSnapshotSize(version)];

                    while (stream.Position < stream.Length)
                    {
                        stream.ReadBytes(buffer, buffer.Length);

                        var message = _serializer.Deserialize(version, buffer);

                        _snapshots.Add(_serializer.GetSecurityId(message), Tuple.Create(stream.Position - buffer.Length, message));
                    }

                    _maxOffset = stream.Position;
                }
            }
            else
            {
                version    = _serializer.Version;
                _maxOffset = 2;                 // version bytes

                buffer = new byte[_serializer.GetSnapshotSize(version)];
            }

            _snapshotSize = buffer.Length;

            var isFlushing = false;

            ThreadingHelper.Timer(() =>
            {
                Tuple <long, TMessage>[] changed;

                lock (_snapshots.SyncRoot)
                {
                    if (_dirtySecurities.Count == 0)
                    {
                        return;
                    }

                    if (isFlushing)
                    {
                        return;
                    }

                    isFlushing = true;

                    changed = _dirtySecurities.Select(id =>
                    {
                        var tuple = _snapshots[id];
                        return(Tuple.Create(tuple.Item1, (TMessage)tuple.Item2.Clone()));
                    }).OrderBy(t => t.Item1).ToArray();

                    _dirtySecurities.Count = 0;
                }

                try
                {
                    using (var stream = File.OpenWrite(fileName))
                    {
                        if (stream.Length == 0)
                        {
                            stream.WriteByte((byte)version.Major);
                            stream.WriteByte((byte)version.Minor);
                        }

                        foreach (var tuple in changed)
                        {
                            stream.Seek(tuple.Item1, SeekOrigin.Begin);

                            Array.Clear(buffer, 0, buffer.Length);
                            _serializer.Serialize(version, tuple.Item2, buffer);

                            stream.Write(buffer, 0, buffer.Length);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.LogError();
                }

                lock (_snapshots.SyncRoot)
                    isFlushing = false;
            }).Interval(TimeSpan.FromSeconds(10));
        }
예제 #7
0
        /// <summary>
        /// Retrieves an aggregate, load your historical events and add to tracking.
        /// </summary>
        /// <typeparam name="TAggregate"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="AggregateNotFoundException"></exception>
        public async Task <TAggregate> GetByIdAsync <TAggregate>(Guid id) where TAggregate : Aggregate, new()
        {
            _logger.LogDebug($"Getting aggregate '{typeof(TAggregate).FullName}' with identifier: '{id}'.");

            var aggregate = _aggregateTracker.GetById <TAggregate>(id);

            _logger.LogDebug("Returning an aggregate tracked.");

            if (aggregate != null)
            {
                RegisterForTracking(aggregate);

                return(aggregate);
            }

            aggregate = new TAggregate();

            IEnumerable <ICommitedEvent> events;

            _logger.LogDebug("Checking if aggregate has snapshot support.");

            if (_snapshotStrategy.CheckSnapshotSupport(aggregate.GetType()))
            {
                var snapshotAggregate = aggregate as ISnapshotAggregate;
                if (snapshotAggregate != null)
                {
                    int version  = 0;
                    var snapshot = await _eventStore.GetLatestSnapshotByIdAsync(id).ConfigureAwait(false);

                    if (snapshot != null)
                    {
                        version = snapshot.AggregateVersion;

                        _logger.LogDebug("Restoring snapshot.");

                        var snapshotRestore = _snapshotSerializer.Deserialize(snapshot);

                        snapshotAggregate.Restore(snapshotRestore);

                        _logger.LogDebug("Snapshot restored.");
                    }

                    events = await _eventStore.GetEventsForwardAsync(id, version).ConfigureAwait(false);

                    LoadAggregate(aggregate, events);
                }
            }
            else
            {
                events = await _eventStore.GetAllEventsAsync(id).ConfigureAwait(false);

                LoadAggregate(aggregate, events);
            }

            if (aggregate.Id.Equals(Guid.Empty))
            {
                _logger.LogError($"The aggregate ({typeof(TAggregate).FullName} {id}) was not found.");

                throw new AggregateNotFoundException(typeof(TAggregate).Name, id);
            }

            RegisterForTracking(aggregate);

            return(aggregate);
        }