public async Task WhenMessageIsAppended()
            {
                var mapping       = new EventMapping(EventMapping.DiscoverEventNamesInAssembly(typeof(RoadNetworkEvents).Assembly));
                var settings      = EventsJsonSerializerSettingsProvider.CreateSerializerSettings();
                var archiveStream = new StreamName("archive-1");
                var commandStream = new StreamName("road-network-commands");
                var id            = Guid.NewGuid();
                var reaction      = new ReactionScenarioBuilder()
                                    .Given(new RecordedEvent(archiveStream, new Messages.UploadRoadNetworkChangesArchive {
                    ArchiveId = "123"
                }).WithMessageId(id))
                                    .Then(new RecordedEvent(commandStream, new Messages.UploadRoadNetworkChangesArchive {
                    ArchiveId = "123"
                }).WithMessageId(id).WithMetadata(new { Position = 1 }))
                                    .Build();

                var sut = new Subscriber(_store, commandStream);

                using (sut)
                {
                    sut.Start();

                    //Act
                    foreach (var stream in reaction.Givens.GroupBy(given => given.Stream))
                    {
                        await _store.AppendToStream(
                            stream.Key,
                            ExpectedVersion.NoStream,
                            stream.Select((given, index) => new NewStreamMessage(
                                              Deterministic.Create(Deterministic.Namespaces.Events,
                                                                   $"{given.Stream}-{index}"),
                                              mapping.GetEventName(given.Event.GetType()),
                                              JsonConvert.SerializeObject(given.Event, settings),
                                              given.Metadata != null ? JsonConvert.SerializeObject(given.Metadata, settings) : null
                                              )).ToArray());
                    }


                    //Await
                    var page = await _store.ReadStreamForwards(commandStream, StreamVersion.Start, 1);

                    while (page.Status == PageReadStatus.StreamNotFound)
                    {
                        page = await _store.ReadStreamForwards(commandStream, StreamVersion.Start, 1);
                    }

                    //Assert
                    //Assert.Equal(_messageId, page.Messages[0].MessageId);
                }

                await sut.Disposed;
            }
        public async Task <T> Load <T>(AggregateId <T> aggregateId) where T : AggregateRoot
        {
            var streamId = GetStreamId(aggregateId);

            IList <IDomainEvent> domainEvents = new List <IDomainEvent>();
            ReadStreamPage       readStreamPage;

            do
            {
                readStreamPage = await _streamStore.ReadStreamForwards(streamId, StreamVersion.Start, maxCount : 100);

                var messages = readStreamPage.Messages;
                foreach (var streamMessage in messages)
                {
                    Type type     = DomainEventTypeMappings.Dictionary[streamMessage.Type];
                    var  jsonData = await streamMessage.GetJsonData();

                    var domainEvent = JsonConvert.DeserializeObject(jsonData, type) as IDomainEvent;

                    domainEvents.Add(domainEvent);
                }
            } while (!readStreamPage.IsEnd);

            if (!domainEvents.Any())
            {
                return(null);
            }

            var aggregate = (T)Activator.CreateInstance(typeof(T), true);

            aggregate.Load(domainEvents);

            return(aggregate);
        }
        public async Task <IEnumerable <StreamMessage> > GetAsync(string streamName)
        {
            var       start     = 0;
            const int BatchSize = 500;

            StreamMessagesPage messagesPage;
            var events = new List <StreamMessage>();

            do
            {
                messagesPage = await _streamStore.ReadStreamForwards(streamName, start, BatchSize);

                if (messagesPage.Status == PageReadStatus.StreamNotFound)
                {
                    throw new Exception("Stream not found");
                }

                events.AddRange(
                    messagesPage.Messages);

                start = messagesPage.NextStreamVersion;
            }while (!messagesPage.IsEndOfStream);

            return(events);
        }
Example #4
0
        public async Task <IEnumerable <Event> > GetAllAsync(StreamId streamId, CancellationToken cancellationToken)
        {
            var events      = new List <Event>();
            var loaded      = false;
            var readAllPage = await _streamStore.ReadStreamForwards(streamId, 0, 100, cancellationToken);

            while (!loaded)
            {
                foreach (var message in readAllPage.Messages)
                {
                    var json = await message.GetJsonData(cancellationToken);

                    var data = (Event)_eventSerializer.DeserializeEvent(message.Type, json);
                    data.ExpectedVersion = message.StreamVersion;
                    events.Add(data);
                }

                if (!readAllPage.IsEnd)
                {
                    readAllPage = await readAllPage.ReadNext(cancellationToken);
                }
                else
                {
                    loaded = true;
                }
            }

            return(events);
        }
