示例#1
0
        private async Task Process(Tracked <IStream> trackedStream)
        {
            var s = trackedStream.Value;

            if (s.Version == ExpectedVersion.NoStream)
            {
                trackedStream.Complete();
                return;
            }

            if (trackedStream.Completed.IsCompleted)
            {
                return;
            }

            var version     = _versions.GetOrAdd(s.Key, ExpectedVersion.EmptyStream);
            var origVersion = version;

            // read from latest snapshot
            var snapshotVersion = s.SnapshotVersion;

            if (version < snapshotVersion && _projection.Latest > s.SnapshotTimestamp)
            {
                version = snapshotVersion - 1;
            }

            if (s.Version <= ExpectedVersion.EmptyStream)
            {
                s.Version = 0;
            }

            if (version > s.Version)
            {
                _log?.Warn($"Stream {s.Key} update is version {s.Version}, behind projection version {version}", GetDetailedName());
            }

            if (version < s.Version)
            {
                var t = await _eventStore.ReadStream <IEvent>(s, version + 1)
                        .TakeWhile(_ => !_token.IsCancellationRequested)
                        .Select(e => _projection.When(e))
                        .ToList()
                        .Timeout(Configuration.Timeout)
                        .LastOrDefaultAsync();

                version += t.Count;
                await Task.WhenAll(t);

                _log?.Debug($"{s.Key}@{s.Version} <- {version}", $"{Parents.Select(p => p.Name).Aggregate((a, n) => a + n)}->{Name}");

                if (!_versions.TryUpdate(s.Key, version, origVersion))
                {
                    throw new InvalidOperationException("Failed updating concurrent versions of projections");
                }
            }

            trackedStream.Complete();
        }