using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.Runtime.Caching; namespace ZelWiki.Caching { /// /// 缓存 /// public class WikiCache { public enum Category { User, Page, Search, Emoji, Configuration } public static int DefaultCacheSeconds { get; set; } private static MemoryCache? _memCache; public static ulong CachePuts { get; set; } public static ulong CacheGets { get; set; } public static ulong CacheHits { get; set; } public static ulong CacheMisses { get; set; } public static int CacheItemCount => MemCache.Count(); public static double CacheMemoryLimit => MemCache.CacheMemoryLimit; public static MemoryCache MemCache => _memCache ?? throw new Exception("缓存尚未初始化"); public static void Initialize(int cacheMemoryLimitMB, int defaultCacheSeconds) { DefaultCacheSeconds = defaultCacheSeconds; var config = new NameValueCollection { //config.Add("pollingInterval", "00:05:00"); //config.Add("physicalMemoryLimitPercentage", "0"); { "CacheMemoryLimitMegabytes", cacheMemoryLimitMB.ToString() } }; _memCache?.Dispose(); _memCache = new MemoryCache("TightWikiCache", config); } /// /// 获取缓存 /// /// /// /// public static T? Get(IWikiCacheKey cacheKey) { CacheGets++; var result = (T)MemCache.Get(cacheKey.Key); if (result == null) { CacheMisses++; } CacheHits++; return result; } /// /// 确定缓存是否包含给定的key /// /// /// public static bool Contains(IWikiCacheKey cacheKey) { CacheGets++; if (MemCache.Contains(cacheKey.Key)) { CacheHits++; return true; } CacheMisses++; return false; } /// /// 获取缓存 /// /// /// /// public static bool TryGet(IWikiCacheKey cacheKey, [NotNullWhen(true)] out T result) { CacheGets++; if ((result = (T)MemCache.Get(cacheKey.Key)) == null) { CacheMisses++; return false; } CacheHits++; return true; } /// ///添加缓存 /// /// /// /// public static void Put(IWikiCacheKey cacheKey, object value, int? seconds = null) { CachePuts++; seconds ??= DefaultCacheSeconds; if (seconds <= 0) { return; } var policy = new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(seconds ?? DefaultCacheSeconds) }; MemCache.Add(cacheKey.Key, value, policy); } public static void Put(IWikiCacheKey cacheKey, object value, CacheItemPolicy policy) { CachePuts++; MemCache.Add(cacheKey.Key, value, policy); } /// /// 清理 /// public static void Clear() { if (_memCache == null) { return; } var items = MemCache.ToList(); foreach (var a in items) { MemCache.Remove(a.Key); } } /// /// 删除某个 /// /// public static void ClearCategory(WikiCacheKey cacheKey) { var keys = new List(); foreach (var item in MemCache) { if (item.Key.StartsWith(cacheKey.Key)) { keys.Add(item.Key); } } keys.ForEach(o => MemCache.Remove(o)); } /// /// 删除给定类别中的缓存条目 /// /// public static void ClearCategory(Category category) { var cacheKey = WikiCacheKey.Build(category); var keys = new List(); foreach (var item in MemCache) { if (item.Key.StartsWith(cacheKey.Key)) { keys.Add(item.Key); } } keys.ForEach(o => MemCache.Remove(o)); } } }