Example #5
0
File: Remote.cs Project: zedr0n/ZES
        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();
        }
        private async Task <bool> StreamExists(PublicServiceId publicServiceId)
        {
            var pageReadStatus = await _streamStore
                                 .ReadStreamForwards(
                streamId : publicServiceId.ToString(),
                fromVersionInclusive : StreamVersion.Start,
                maxCount : 1,
                prefetchJsonData : false);

            return(pageReadStatus.Status != PageReadStatus.StreamNotFound);
        }
        private async IAsyncEnumerable <object> ReadEvents(string streamId, CancellationToken cancellationToken)
        {
            var page = await _streamStore.ReadStreamForwards(streamId, 0, int.MaxValue, cancellationToken);

            foreach (var message in page.Messages)
            {
                var type = typeof(DoSomething).Assembly.GetType(message.Type);

                yield return(JsonSerializer.Deserialize(await message.GetJsonData(cancellationToken), type));
            }
        }
        public async Task <RoadNetworkChangesArchive> Get(ArchiveId id, CancellationToken ct = default)
        {
            var stream = new StreamName(id);

            if (_map.TryGet(stream, out var entry))
            {
                return((RoadNetworkChangesArchive)entry.Entity);
            }
            var page = await _store.ReadStreamForwards(stream, StreamVersion.Start, 1024, ct);

            if (page.Status == PageReadStatus.StreamNotFound)
            {
                var network = RoadNetworkChangesArchive.Factory();
                _map.Attach(new EventSourcedEntityMapEntry(network, stream, ExpectedVersion.NoStream));
                return(network);
            }
            IEventSourcedEntity entity = RoadNetworkChangesArchive.Factory();
            var messages = new List <object>(page.Messages.Length);

            foreach (var message in page.Messages)
            {
                messages.Add(
                    JsonConvert.DeserializeObject(
                        await message.GetJsonData(ct),
                        _mapping.GetEventType(message.Type),
                        _settings));
            }
            entity.RestoreFromEvents(messages.ToArray());
            while (!page.IsEnd)
            {
                messages.Clear();
                page = await page.ReadNext(ct);

                if (page.Status == PageReadStatus.StreamNotFound)
                {
                    var network = RoadNetworkChangesArchive.Factory();
                    _map.Attach(new EventSourcedEntityMapEntry(network, stream, ExpectedVersion.NoStream));
                    return(network);
                }
                foreach (var message in page.Messages)
                {
                    messages.Add(
                        JsonConvert.DeserializeObject(
                            await message.GetJsonData(ct),
                            _mapping.GetEventType(message.Type),
                            _settings));
                }
                entity.RestoreFromEvents(messages.ToArray());
            }
            _map.Attach(new EventSourcedEntityMapEntry(entity, stream, page.LastStreamVersion));
            return((RoadNetworkChangesArchive)entity);
        }
Example #10
0
        public async Task <Organization> TryGet(OrganizationId id, CancellationToken ct = default)
        {
            var stream = StreamNameFactory(id);

            if (_map.TryGet(stream, out var entry))
            {
                return((Organization)entry.Entity);
            }
            var organization = Organization.Factory();
            var page         = await _store.ReadStreamForwards(stream, StreamVersion.Start, 100, ct);

            if (page.Status == PageReadStatus.StreamNotFound)
            {
                return(null);
            }
            IEventSourcedEntity entity = organization;
            var messages = new List <object>(page.Messages.Length);

            foreach (var message in page.Messages)
            {
                messages.Add(
                    JsonConvert.DeserializeObject(
                        await message.GetJsonData(ct),
                        _mapping.GetEventType(message.Type),
                        _settings));
            }
            entity.RestoreFromEvents(messages.ToArray());
            while (!page.IsEnd)
            {
                messages.Clear();
                page = await page.ReadNext(ct);

                if (page.Status == PageReadStatus.StreamNotFound)
                {
                    return(null);
                }
                foreach (var message in page.Messages)
                {
                    messages.Add(
                        JsonConvert.DeserializeObject(
                            await message.GetJsonData(ct),
                            _mapping.GetEventType(message.Type),
                            _settings));
                }
                entity.RestoreFromEvents(messages.ToArray());
            }
            _map.Attach(new EventSourcedEntityMapEntry(entity, stream, page.LastStreamVersion));
            return(organization);
        }
        public async Task <TodoListState> Load(string aggregateId)
        {
            var stream = await _store.ReadStreamForwards(new StreamId(aggregateId), 0, int.MaxValue, true);

            var aggregate = new TodoListState(aggregateId, stream.LastStreamVersion);

            foreach (var message in stream.Messages)
            {
                var @event = await Deserialize(message);

                aggregate.Apply(@event);
            }

            return(aggregate);
        }
        public async Task <IEnumerable <dynamic> > GetHistory(string persistenceId)
        {
            var history        = new List <dynamic>();
            var streamId       = new StreamId(persistenceId);
            var readStreamPage = await streamStore.ReadStreamForwards(streamId, global::SqlStreamStore.Streams.StreamVersion.Start, int.MaxValue);

            foreach (var message in readStreamPage.Messages)
            {
                var @event = await DeserializeEvent(message);

                history.Add(@event);
            }

            return(history);
        }
