<commit_before>﻿using Foundatio.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Foundatio.Caching {
    public class ScopedCacheClient : ICacheClient {
        public ScopedCacheClient(ICacheClient client, string scope) {
            UnscopedCache = client ?? new NullCacheClient();
            Scope = scope;
        }

        public ICacheClient UnscopedCache { get; private set; }

        public string Scope { get; private set; }

        protected string GetScopedCacheKey(string key) {
            return String.Concat(Scope, ":", key);
        }

        protected IEnumerable<string> GetScopedCacheKeys(IEnumerable<string> keys) {
            return keys?.Select(GetScopedCacheKey);
        }

        protected string GetUnscopedCacheKey(string scopedKey) {
            int i = scopedKey.IndexOf(':');

            if (-1 < i && i < (scopedKey.Length - 1)) {
                return scopedKey.Substring(i + 1);
            }

            return scopedKey;
        }

        public Task<int> RemoveAllAsync(IEnumerable<string> keys = null) {
            if (keys == null)
                return RemoveByPrefixAsync(String.Empty);

            return UnscopedCache.RemoveAllAsync(GetScopedCacheKeys(keys));
        }

        public Task<int> RemoveByPrefixAsync(string prefix) {
            return UnscopedCache.RemoveByPrefixAsync(GetScopedCacheKey(prefix));
        }

        public Task<CacheValue<T>> GetAsync<T>(string key) {
            return UnscopedCache.GetAsync<T>(GetScopedCacheKey(key));
        }

        public async Task<IDictionary<string, CacheValue<T>>> GetAllAsync<T>(IEnumerable<string> keys) {
            var scopedValueMap = await UnscopedCache.GetAllAsync<T>(GetScopedCacheKeys(keys)).AnyContext();
            var valueMap = new Dictionary<string, CacheValue<T>>();

            foreach (var kvp in scopedValueMap)
                valueMap[GetUnscopedCacheKey(kvp.Key)] = kvp.Value;

            return valueMap;
        }

        public Task<bool> AddAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.AddAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.SetAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<int> SetAllAsync<T>(IDictionary<string, T> values, TimeSpan? expiresIn = null) {
            return UnscopedCache.SetAllAsync(values.ToDictionary(kvp => GetScopedCacheKey(kvp.Key), kvp => kvp.Value), expiresIn);
        }

        public Task<bool> ReplaceAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.ReplaceAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<double> IncrementAsync(string key, double amount = 1, TimeSpan? expiresIn = null) {
            return UnscopedCache.IncrementAsync(GetScopedCacheKey(key), amount, expiresIn);
        }
        
        public Task<bool> ExistsAsync(string key) {
            return UnscopedCache.ExistsAsync(GetScopedCacheKey(key));
        }

        public Task<TimeSpan?> GetExpirationAsync(string key) {<commit_msg>Improvements<commit_after>﻿using Foundatio.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Foundatio.Caching {
    public class ScopedCacheClient : ICacheClient {
        private readonly string _keyPrefix;

        public ScopedCacheClient(ICacheClient client, string scope) {
            UnscopedCache = client ?? new NullCacheClient();
            Scope = scope;

            _keyPrefix = scope != null ? String.Concat(scope, ":") : String.Empty;
        }

        public ICacheClient UnscopedCache { get; private set; }

        public string Scope { get; private set; }

        protected string GetScopedCacheKey(string key) {
            return String.Concat(_keyPrefix, key);
        }

        protected IEnumerable<string> GetScopedCacheKeys(IEnumerable<string> keys) {
            return keys?.Select(GetScopedCacheKey);
        }

        protected string UnscopeCacheKey(string scopedKey) {
            return scopedKey?.Substring(_keyPrefix.Length);
        }

        public Task<int> RemoveAllAsync(IEnumerable<string> keys = null) {
            if (keys == null)
                return RemoveByPrefixAsync(String.Empty);

            return UnscopedCache.RemoveAllAsync(GetScopedCacheKeys(keys));
        }

        public Task<int> RemoveByPrefixAsync(string prefix) {
            return UnscopedCache.RemoveByPrefixAsync(GetScopedCacheKey(prefix));
        }

        public Task<CacheValue<T>> GetAsync<T>(string key) {
            return UnscopedCache.GetAsync<T>(GetScopedCacheKey(key));
        }

        public async Task<IDictionary<string, CacheValue<T>>> GetAllAsync<T>(IEnumerable<string> keys) {
            var scopedValueMap = await UnscopedCache.GetAllAsync<T>(GetScopedCacheKeys(keys)).AnyContext();
            var valueMap = new Dictionary<string, CacheValue<T>>();

            foreach (var kvp in scopedValueMap)
                valueMap[UnscopeCacheKey(kvp.Key)] = kvp.Value;

            return valueMap;
        }

        public Task<bool> AddAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.AddAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.SetAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<int> SetAllAsync<T>(IDictionary<string, T> values, TimeSpan? expiresIn = null) {
            return UnscopedCache.SetAllAsync(values.ToDictionary(kvp => GetScopedCacheKey(kvp.Key), kvp => kvp.Value), expiresIn);
        }

        public Task<bool> ReplaceAsync<T>(string key, T value, TimeSpan? expiresIn = null) {
            return UnscopedCache.ReplaceAsync(GetScopedCacheKey(key), value, expiresIn);
        }

        public Task<double> IncrementAsync(string key, double amount = 1, TimeSpan? expiresIn = null) {
            return UnscopedCache.IncrementAsync(GetScopedCacheKey(key), amount, expiresIn);
        }
        
        public Task<bool> ExistsAsync(string key) {
            return UnscopedCache.ExistsAsync(GetScopedCacheKey(key));
        }

        public Task<TimeSpan?> GetExpirationAsync(string key) {
{'fraction_non_alphanumeric': 0.09832539560608389, 'fraction_numerical': 0.0007681671531725304, 'mean_word_length': 2.7826844857640904, 'pattern_counts': {'":': 2, '<': 63, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7304525', 'n_tokens_mistral': 1862, 'n_tokens_neox': 1791, 'n_words': 387}