public async Task RemoveFromStart(ITransaction tx, string key, int countToRemove = 1)
        {
            var metadata = await GetMetadataAsync(tx, key).ConfigureAwait(false);

            var from  = metadata.From;
            var count = metadata.Count;

            if (countToRemove > count)
            {
                throw new InvalidOperationException($"Trying to remove {countToRemove} entries from {_name} with only {count} messages");
            }
            for (var i = 0; i < countToRemove; i++)
            {
                var listKey = new ReliableListKey {
                    Key = key, Id = from
                };
                await _valueStore.TryRemoveAsync(tx, listKey).ConfigureAwait(false);

                from++;
                count--;
            }
            var updatedMetadata = new ReliableListMetaData {
                From = from, Count = count
            };

            await UpdateMetadataAsync(tx, key, updatedMetadata).ConfigureAwait(false);
        }
        public async Task AddAsync(ITransaction tx, string key, TValue value)
        {
            var metadata = await GetMetadataAsync(tx, key).ConfigureAwait(false);

            var index   = metadata.From + metadata.Count;
            var listKey = new ReliableListKey {
                Key = key, Id = index
            };
            await _valueStore.SetAsync(tx, listKey, value).ConfigureAwait(false);

            var updatedMetadata = new ReliableListMetaData {
                From = metadata.From, Count = metadata.Count + 1
            };

            await UpdateMetadataAsync(tx, key, updatedMetadata).ConfigureAwait(false);
        }
        public async Task ClearAsync(ITransaction tx, string key)
        {
            var metadata = await GetMetadataAsync(tx, key).ConfigureAwait(false);

            var from  = metadata.From;
            var count = metadata.Count;

            for (var i = 0; i < count; i++)
            {
                var listKey = new ReliableListKey {
                    Key = key, Id = from + i
                };
                await _valueStore.TryRemoveAsync(tx, listKey).ConfigureAwait(false);
            }
            await UpdateMetadataAsync(tx, key, new ReliableListMetaData()).ConfigureAwait(false);
        }
        public async Task SetAsync(ITransaction tx, string key, int index, TValue value)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            var metadata = await GetMetadataAsync(tx, key).ConfigureAwait(false);

            if (index >= metadata.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            else
            {
                var listKey = new ReliableListKey {
                    Key = key, Id = index
                };
                await _valueStore.SetAsync(tx, listKey, value).ConfigureAwait(false);
            }
        }
        public async Task <ConditionalValue <TValue> > TryGetAsync(ITransaction tx, string key, int index)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            var metadataValue = await TryGetMetadataAsync(tx, key).ConfigureAwait(false);

            if (metadataValue.HasValue)
            {
                var listKey = new ReliableListKey {
                    Key = key, Id = index
                };
                return(await _valueStore.TryGetValueAsync(tx, listKey).ConfigureAwait(false));
            }
            else
            {
                return(new ConditionalValue <TValue>());
            }
        }
        public async Task AddRangeAsync(ITransaction tx, string key, IEnumerable <TValue> values)
        {
            var metadata = await GetMetadataAsync(tx, key).ConfigureAwait(false);

            var from  = metadata.From;
            var count = metadata.Count;

            foreach (var value in values)
            {
                var listKey = new ReliableListKey {
                    Key = key, Id = from + count
                };
                await _valueStore.SetAsync(tx, listKey, value).ConfigureAwait(false);

                count++;
            }
            var updatedMetadata = new ReliableListMetaData {
                From = from, Count = count
            };

            await UpdateMetadataAsync(tx, key, updatedMetadata).ConfigureAwait(false);
        }