Example #13
0
        protected override async Task <List <IDomainEvent> > LoadChangeLog(string streamId)
        {
            var changeLog = new List <IDomainEvent>();
            var page      = await _eventStore.ReadStreamForwards(streamId, 0, int.MaxValue);

            foreach (var message in page.Messages)
            {
                var json = await message.GetJsonData();

                var evt = (IDomainEvent)JsonConvert.DeserializeObject(json, SqlStreamStoreOutbox.SerializerSettings);
                changeLog.Add(evt);
            }

            return(changeLog);
        }
Example #14
0
        public IEnumerable LoadEventsFor(Guid aggregateId, int fromVersion)
        {
            var endOfStream  = false;
            var startVersion = fromVersion;

            while (!endOfStream)
            {
                var stream = _streamStore.ReadStreamForwards(aggregateId.ToString(), startVersion, 10).GetAwaiter().GetResult();
                endOfStream  = stream.IsEnd;
                startVersion = stream.NextStreamVersion;
                foreach (var msg in stream.Messages)
                {
                    yield return(JsonConvert.DeserializeObject(msg.GetJsonData().GetAwaiter().GetResult(), type: Type.GetType(msg.Type)));
                }
            }
        }
        public async Task <T> Get(Func <T> factory)
        {
            var instance = factory();

            var streamId       = new StreamId(instance.PersistenceId);
            var readStreamPage = await streamStore.ReadStreamForwards(streamId, StreamVersion.Start, int.MaxValue);

            foreach (var message in readStreamPage.Messages)
            {
                var eventJson = await message.GetJsonData();

                var eventType = Type.GetType($"EventSourced.Simple.Aggregate.Events.{message.Type}, EventSourced.Simple");
                var @event    = JsonConvert.DeserializeObject(eventJson, eventType);
                instance.OnRecover(@event);
            }

            return((T)instance);
        }
        public IEnumerable <JournalRecord> GetRecords(long fromRecord = 0)
        {
            var pageSize = 20;

            while (true)
            {
                var page = _streamStore.ReadStreamForwards(
                    _streamId, (int)fromRecord, pageSize).Result;
                foreach (var message in page.Messages)
                {
                    yield return(RecordFromStreamMessage(message));
                }
                if (page.IsEnd)
                {
                    break;
                }
                fromRecord += page.Messages.Length;
            }
        }
Example #17
0
        private async Task <List <StreamMessage> > ReadStreamMessages(string streamId, int fromVersionInclusive)
        {
            if (fromVersionInclusive < 0)
            {
                throw new InvalidOperationException("Cannot get version < 0");
            }

            var page = await _store.ReadStreamForwards(streamId, fromVersionInclusive, ReadPageSize);

            var messages = new List <StreamMessage>(page.Messages);

            while (!page.IsEnd)
            {
                page = await page.ReadNext();

                messages.AddRange(page.Messages);
            }

            return(messages);
        }
        public async Task <IList <IDomainEvent> > GetEventsByStreamId(EventStreamId eventStreamId)
        {
            var streamMessages = new List <StreamMessage>();

            ReadStreamPage currentStreamPage;
            var            nextSliceStart = 0;

            do
            {
                currentStreamPage = await _streamStore.ReadStreamForwards(
                    streamId : new StreamId(eventStreamId.StreamName),
                    fromVersionInclusive : nextSliceStart,
                    maxCount : ReadBatchSize);

                nextSliceStart = currentStreamPage.NextStreamVersion;
                streamMessages.AddRange(currentStreamPage.Messages);
            } while (!currentStreamPage.IsEnd);

            return(streamMessages.Select(ConvertStreamMessageToDomainEvent).ToList());
        }
