protected override Task <StreamMessagesPage> ReadStreamBackwardsInternal(
            string streamId,
            int fromVersionInclusive,
            int count,
            CancellationToken cancellationToken)
        {
            GuardAgainstDisposed();

            using (_lock.UseReadLock())
            {
                InMemoryStream stream;
                if (!_streams.TryGetValue(streamId, out stream))
                {
                    var notFound = new StreamMessagesPage(streamId,
                                                          PageReadStatus.StreamNotFound,
                                                          fromVersionInclusive,
                                                          -1,
                                                          -1,
                                                          ReadDirection.Backward,
                                                          true);
                    return(Task.FromResult(notFound));
                }

                var events = new List <StreamMessage>();
                var i      = fromVersionInclusive == StreamVersion.End ? stream.Events.Count - 1 : fromVersionInclusive;
                while (i >= 0 && count > 0)
                {
                    var inMemorymessage = stream.Events[i];
                    var message         = new StreamMessage(
                        streamId,
                        inMemorymessage.MessageId,
                        inMemorymessage.StreamVersion,
                        inMemorymessage.Position,
                        inMemorymessage.Created,
                        inMemorymessage.Type,
                        inMemorymessage.JsonData,
                        inMemorymessage.JsonMetadata);
                    events.Add(message);

                    i--;
                    count--;
                }

                var lastStreamVersion = stream.Events.Last().StreamVersion;
                var nextStreamVersion = events.Last().StreamVersion - 1;
                var endOfStream       = nextStreamVersion < 0;

                var page = new StreamMessagesPage(
                    streamId,
                    PageReadStatus.Success,
                    fromVersionInclusive,
                    nextStreamVersion,
                    lastStreamVersion,
                    ReadDirection.Backward,
                    endOfStream,
                    events.ToArray());

                return(Task.FromResult(page));
            }
        }
 public ReadStreamTheory(
     string streamId,
     int start,
     int pageSize,
     StreamMessagesPage expectedStreamMessagesPage)
 {
     StreamId = streamId;
     Start    = start;
     PageSize = pageSize;
     ExpectedStreamMessagesPage = expectedStreamMessagesPage;
 }
        private async Task <StreamMessagesPage> FilterExpired(
            StreamMessagesPage page,
            CancellationToken cancellationToken)
        {
            if (page.StreamId.StartsWith("$"))
            {
                return(page);
            }
            var maxAge = await _metadataMaxAgeCache.GetMaxAge(page.StreamId, cancellationToken);

            if (!maxAge.HasValue)
            {
                return(page);
            }
            var currentUtc = GetUtcNow();
            var valid      = new List <StreamMessage>();

            foreach (var message in page.Messages)
            {
                if (message.CreatedUtc.AddSeconds(maxAge.Value) > currentUtc)
                {
                    valid.Add(message);
                }
                else
                {
                    PurgeExpiredMessage(message);
                }
            }
            return(new StreamMessagesPage(
                       page.StreamId,
                       page.Status,
                       page.FromStreamVersion,
                       page.NextStreamVersion,
                       page.LastStreamVersion,
                       page.ReadDirection,
                       page.IsEndOfStream,
                       valid.ToArray()));
        }