CacheManager.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. using StackExchange.Redis;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using VCommon.Caching.Internals;
  6. using VCommon.Json;
  7. namespace VCommon.Caching
  8. {
  9. public class CacheManager
  10. {
  11. private readonly RedisCacheAccess _cacheAccess;
  12. public CacheManager(string server) => _cacheAccess = CacheAccess.CreateRedisAccessInstance(server);
  13. public void KeyExpire(int db, string key, CacheExpire expire)
  14. {
  15. if (null != expire)
  16. {
  17. if (expire.To.HasValue) _cacheAccess.CacheOp(db, p => p.KeyExpire(key, expire.To.Value));
  18. if (expire.Specified.HasValue) _cacheAccess.CacheOp(db, p => p.KeyExpire(key, expire.Specified.Value));
  19. }
  20. }
  21. public bool KeyExist(int db, string key) => _cacheAccess.CacheOp(db, p => p.KeyExists(key));
  22. public bool KeyDelete(int db, string key) => _cacheAccess.CacheOp(db, p => p.KeyDelete(key));
  23. public void KeySetJson(int db, string key, object value, CacheExpire expire = null)
  24. {
  25. var json = VJsonSerializer.Serialize(value);
  26. _cacheAccess.CacheOp(db, p => p.StringSet(key, json));
  27. KeyExpire(db, key, expire);
  28. }
  29. public T KeyGetJson<T>(int db, string key) => VJsonSerializer.Deserialize<T>(_cacheAccess.CacheOp(db, p => p.StringGet(key)));
  30. public CacheValue KeyFetch(int db, string key, Func<CacheValue> missingCacheValueProvider, CacheExpire expire = null)
  31. {
  32. if (KeyExist(db, key))
  33. {
  34. return _cacheAccess.CacheOp(db, p => p.StringGet(key));
  35. }
  36. else
  37. {
  38. var value = missingCacheValueProvider();
  39. _cacheAccess.CacheOp(db, p => p.StringSet(key, value));
  40. KeyExpire(db, key, expire);
  41. return value;
  42. }
  43. }
  44. public T KeyFetchJson<T>(int db, string key, Func<T> missingCacheValueProvider, CacheExpire expire = null)
  45. {
  46. if (KeyExist(db, key))
  47. {
  48. var json = (string)_cacheAccess.CacheOp(db, p => p.StringGet(key));
  49. return VJsonSerializer.Deserialize<T>(json);
  50. }
  51. else
  52. {
  53. var value = missingCacheValueProvider();
  54. var json = VJsonSerializer.Serialize(value);
  55. _cacheAccess.CacheOp(db, p => p.StringSet(key, json));
  56. KeyExpire(db, key, expire);
  57. return value;
  58. }
  59. }
  60. public void KeySet(int db, string key, CacheValue value, CacheExpire expire = null)
  61. {
  62. _cacheAccess.CacheOp(db, p => p.StringSet(key, value));
  63. KeyExpire(db, key, expire);
  64. }
  65. public CacheValue KeyGet(int db, string key) => _cacheAccess.CacheOp(db, p => p.StringGet(key));
  66. public bool HashFieldExist(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashExists(hashKey, hashField));
  67. public bool HashFieldDelete(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, hashField));
  68. public long HashFieldDelete(int db, string hashKey, params string[] hashFields)
  69. {
  70. if (0 == hashFields.Length) return 0;
  71. var fields = hashFields.Select(p => (RedisValue)p).ToArray();
  72. return _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, fields));
  73. }
  74. public CacheValue HashFieldFetch(int db, string hashKey, string hashField, Func<CacheValue> missingCacheValueProvider, CacheExpire expire = null)
  75. {
  76. CacheValue cv = _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  77. if (false == cv.IsNull) return cv;
  78. var through = missingCacheValueProvider();
  79. if (through.IsNull) return through;
  80. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, through));
  81. KeyExpire(db, hashKey, expire);
  82. return through;
  83. }
  84. public T HashFieldFetchJson<T>(int db, string hashKey, string hashField, Func<T> missingCacheValueProvider, CacheExpire expire = null)
  85. {
  86. string json = _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  87. if (null != json) return VJsonSerializer.Deserialize<T>(json);
  88. var through = missingCacheValueProvider();
  89. var json2 = VJsonSerializer.Serialize(through);
  90. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, json2));
  91. KeyExpire(db, hashKey, expire);
  92. return through;
  93. }
  94. public T HashFieldGetJson<T>(int db, string hashKey, string hashField)
  95. {
  96. var json = (string)_cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  97. return VJsonSerializer.Deserialize<T>(json);
  98. }
  99. public void HashFieldSetJson<T>(int db, string hashKey, string hashField, T value, CacheExpire expire = null)
  100. {
  101. var json = VJsonSerializer.Serialize(value);
  102. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, json));
  103. KeyExpire(db, hashKey, expire);
  104. }
  105. public void HashFieldSetJson<T>(int db, string hashKey, IReadOnlyDictionary<string, T> entries, CacheExpire expire = null)
  106. {
  107. var hashEntrys = entries.Select(p => new HashEntry(p.Key, VJsonSerializer.Serialize(p.Value))).ToArray();
  108. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashEntrys));
  109. KeyExpire(db, hashKey, expire);
  110. }
  111. public void HashFieldPurgeAndSet(int db, string hashKey, IReadOnlyDictionary<string, CacheValue> hashFields)
  112. {
  113. var entries = hashFields.Select(p => new HashEntry(p.Key, p.Value)).ToArray();
  114. if (0 == entries.Length) return;
  115. _cacheAccess.CacheOp(db, p =>
  116. {
  117. var batch = p.CreateBatch();
  118. batch.KeyDeleteAsync(hashKey);
  119. batch.HashSetAsync(hashKey, entries);
  120. batch.Execute();
  121. });
  122. }
  123. public void HashFieldDeleteByPattern(int db, string hashKey, string pattern)
  124. {
  125. var entries = _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue)).Select(p => p.Name).ToArray();
  126. _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, entries));
  127. }
  128. public IReadOnlyDictionary<string, CacheValue> HashFieldGetByPattern(int db, string hashKey, string pattern)
  129. {
  130. return _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue))
  131. .ToDictionary(p => (string)p.Name, p => (CacheValue)p.Value);
  132. }
  133. public IReadOnlyDictionary<string, T> HashFieldGetByPatternJson<T>(int db, string hashKey, string pattern)
  134. {
  135. return _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue))
  136. .ToDictionary(p => (string)p.Name, p => VJsonSerializer.Deserialize<T>(p.Value));
  137. }
  138. public void HashFieldSet(int db, string hashKey, string hashField, CacheValue value, CacheExpire expire = null)
  139. {
  140. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, value));
  141. KeyExpire(db, hashKey, expire);
  142. }
  143. public CacheValue HashFieldGet(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  144. public void HashFieldSet(int db, string hashKey, IReadOnlyDictionary<string, CacheValue> hashField, CacheExpire expire = null)
  145. {
  146. var entries = hashField.Select(p => new HashEntry(p.Key, p.Value)).ToArray();
  147. if (0 == entries.Length) return;
  148. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, entries));
  149. KeyExpire(db, hashKey, expire);
  150. }
  151. public long HashFieldIncrement(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashIncrement(hashKey, hashField));
  152. public long HashFieldDecrement(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashDecrement(hashKey, hashField));
  153. public IReadOnlyDictionary<string, CacheValue> HashFieldGet(int db, string hashKey, params string[] hashFields)
  154. {
  155. if (0 == hashFields.Length) return new Dictionary<string, CacheValue>();
  156. var keys = hashFields.Distinct().ToArray();
  157. var fields = keys.Select(p => (RedisValue)p).ToArray();
  158. return _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, fields))
  159. .Select((p, i) => new { k = keys[i], v = p })
  160. .ToDictionary(p => p.k, p => (CacheValue)p.v);
  161. }
  162. public IReadOnlyDictionary<TK, TV> HashFieldsFetchAsDic<TK, TV>(int db, string key, IEnumerable<TK> hashFields,
  163. Func<TK, string> convertHashField,
  164. Func<IEnumerable<TK>, IReadOnlyDictionary<TK, TV>> missingCacheValueProvider,
  165. Func<TV, CacheValue> convertValueToCache,
  166. Func<CacheValue, TV> convertCacheToValue,
  167. CacheExpire expire = null)
  168. {
  169. var result = new Dictionary<TK, TV>();
  170. var missingFields = new List<TK>(); //get from cache,and collect missing
  171. {
  172. var fields = hashFields.Distinct().ToArray();
  173. if (0 == fields.Length) return result;
  174. var hf = fields.Select(p => (RedisValue)convertHashField(p)).ToArray();
  175. var fromCache = _cacheAccess.CacheOp(db, p => p.HashGet(key, hf));
  176. for (var i = 0; i < fromCache.Length; i++)
  177. {
  178. if (false == fromCache[i].HasValue) missingFields.Add(fields[i]);
  179. else result[fields[i]] = convertCacheToValue(fromCache[i]);
  180. }
  181. }
  182. if (0 != missingFields.Count) //get from db,and put cache
  183. {
  184. var fromDb = missingCacheValueProvider(missingFields);
  185. var entries = fromDb.Select(p => new HashEntry(convertHashField(p.Key), convertValueToCache(p.Value)))
  186. .Where(p => false == p.Value.IsNull)
  187. .ToArray();
  188. _cacheAccess.CacheOp(db, p => p.HashSet(key, entries));
  189. //merge to result
  190. foreach (var kvp in fromDb) result[kvp.Key] = kvp.Value;
  191. }
  192. KeyExpire(db, key, expire);
  193. return result;
  194. }
  195. public string[] SearchKeys(int db, string pattern) => _cacheAccess.SearchKeys(db, pattern).Select(p => (string)p).ToArray();
  196. }
  197. }