Example #19
0
        protected async Task <TAggregate> Load <TAggregate>(string aggregateId, bool isReadOnly = false) where TAggregate : AggregateState, new()
        {
            var stream = await _store.ReadStreamForwards(new StreamId(aggregateId), 0, int.MaxValue, true);

            var events = new List <object>();

            foreach (var message in stream.Messages)
            {
                var @event = await Deserialize(message);

                events.Add(@event);
            }
            //var events = await Task.WhenAll(stream.Messages.Select(Deserialize));
            var aggregate = AggregateState.Build <TAggregate>(aggregateId, stream.LastStreamVersion, isReadOnly, events);

            if (!isReadOnly)
            {
                _trackedAggregates.Add(aggregate);
            }
            return(aggregate);
        }
Example #20
0
        public async IAsyncEnumerable <object> GetEventsFromStream(string streamId)
        {
            var            stream = new StreamId(streamId);
            ReadStreamPage page;

            var readFrom = StreamVersion.Start;

            do
            {
                page = await _streamStore.ReadStreamForwards(stream, readFrom, 1000);

                foreach (var message in page.Messages)
                {
                    var json = await message.GetJsonData();

                    yield return(Deserialize(TypeCache.GetType(message.Type), json));
                }

                readFrom = page.NextStreamVersion;
            } while (!page.IsEnd);
        }
Example #21
0
        public static async Task <int> DeletedCount(this IStreamStore streamStore, string key)
        {
            var deleted = 0;
            var page    = await streamStore.ReadStreamForwards("$deleted", 0, Configuration.BatchSize);

            while (page.Messages.Length > 0)
            {
                foreach (var m in page.Messages)
                {
                    var json = await m.GetJsonData();

                    if (json.Contains(key))
                    {
                        deleted++;
                    }
                }

                page = await page.ReadNext();
            }

            return(deleted);
        }
Example #22
0
        private IObservable <ICommand> GetCommands(IStream stream)
        {
            var observable = Observable.Create(async(IObserver <ICommand> observer) =>
            {
                var page = await _streamStore.ReadStreamForwards(stream.Key, ExpectedVersion.EmptyStream + 1, Configuration.BatchSize);
                while (page.Messages.Length > 0)
                {
                    foreach (var m in page.Messages)
                    {
                        var data    = await m.GetJsonData();
                        var command = _serializer.Deserialize(data);
                        observer.OnNext(command);
                    }

                    page = await page.ReadNext();
                }

                observer.OnCompleted();
            });

            return(observable);
        }
Example #23
0
        public async Task <StreamEventsPage> ReadStream(
            string streamName, long fromVersion, long maxCount,
            StreamReadDirection direction       = StreamReadDirection.Forward,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var page = await _streamStore
                       .ReadStreamForwards(streamName, (int)fromVersion, (int)maxCount, cancellationToken)
                       .ConfigureAwait(false);

            var events = await Task
                         .WhenAll(page.Messages.Select(streamMessage => _resolveStreamEvent(streamMessage, cancellationToken)))
                         .ConfigureAwait(false);

            return(new StreamEventsPage(
                       streamName: page.StreamId,
                       fromVersion: page.FromStreamVersion,
                       nextVersion: page.NextStreamVersion,
                       lastVersion: page.LastStreamVersion,
                       isEndOfStream: page.IsEnd,
                       events: events,
                       direction: direction));
        }
