Пример #1
0
        public void SerializeSnapshot(ISnapshot snap, Stream stream)
        {
            snap.AcquireReference();
            try
            {
                _sentSnapshot.Add(snap.SnapshotSeq, snap);
            }
            catch (Exception e)
            {
                int i = 0;
                i++;
            }
            _snapshotQueue.Enqueue(snap.SnapshotSeq);
            ISnapshot baseSnap = GetBaseSnapshot(AckedSnapshotId);

            if (baseSnap == null)
            {
                _emptySnapshot.SnapshotSeq = -1;
                _snapSerializer.Serialize(_emptySnapshot, snap, stream);
                _lastAllSnapShotId   = snap.SnapshotSeq;
                _lastAllSnapShotTime = snap.ServerTime;
                _isSendAll           = true;
                _logger.Warn("send full snapshot!");
                FullCount++;
            }
            else
            {
                _snapSerializer.Serialize(baseSnap, snap, stream);
                _isSendAll = false;
                DiffCount++;
            }

            ClearOldSnapshot(AckedSnapshotId);
            ClearSnapshotWhenLimitExceeded();
        }
Пример #2
0
        // Todo: Do this lazy and out of session? Possible future performance optimization.
        public async Task Save(Snapshot snapshot, Guid?sessionKey)
        {
            using (var context = await _frameworkContextFactor.CreateContext(sessionKey))
            {
                var existingSnapshot = context.Snapshots.SingleOrDefault(s => s.AggregateId == snapshot.AggregateId);

                if (existingSnapshot != null)
                {
                    existingSnapshot.Version = snapshot.Version;
                    existingSnapshot.Type    = snapshot.GetType().AssemblyQualifiedName;
                    existingSnapshot.Content = _snapshotSerializer.Serialize(snapshot);
                }
                else
                {
                    context.Snapshots.Add(new Models.Snapshot
                    {
                        AggregateId = snapshot.AggregateId,
                        Version     = snapshot.Version,
                        Type        = snapshot.GetType().AssemblyQualifiedName,
                        Content     = _snapshotSerializer.Serialize(snapshot),
                    });
                }

                await context.SaveChangesAsync(); // Todo: CT
            }
        }
Пример #3
0
                public void FlushChanges()
                {
                    // TODO Optimize memory

                    IEnumerable <byte[]> buffers;

                    lock (_snapshots.SyncRoot)
                    {
                        if (!_resetFile)
                        {
                            if (_dirtyKeys.Count == 0)
                            {
                                return;
                            }

                            foreach (var key in _dirtyKeys)
                            {
                                _buffers[key] = _serializer.Serialize(_version, _snapshots[key]);
                            }
                        }
                        else
                        {
                            _buffers.Clear();

                            foreach (var pair in _snapshots)
                            {
                                _buffers.Add(pair.Key, _serializer.Serialize(_version, pair.Value));
                            }
                        }

                        _dirtyKeys.Clear();

                        buffers = _buffers.Values.ToArray();
                    }

                    Directory.CreateDirectory(Path.GetDirectoryName(_fileName));

                    Debug.WriteLine($"Snapshot (Save): {_fileName}");

                    if (_disabled)
                    {
                        Debug.WriteLine($"Snapshot !! DISABLED !!: {_fileName}");
                        return;
                    }

                    using (var stream = new FileStream(_fileName, FileMode.Create, FileAccess.Write))
                    {
                        stream.WriteByte((byte)_version.Major);
                        stream.WriteByte((byte)_version.Minor);

                        foreach (var buffer in buffers)
                        {
                            stream.Write(buffer);
                        }
                    }
                }
Пример #4
0
        /// <summary>
        /// Creates the snapshot data object from the aggregate root.
        /// </summary>
        /// <param name="aggregateRoot">The aggregate root for which the snapshot is being created.</param>
        /// <returns>The snapshot data object.</returns>
        public static SnapshotDataObject CreateFromAggregateRoot(ISourcedAggregateRoot aggregateRoot)
        {
            ISnapshotSerializer serializer = null;

            string eventSerializerTypeName = ConfigurationManager.AppSettings["napshotSerializer"];

            if (eventSerializerTypeName == null)
            {
                serializer = new SnapshotXmlSerializer();
            }
            else
            {
                Type serializerType = Type.GetType(eventSerializerTypeName);
                if (serializerType == null)
                {
                    throw new InfrastructureException("The serializer defined by type '{0}' doesn't exist.", eventSerializerTypeName);
                }
                serializer = (ISnapshotSerializer)Activator.CreateInstance(serializerType);
            }

            ISnapshot snapshot = aggregateRoot.CreateSnapshot();

            return(new SnapshotDataObject
            {
                AggregateRootId = aggregateRoot.Id,
                AggregateRootType = aggregateRoot.GetType().AssemblyQualifiedName,
                Version = aggregateRoot.Version,
                SnapshotType = snapshot.GetType().AssemblyQualifiedName,
                Timestamp = snapshot.Timestamp,
                SnapshotData = serializer.Serialize(snapshot)
            });
        }
