CacheManager.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 void KeySet(int db, string key, CacheValue value, CacheExpire expire = null)
  31. {
  32. _cacheAccess.CacheOp(db, p => p.StringSet(key, value));
  33. KeyExpire(db, key, expire);
  34. }
  35. public CacheValue KeyGet(int db, string key) => _cacheAccess.CacheOp(db, p => p.StringGet(key));
  36. public bool HashFieldExist(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashExists(hashKey, hashField));
  37. public bool HashFieldDelete(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, hashField));
  38. public long HashFieldDelete(int db, string hashKey, params string[] hashFields)
  39. {
  40. if (0 == hashFields.Length) return 0;
  41. var fields = hashFields.Select(p => (RedisValue)p).ToArray();
  42. return _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, fields));
  43. }
  44. public CacheValue HashFieldFetch(int db, string hashKey, string hashField, Func<CacheValue> missingCacheValueProvider, CacheExpire expire = null)
  45. {
  46. CacheValue cv = _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  47. if (false == cv.IsNull) return cv;
  48. var through = missingCacheValueProvider();
  49. if (through.IsNull) return through;
  50. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, through));
  51. KeyExpire(db, hashKey, expire);
  52. return through;
  53. }
  54. public T HashFieldFetchJson<T>(int db, string hashKey, string hashField, Func<T> missingCacheValueProvider, CacheExpire expire = null)
  55. {
  56. string json = _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  57. if (null != json) return VJsonSerializer.Deserialize<T>(json);
  58. var through = missingCacheValueProvider();
  59. var json2 = VJsonSerializer.Serialize(through);
  60. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, json2));
  61. KeyExpire(db, hashKey, expire);
  62. return through;
  63. }
  64. public T HashFieldGetJson<T>(int db, string hashKey, string hashField)
  65. {
  66. var json = (string)_cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  67. return VJsonSerializer.Deserialize<T>(json);
  68. }
  69. public void HashFieldSetJson<T>(int db, string hashKey, string hashField, T value, CacheExpire expire = null)
  70. {
  71. var json = VJsonSerializer.Serialize(value);
  72. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, json));
  73. KeyExpire(db, hashKey, expire);
  74. }
  75. public void HashFieldSetJson<T>(int db, string hashKey, IReadOnlyDictionary<string, T> entries, CacheExpire expire = null)
  76. {
  77. var hashEntrys = entries.Select(p => new HashEntry(p.Key, VJsonSerializer.Serialize(p.Value))).ToArray();
  78. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashEntrys));
  79. KeyExpire(db, hashKey, expire);
  80. }
  81. public void HashFieldPurgeAndSet(int db, string hashKey, IReadOnlyDictionary<string, CacheValue> hashFields)
  82. {
  83. var entries = hashFields.Select(p => new HashEntry(p.Key, p.Value)).ToArray();
  84. if (0 == entries.Length) return;
  85. _cacheAccess.CacheOp(db, p =>
  86. {
  87. var batch = p.CreateBatch();
  88. batch.KeyDeleteAsync(hashKey);
  89. batch.HashSetAsync(hashKey, entries);
  90. batch.Execute();
  91. });
  92. }
  93. public void HashFieldDeleteByPattern(int db, string hashKey, string pattern)
  94. {
  95. var entries = _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue)).Select(p => p.Name).ToArray();
  96. _cacheAccess.CacheOp(db, p => p.HashDelete(hashKey, entries));
  97. }
  98. public IReadOnlyDictionary<string, CacheValue> HashFieldGetByPattern(int db, string hashKey, string pattern)
  99. {
  100. return _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue))
  101. .ToDictionary(p => (string)p.Name, p => (CacheValue)p.Value);
  102. }
  103. public IReadOnlyDictionary<string, T> HashFieldGetByPatternJson<T>(int db, string hashKey, string pattern)
  104. {
  105. return _cacheAccess.CacheOp(db, p => p.HashScan(hashKey, pattern, int.MaxValue))
  106. .ToDictionary(p => (string)p.Name, p => VJsonSerializer.Deserialize<T>(p.Value));
  107. }
  108. public void HashFieldSet(int db, string hashKey, string hashField, CacheValue value, CacheExpire expire = null)
  109. {
  110. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, hashField, value));
  111. KeyExpire(db, hashKey, expire);
  112. }
  113. public CacheValue HashFieldGet(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, hashField));
  114. public void HashFieldSet(int db, string hashKey, IReadOnlyDictionary<string, CacheValue> hashField, CacheExpire expire = null)
  115. {
  116. var entries = hashField.Select(p => new HashEntry(p.Key, p.Value)).ToArray();
  117. if (0 == entries.Length) return;
  118. _cacheAccess.CacheOp(db, p => p.HashSet(hashKey, entries));
  119. KeyExpire(db, hashKey, expire);
  120. }
  121. public long HashFieldIncrement(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashIncrement(hashKey, hashField));
  122. public long HashFieldDecrement(int db, string hashKey, string hashField) => _cacheAccess.CacheOp(db, p => p.HashDecrement(hashKey, hashField));
  123. public IReadOnlyDictionary<string, CacheValue> HashFieldGet(int db, string hashKey, params string[] hashFields)
  124. {
  125. if (0 == hashFields.Length) return new Dictionary<string, CacheValue>();
  126. var keys = hashFields.Distinct().ToArray();
  127. var fields = keys.Select(p => (RedisValue)p).ToArray();
  128. return _cacheAccess.CacheOp(db, p => p.HashGet(hashKey, fields))
  129. .Select((p, i) => new { k = keys[i], v = p })
  130. .ToDictionary(p => p.k, p => (CacheValue)p.v);
  131. }
  132. public IReadOnlyDictionary<TK, TV> HashFieldsFetchAsDic<TK, TV>(int db, string key, IEnumerable<TK> hashFields,
  133. Func<TK, string> convertHashField,
  134. Func<IEnumerable<TK>, IReadOnlyDictionary<TK, TV>> missingCacheValueProvider,
  135. Func<TV, CacheValue> convertValueToCache,
  136. Func<CacheValue, TV> convertCacheToValue,
  137. CacheExpire expire = null)
  138. {
  139. var result = new Dictionary<TK, TV>();
  140. var missingFields = new List<TK>(); //get from cache,and collect missing
  141. {
  142. var fields = hashFields.Distinct().ToArray();
  143. if (0 == fields.Length) return result;
  144. var hf = fields.Select(p => (RedisValue)convertHashField(p)).ToArray();
  145. var fromCache = _cacheAccess.CacheOp(db, p => p.HashGet(key, hf));
  146. for (var i = 0; i < fromCache.Length; i++)
  147. {
  148. if (false == fromCache[i].HasValue) missingFields.Add(fields[i]);
  149. else result[fields[i]] = convertCacheToValue(fromCache[i]);
  150. }
  151. }
  152. if (0 != missingFields.Count) //get from db,and put cache
  153. {
  154. var fromDb = missingCacheValueProvider(missingFields);
  155. var entries = fromDb.Select(p => new HashEntry(convertHashField(p.Key), convertValueToCache(p.Value)))
  156. .Where(p => false == p.Value.IsNull)
  157. .ToArray();
  158. _cacheAccess.CacheOp(db, p => p.HashSet(key, entries));
  159. //merge to result
  160. foreach (var kvp in fromDb) result[kvp.Key] = kvp.Value;
  161. }
  162. KeyExpire(db, key, expire);
  163. return result;
  164. }
  165. public string[] SearchKeys(int db, string pattern) => _cacheAccess.SearchKeys(db, pattern).Select(p => (string)p).ToArray();
  166. }
  167. }