예제 #1
0
파일: Remote.cs 프로젝트: zedr0n/ZES
        private async Task <bool> Validate(
            IStreamStore from,
            IStreamStore to,
            string branchId,
            bool failOnNoStream = false)
        {
            await _messageQueue.UncompletedMessagesOnBranch(branchId).FirstAsync(s => s == 0)
            .Timeout(Configuration.Timeout);

            var page = await from.ListStreams();

            while (page.StreamIds.Length > 0)
            {
                foreach (var s in page.StreamIds.Where(x => !x.StartsWith("$")))
                {
                    var source = await from.GetStream(s, _serializer);

                    if (source.Timeline != branchId)
                    {
                        continue;
                    }

                    var target = await to.GetStream(s, _serializer);

                    if (target == null) // stream exists but some of the ancestors do not
                    {
                        return(false);
                    }

                    if (failOnNoStream && target.Version == ExpectedVersion.NoStream)
                    {
                        _log.Warn($"Stream {s} does not exist on target, probably due to missing ancestors", this);
                        return(false);
                    }

                    if (source.Version <= target.Version && source.Version > ExpectedVersion.EmptyStream)
                    {
                        var fromMessage = (await from.ReadStreamBackwards(s, StreamVersion.End, 1)).Messages.SingleOrDefault();
                        var toMessage   = (await to.ReadStreamForwards(s, source.ReadPosition(source.Version), 1)).Messages.SingleOrDefault();

                        if (fromMessage.MessageId == toMessage.MessageId)
                        {
                            return(true);
                        }
                        _log.Warn(
                            $"Message doesn't match with remote for stream {s}@{source.Version} : " +
                            $"{fromMessage.MessageId} != {toMessage.MessageId}", this);
                        return(false);
                    }

                    var parent = source.Parent;
                    while (parent != null && parent.Version > ExpectedVersion.EmptyStream)
                    {
                        if (!await Validate(from, to, parent.Timeline, true))
                        {
                            return(false);
                        }

                        parent = parent.Parent;
                    }
                }

                page = await page.Next();
            }

            return(true);
        }