Example #24
0
        public async Task Transactions()
        {
            decimal balance      = 0;
            var     endOfStream  = false;
            var     startVersion = 0;

            while (endOfStream == false)
            {
                var stream = await _streamStore.ReadStreamForwards(_streamId, startVersion, 10);

                endOfStream  = stream.IsEnd;
                startVersion = stream.NextStreamVersion;

                foreach (var msg in stream.Messages)
                {
                    switch (msg.Type)
                    {
                    case "Deposited":
                        var depositedJson = await msg.GetJsonData();

                        var deposited = JsonConvert.DeserializeObject <Deposited>(depositedJson);
                        Console.WriteLine($"Deposited: {deposited.Amount:C} @ {deposited.DateTime} ({deposited.TransactionId})");
                        balance += deposited.Amount;
                        break;

                    case "Withdrawn":
                        var withdrawnJson = await msg.GetJsonData();

                        var withdrawn = JsonConvert.DeserializeObject <Withdrawn>(withdrawnJson);
                        Console.WriteLine($"Withdrawn: {withdrawn.Amount:C} @ {withdrawn.DateTime} ({withdrawn.TransactionId})");
                        balance -= withdrawn.Amount;
                        break;
                    }
                }
            }

            Console.WriteLine($"Balance: {balance:C}");
        }
        public async Task <IActionResult> GetOutStreamPage(
            Guid id,
            int?start = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var fromVersionInclusive = start ?? StreamVersion.Start;

            var webHooks = await _webHooksRepository.Load(cancellationToken);

            if (!webHooks.TryGet(id, out var w))
            {
                return(NotFound());
            }
            var streamId = w.StreamIds.OutStreamId;
            var page     = await _streamStore
                           .ReadStreamForwards(streamId, fromVersionInclusive, PageSize, true, cancellationToken);

            if (page.Status == PageReadStatus.StreamNotFound)
            {
                return(new ObjectResult(new OutEventsPage
                {
                    Next = StreamVersion.Start
                }));
            }
            var items = page.Messages.Select(m => new OutEventItem
            {
                MessageId  = m.MessageId,
                CreatedUtc = m.CreatedUtc,
                EventName  = m.Type,
                Sequence   = m.StreamVersion
            }).ToArray();

            return(new ObjectResult(new OutEventsPage
            {
                Items = items,
                Next = items.Last().Sequence
            }));
        }
        public static async Task <Queue <StreamMessage> > LoadEvents(this IStreamStore eventStream, Guid id, int batchSize = 100)
        {
            var streamId = new StreamId(id.ToString());

            var  messages = new Queue <StreamMessage>();
            bool haveMoreEvents;
            var  readFromVersion = 0;

            do
            {
                var page = await eventStream.ReadStreamForwards(streamId, readFromVersion, batchSize);

                foreach (var message in page.Messages)
                {
                    messages.Enqueue(message);
                }

                haveMoreEvents  = !page.IsEnd;
                readFromVersion = page.NextStreamVersion;
            } while (haveMoreEvents);

            return(messages);
        }
 public Task <ReadStreamPage> Invoke(IStreamStore streamStore, CancellationToken ct)
 => ReadDirection == Constants.ReadDirection.Forwards
         ? streamStore.ReadStreamForwards(StreamId, _fromVersionInclusive, _maxCount, EmbedPayload, ct)
         : streamStore.ReadStreamBackwards(StreamId, _fromVersionInclusive, _maxCount, EmbedPayload, ct);
Example #28
0
 public Task <ReadStreamPage> ReadStreamForwards(StreamId streamId, int fromVersionInclusive, int maxCount, bool prefetchJsonData = true,
                                                 CancellationToken cancellationToken = new CancellationToken())
 {
     return(_store.ReadStreamForwards(streamId, fromVersionInclusive, maxCount, prefetchJsonData, cancellationToken));
 }
Example #29
0
File: Remote.cs Project: 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);
        }
Example #30
0
        public async Task <RoadNetwork> Get(CancellationToken ct = default)
        {
            if (_map.TryGet(Stream, out var entry))
            {
                return((RoadNetwork)entry.Entity);
            }

            var roadNetwork = RoadNetwork.Factory();

            var(snapshot, version) = await _snapshotReader.ReadSnapshot(ct);

            if (version != ExpectedVersion.NoStream)
            {
                roadNetwork.RestoreFromSnapshot(snapshot);
                version += 1;
            }
            else
            {
                version = StreamVersion.Start;
            }
            var page = await _store.ReadStreamForwards(Stream, version, StreamPageSize, ct);

            if (page.Status == PageReadStatus.StreamNotFound)
            {
                var initial = RoadNetwork.Factory();
                _map.Attach(new EventSourcedEntityMapEntry(initial, Stream, ExpectedVersion.NoStream));
                return(initial);
            }
            IEventSourcedEntity entity = roadNetwork;
            var messages = new List <object>(page.Messages.Length);

            foreach (var message in page.Messages)
            {
                messages.Add(
                    JsonConvert.DeserializeObject(
                        await message.GetJsonData(ct),
                        _mapping.GetEventType(message.Type),
                        _settings));
            }
            entity.RestoreFromEvents(messages.ToArray());
            while (!page.IsEnd)
            {
                messages.Clear();
                page = await page.ReadNext(ct);

                if (page.Status == PageReadStatus.StreamNotFound)
                {
                    var initial = RoadNetwork.Factory();
                    _map.Attach(new EventSourcedEntityMapEntry(initial, Stream, ExpectedVersion.NoStream));
                    return(initial);
                }
                foreach (var message in page.Messages)
                {
                    messages.Add(
                        JsonConvert.DeserializeObject(
                            await message.GetJsonData(ct),
                            _mapping.GetEventType(message.Type),
                            _settings));
                }
                entity.RestoreFromEvents(messages.ToArray());
            }
            _map.Attach(new EventSourcedEntityMapEntry(entity, Stream, page.LastStreamVersion));
            return(roadNetwork);
        }