private async Task <AllMessagesPage> FilterExpired(
            AllMessagesPage allMessagesPage,
            CancellationToken cancellationToken)
        {
            var valid      = new List <StreamMessage>();
            var currentUtc = GetUtcNow();

            foreach (var streamMessage in allMessagesPage.Messages)
            {
                if (streamMessage.StreamId.StartsWith("$"))
                {
                    valid.Add(streamMessage);
                    continue;
                }
                var maxAge = await _metadataMaxAgeCache.GetMaxAge(streamMessage.StreamId, cancellationToken);

                if (!maxAge.HasValue)
                {
                    valid.Add(streamMessage);
                    continue;
                }
                if (streamMessage.CreatedUtc.AddSeconds(maxAge.Value) > currentUtc)
                {
                    valid.Add(streamMessage);
                }
                else
                {
                    PurgeExpiredMessage(streamMessage);
                }
            }
            return(new AllMessagesPage(
                       allMessagesPage.FromPosition,
                       allMessagesPage.NextPosition,
                       allMessagesPage.IsEnd,
                       allMessagesPage.Direction,
                       valid.ToArray()));
        }
        protected override Task <AllMessagesPage> ReadAllBackwardsInternal(
            long fromPositionExclusive,
            int maxCount,
            CancellationToken cancellationToken)
        {
            GuardAgainstDisposed();

            using (_lock.UseReadLock())
            {
                if (fromPositionExclusive == Position.End)
                {
                    fromPositionExclusive = _allStream.Last.Value.Position;
                }

                // Find the node to start from (it may not be equal to the exact position)
                var current = _allStream.First;
                if (current.Next == null) //Empty store
                {
                    return(Task.FromResult(
                               new AllMessagesPage(Position.Start, Position.Start, true, ReadDirection.Backward)));
                }

                var previous = current.Previous;
                while (current.Value.Position < fromPositionExclusive)
                {
                    if (current.Next == null) // fromPosition is past end of store
                    {
                        return(Task.FromResult(
                                   new AllMessagesPage(fromPositionExclusive,
                                                       fromPositionExclusive,
                                                       true,
                                                       ReadDirection.Backward)));
                    }
                    previous = current;
                    current  = current.Next;
                }

                var messages = new List <StreamMessage>();
                while (maxCount > 0 && current != _allStream.First)
                {
                    var message = new StreamMessage(
                        current.Value.StreamId,
                        current.Value.MessageId,
                        current.Value.StreamVersion,
                        current.Value.Position,
                        current.Value.Created,
                        current.Value.Type,
                        current.Value.JsonData,
                        current.Value.JsonMetadata);
                    messages.Add(message);
                    maxCount--;
                    previous = current;
                    current  = current.Previous;
                }

                bool isEnd;
                if (previous == null || previous.Value.Position == 0)
                {
                    isEnd = true;
                }
                else
                {
                    isEnd = false;
                }
                var nextCheckPoint = isEnd
                    ? 0
                    : current.Value.Position;

                fromPositionExclusive = messages.Any() ? messages[0].Position : 0;

                var page = new AllMessagesPage(
                    fromPositionExclusive,
                    nextCheckPoint,
                    isEnd,
                    ReadDirection.Backward,
                    messages.ToArray());

                return(Task.FromResult(page));
            }
        }