private async Task <FastForwardResult> FastForward(IStreamStore from, IStreamStore to, string branchId) { var fastForwardResult = new FastForwardResult(); var page = await from.ListStreams(); while (page.StreamIds.Length > 0) { foreach (var s in page.StreamIds.Where(x => x.StartsWith(branchId))) { var localPosition = await from.LastPosition(s); var remotePosition = await to.LastPosition(s); if (localPosition == remotePosition) { continue; } var eventPage = await from.ReadStreamForwards(s, Math.Max(remotePosition + 1, 0), Configuration.BatchSize); var appendMessages = new List <NewStreamMessage>(); if (eventPage.Messages.Length == 0 && localPosition >= ExpectedVersion.EmptyStream) { await to.AppendToStream(s, remotePosition, appendMessages.ToArray()); } var metadata = await from.GetStreamMetadata(s); await to.SetStreamMetadata(s, ExpectedVersion.Any, metadata.MaxAge, metadata.MaxCount, metadata.MetadataJson); while (eventPage.Messages.Length > 0) { appendMessages.Clear(); foreach (var m in eventPage.Messages) { var payload = await m.GetJsonData(); var message = new NewStreamMessage(m.MessageId, m.Type, payload, m.JsonMetadata); appendMessages.Add(message); } var result = await to.AppendToStream(s, remotePosition, appendMessages.ToArray()); fastForwardResult.NumberOfMessages += result.CurrentVersion - Math.Max(remotePosition, ExpectedVersion.EmptyStream); eventPage = await eventPage.ReadNext(); } fastForwardResult.NumberOfStreams++; } page = await page.Next(); } fastForwardResult.ResultStatus = Status.Success; return(fastForwardResult); }
public async Task ShouldAddNewAggregate() { // Arrange var aggregate = new TestAggregate(); // Act await _sut.Save(aggregate); // Assert var streamId = _sut.GetStreamId(aggregate); var streams = await _streamStore.ListStreams(Pattern.StartsWith(streamId)); streams.StreamIds.Length.ShouldBe(1); var events = (await _streamStore.ReadStreamForwards(streamId, StreamVersion.Start, 1)).Messages; (await Task.WhenAll(events.Select(@event => @event.ToEvent(CancellationToken.None)))) .All(@event => @event.GetType() == typeof(TestEvent)).ShouldBeTrue(); }
/// <inheritdoc /> public async Task DeleteBranch(string branchId) { var page = await _streamStore.ListStreams(Configuration.BatchSize); while (page.StreamIds.Length > 0) { foreach (var s in page.StreamIds) { if (!s.StartsWith(branchId) || !s.Contains("Command")) { continue; } await _streamStore.DeleteStream(s); _log.Debug($"Deleted {nameof(ICommand)} stream {s}"); } page = await page.Next(); } }
public Task <ListStreamsPage> Invoke(IStreamStore streamStore, CancellationToken cancellationToken) => streamStore.ListStreams(Pattern, MaxCount, ContinuationToken, cancellationToken);
/// <inheritdoc /> protected override async Task ListStreamsObservable(IObserver <IStream> observer, Func <string, bool> predicate, CancellationToken token) { var page = await _streamStore.ListStreams(Pattern.Anything(), Configuration.BatchSize, default, token);
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); }
public Task <ListStreamsPage> ListStreams(int maxCount = 100, string continuationToken = null, CancellationToken cancellationToken = new CancellationToken()) { return(_store.ListStreams(maxCount, continuationToken, cancellationToken)); }