188 lines
5.2 KiB
C#
188 lines
5.2 KiB
C#
using System.Collections.Specialized;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.Caching;
|
|
|
|
namespace ZelWiki.Caching
|
|
{
|
|
/// <summary>
|
|
/// 缓存
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取缓存
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="cacheKey"></param>
|
|
/// <returns></returns>
|
|
public static T? Get<T>(IWikiCacheKey cacheKey)
|
|
{
|
|
CacheGets++;
|
|
var result = (T)MemCache.Get(cacheKey.Key);
|
|
|
|
if (result == null)
|
|
{
|
|
CacheMisses++;
|
|
}
|
|
|
|
CacheHits++;
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 确定缓存是否包含给定的key
|
|
/// </summary>
|
|
/// <param name="cacheKey"></param>
|
|
/// <returns></returns>
|
|
public static bool Contains(IWikiCacheKey cacheKey)
|
|
{
|
|
CacheGets++;
|
|
if (MemCache.Contains(cacheKey.Key))
|
|
{
|
|
CacheHits++;
|
|
return true;
|
|
}
|
|
|
|
CacheMisses++;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取缓存
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="cacheKey"></param>
|
|
/// <returns></returns>
|
|
public static bool TryGet<T>(IWikiCacheKey cacheKey, [NotNullWhen(true)] out T result)
|
|
{
|
|
CacheGets++;
|
|
if ((result = (T)MemCache.Get(cacheKey.Key)) == null)
|
|
{
|
|
CacheMisses++;
|
|
return false;
|
|
}
|
|
|
|
CacheHits++;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
///添加缓存
|
|
/// </summary>
|
|
/// <param name="cacheKey"></param>
|
|
/// <param name="value"></param>
|
|
/// <param name="seconds"></param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理
|
|
/// </summary>
|
|
public static void Clear()
|
|
{
|
|
if (_memCache == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var items = MemCache.ToList();
|
|
foreach (var a in items)
|
|
{
|
|
MemCache.Remove(a.Key);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除某个
|
|
/// </summary>
|
|
/// <param name="cacheKey"></param>
|
|
public static void ClearCategory(WikiCacheKey cacheKey)
|
|
{
|
|
var keys = new List<string>();
|
|
|
|
foreach (var item in MemCache)
|
|
{
|
|
if (item.Key.StartsWith(cacheKey.Key))
|
|
{
|
|
keys.Add(item.Key);
|
|
}
|
|
}
|
|
|
|
keys.ForEach(o => MemCache.Remove(o));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除给定类别中的缓存条目
|
|
/// </summary>
|
|
/// <param name="category"></param>
|
|
public static void ClearCategory(Category category)
|
|
{
|
|
var cacheKey = WikiCacheKey.Build(category);
|
|
|
|
var keys = new List<string>();
|
|
|
|
foreach (var item in MemCache)
|
|
{
|
|
if (item.Key.StartsWith(cacheKey.Key))
|
|
{
|
|
keys.Add(item.Key);
|
|
}
|
|
}
|
|
|
|
keys.ForEach(o => MemCache.Remove(o));
|
|
}
|
|
}
|
|
} |