Пример #5
0
        /// <summary>
        /// 为给定的聚合根实体创建快照数据对象。
        /// </summary>
        /// <param name="serializer"></param>
        /// <param name="aggregateRoot">快照为该聚合根对象创建。</param>
        /// <returns>快照数据对象。</returns>
        public static SnapshotDataObject <TAggregateRootId> CreateFromAggregateRoot <TAggregateRootId>(this ISnapshotSerializer serializer, ISourcedAggregateRoot <TAggregateRootId> aggregateRoot)
        {
            var snapshot = aggregateRoot.CreateSnapshot();

            return(new SnapshotDataObject <TAggregateRootId>
            {
                AggregateRootId = aggregateRoot.Id,
                AggregateRootType = aggregateRoot.GetType().AssemblyQualifiedName,
                Version = aggregateRoot.Version,
                Branch = Constants.ApplicationRuntime.DefaultBranch,
                SnapshotType = snapshot.GetType().AssemblyQualifiedName,
                Timestamp = snapshot.Timestamp,
                SnapshotData = serializer.Serialize(snapshot)
            });
        }
Пример #6
0
        public static async Task TakeSnapshot(this Aggregate aggregate,
                                              IEventStore eventStore,
                                              ISnapshotSerializer snapshotSerializer)
        {
            var snapshot = ((ISnapshotAggregate)aggregate).CreateSnapshot();

            var metadatas = new[]
            {
                new KeyValuePair <string, object>(MetadataKeys.AggregateId, aggregate.Id),
                new KeyValuePair <string, object>(MetadataKeys.AggregateSequenceNumber, aggregate.Sequence),
                new KeyValuePair <string, object>(MetadataKeys.SnapshotId, Guid.NewGuid()),
                new KeyValuePair <string, object>(MetadataKeys.SnapshotClrType, snapshot.GetType().AssemblyQualifiedName),
                new KeyValuePair <string, object>(MetadataKeys.SnapshotName, snapshot.GetType().Name),
            };

            var serializedSnapshot = snapshotSerializer.Serialize(aggregate, snapshot, metadatas);

            await eventStore.SaveSnapshotAsync(serializedSnapshot).ConfigureAwait(false);
        }
Пример #7
0
        /// <summary>
        /// Creates the snapshot data object from the aggregate root.
        /// </summary>
        /// <param name="aggregateRoot">The aggregate root for which the snapshot is being created.</param>
        /// <returns>The snapshot data object.</returns>
        public static SnapshotDataObject CreateFromAggregateRoot(ISourcedAggregateRoot aggregateRoot)
        {
            ISnapshotSerializer serializer = null;

            ApworksConfigSection config = AppRuntime.Instance.CurrentApplication.ConfigSource.Config;

            if (config.Serializers == null ||
                config.Serializers.SnapshotSerializer == null ||
                string.IsNullOrEmpty(config.Serializers.SnapshotSerializer.Provider) ||
                string.IsNullOrWhiteSpace(config.Serializers.SnapshotSerializer.Provider))
            {
                serializer = new SnapshotXmlSerializer();
            }
            else
            {
                string typeName       = config.Serializers.SnapshotSerializer.Provider;
                Type   serializerType = Type.GetType(typeName);
                if (serializerType == null)
                {
                    throw new InfrastructureException("The serializer defined by type '{0}' doesn't exist.", typeName);
                }
                serializer = (ISnapshotSerializer)Activator.CreateInstance(serializerType);
            }

            ISnapshot snapshot = aggregateRoot.CreateSnapshot();

            return(new SnapshotDataObject
            {
                AggregateRootID = aggregateRoot.ID,
                AggregateRootType = aggregateRoot.GetType().AssemblyQualifiedName,
                Version = aggregateRoot.Version,
                Branch = Constants.ApplicationRuntime.DefaultBranch,
                SnapshotType = snapshot.GetType().AssemblyQualifiedName,
                Timestamp = snapshot.Timestamp,
                SnapshotData = serializer.Serialize(snapshot)
            });
        }
Пример #8
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));
        }
Пример #9
0
                public void FlushChanges()
                {
                    Tuple <long, byte[]>[] changed;

                    lock (_snapshots.SyncRoot)
                    {
                        if (!_resetFile)
                        {
                            if (_dirtyKeys.Count == 0)
                            {
                                return;
                            }

                            changed = _dirtyKeys.Select(key =>
                            {
                                var buffer = _serializer.Serialize(_version, _snapshots[key]);

                                if (!_offsets.TryGetValue(key, out var offset))
                                {
                                    offset = _currOffset;
                                    _offsets.Add(key, offset);
                                    _currOffset += _bufSizeLen + buffer.Length;
                                }

                                return(Tuple.Create(offset, buffer));
                            }).OrderBy(t => t.Item1).ToArray();
                        }
                        else
                        {
                            _offsets.Clear();
                            _currOffset = _versionLen;

                            changed = _snapshots.Select(pair =>
                            {
                                var buffer = _serializer.Serialize(_version, pair.Value);

                                var offset = _currOffset;
                                _offsets.Add(pair.Key, offset);
                                _currOffset += _bufSizeLen + buffer.Length;

                                return(Tuple.Create(offset, buffer));
                            }).OrderBy(t => t.Item1).ToArray();
                        }

                        _dirtyKeys.Clear();
                    }

                    Debug.WriteLine($"Snapshot (Save): {_fileName}");

                    Directory.CreateDirectory(Path.GetDirectoryName(_fileName));

                    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);
                            stream.Write(tuple.Item2);
                        }
                    }
                }
Пример #10
0
 private Task saveSnapshotToFile(object snapshot, string fileName) => _snapshotSerializer.Serialize(snapshot, fileName);