cache.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package service
  2. import (
  3. "context"
  4. "dashoo.cn/micro/app/common/global"
  5. "fmt"
  6. "github.com/gogf/gcache-adapter/adapter"
  7. "github.com/gogf/gf/crypto/gmd5"
  8. "github.com/gogf/gf/encoding/gjson"
  9. "github.com/gogf/gf/frame/g"
  10. "github.com/gogf/gf/os/gcache"
  11. "github.com/gogf/gf/util/gconv"
  12. "reflect"
  13. "sync"
  14. "time"
  15. )
  16. type cache struct {
  17. }
  18. type cacheTagService struct {
  19. tagKey interface{}
  20. cache *gcache.Cache
  21. tagSetMux *sync.Mutex
  22. }
  23. var (
  24. Cache = new(cache)
  25. userRedis = g.Cfg().GetBool("redis.open")
  26. gChe = gcache.New()
  27. )
  28. func (s *cache) New() *cacheTagService {
  29. gChe.Ctx(context.Background())
  30. if userRedis {
  31. adapter := adapter.NewRedis(g.Redis())
  32. gChe.SetAdapter(adapter)
  33. }
  34. return &cacheTagService{
  35. cache: gChe,
  36. tagSetMux: new(sync.Mutex),
  37. }
  38. }
  39. // 设置tag缓存的keys
  40. func (c *cacheTagService) cacheTagKey(key interface{}, tag interface{}) {
  41. c.setTagKey(tag)
  42. if c.tagKey != nil {
  43. tagValue := []interface{}{key}
  44. value, _ := c.cache.Get(c.tagKey)
  45. if value != nil {
  46. var keyValue []interface{}
  47. //若是字符串
  48. if kStr, ok := value.(string); ok {
  49. js, err := gjson.DecodeToJson(kStr)
  50. if err != nil {
  51. g.Log().Error(err)
  52. return
  53. }
  54. keyValue = gconv.SliceAny(js.Value())
  55. } else {
  56. keyValue = gconv.SliceAny(value)
  57. }
  58. for _, v := range keyValue {
  59. if !reflect.DeepEqual(key, v) {
  60. tagValue = append(tagValue, v)
  61. }
  62. }
  63. }
  64. c.cache.Set(c.tagKey, tagValue, 0)
  65. }
  66. }
  67. // 获取带标签的键名
  68. func (c *cacheTagService) setTagKey(tag interface{}) {
  69. if tag != nil {
  70. c.tagKey = interface{}(fmt.Sprintf("%s_tag_%s", global.CachePrefix, gmd5.MustEncryptString(gconv.String(tag))))
  71. }
  72. }
  73. // Set sets cache with <tagKey>-<value> pair, which is expired after <duration>.
  74. // It does not expire if <duration> <= 0.
  75. func (c *cacheTagService) Set(key interface{}, value interface{}, duration time.Duration, tag ...interface{}) {
  76. c.tagSetMux.Lock()
  77. if len(tag) > 0 {
  78. c.cacheTagKey(key, tag[0])
  79. }
  80. err := c.cache.Set(key, value, duration)
  81. if err != nil {
  82. g.Log().Error(err)
  83. }
  84. c.tagSetMux.Unlock()
  85. }
  86. // SetIfNotExist sets cache with <tagKey>-<value> pair if <tagKey> does not exist in the cache,
  87. // which is expired after <duration>. It does not expire if <duration> <= 0.
  88. func (c *cacheTagService) SetIfNotExist(key interface{}, value interface{}, duration time.Duration, tag interface{}) bool {
  89. c.tagSetMux.Lock()
  90. defer c.tagSetMux.Unlock()
  91. c.cacheTagKey(key, tag)
  92. v, _ := c.cache.SetIfNotExist(key, value, duration)
  93. return v
  94. }
  95. // Sets batch sets cache with tagKey-value pairs by <data>, which is expired after <duration>.
  96. //
  97. // It does not expire if <duration> <= 0.
  98. func (c *cacheTagService) Sets(data map[interface{}]interface{}, duration time.Duration, tag interface{}) {
  99. c.tagSetMux.Lock()
  100. if tag != nil {
  101. for k, _ := range data {
  102. c.cacheTagKey(k, tag)
  103. }
  104. c.cache.Sets(data, duration)
  105. } else {
  106. c.cache.Sets(data, duration)
  107. }
  108. c.tagSetMux.Unlock()
  109. }
  110. // Get returns the value of <tagKey>.
  111. // It returns nil if it does not exist or its value is nil.
  112. func (c *cacheTagService) Get(key interface{}) interface{} {
  113. v, err := c.cache.Get(key)
  114. if err != nil {
  115. g.Log().Error(err)
  116. }
  117. return v
  118. }
  119. // GetOrSet returns the value of <tagKey>,
  120. // or sets <tagKey>-<value> pair and returns <value> if <tagKey> does not exist in the cache.
  121. // The tagKey-value pair expires after <duration>.
  122. //
  123. // It does not expire if <duration> <= 0.
  124. func (c *cacheTagService) GetOrSet(key interface{}, value interface{}, duration time.Duration, tag interface{}) interface{} {
  125. c.tagSetMux.Lock()
  126. defer c.tagSetMux.Unlock()
  127. c.cacheTagKey(key, tag)
  128. v, _ := c.cache.GetOrSet(key, value, duration)
  129. return v
  130. }
  131. // GetOrSetFunc returns the value of <tagKey>, or sets <tagKey> with result of function <f>
  132. // and returns its result if <tagKey> does not exist in the cache. The tagKey-value pair expires
  133. // after <duration>. It does not expire if <duration> <= 0.
  134. func (c *cacheTagService) GetOrSetFunc(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} {
  135. c.tagSetMux.Lock()
  136. defer c.tagSetMux.Unlock()
  137. c.cacheTagKey(key, tag)
  138. v, _ := c.cache.GetOrSetFunc(key, f, duration)
  139. return v
  140. }
  141. // GetOrSetFuncLock returns the value of <tagKey>, or sets <tagKey> with result of function <f>
  142. // and returns its result if <tagKey> does not exist in the cache. The tagKey-value pair expires
  143. // after <duration>. It does not expire if <duration> <= 0.
  144. //
  145. // Note that the function <f> is executed within writing mutex lock.
  146. func (c *cacheTagService) GetOrSetFuncLock(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} {
  147. c.tagSetMux.Lock()
  148. defer c.tagSetMux.Unlock()
  149. c.cacheTagKey(key, tag)
  150. v, _ := c.cache.GetOrSetFuncLock(key, f, duration)
  151. return v
  152. }
  153. // Contains returns true if <tagKey> exists in the cache, or else returns false.
  154. func (c *cacheTagService) Contains(key interface{}) bool {
  155. v, _ := c.cache.Contains(key)
  156. return v
  157. }
  158. // Remove deletes the <tagKey> in the cache, and returns its value.
  159. func (c *cacheTagService) Remove(key interface{}) interface{} {
  160. v, _ := c.cache.Remove(key)
  161. return v
  162. }
  163. // Removes deletes <keys> in the cache.
  164. func (c *cacheTagService) Removes(keys []interface{}) {
  165. c.cache.Remove(keys...)
  166. }
  167. // Remove deletes the <tag> in the cache, and returns its value.
  168. func (c *cacheTagService) RemoveByTag(tag interface{}) {
  169. c.tagSetMux.Lock()
  170. c.setTagKey(tag)
  171. //删除tagKey 对应的 key和值
  172. keys := c.Get(c.tagKey)
  173. if keys != nil {
  174. //如果是字符串
  175. if kStr, ok := keys.(string); ok {
  176. js, err := gjson.DecodeToJson(kStr)
  177. if err != nil {
  178. g.Log().Error(err)
  179. return
  180. }
  181. ks := gconv.SliceAny(js.Value())
  182. c.Removes(ks)
  183. } else {
  184. ks := gconv.SliceAny(keys)
  185. c.Removes(ks)
  186. }
  187. }
  188. c.Remove(c.tagKey)
  189. c.tagSetMux.Unlock()
  190. }
  191. // Removes deletes <tags> in the cache.
  192. func (c *cacheTagService) RemoveByTags(tag []interface{}) {
  193. for _, v := range tag {
  194. c.RemoveByTag(v)
  195. }
  196. }
  197. // Data returns a copy of all tagKey-value pairs in the cache as map type.
  198. func (c *cacheTagService) Data() map[interface{}]interface{} {
  199. v, _ := c.cache.Data()
  200. return v
  201. }
  202. // Keys returns all keys in the cache as slice.
  203. func (c *cacheTagService) Keys() []interface{} {
  204. v, _ := c.cache.Keys()
  205. return v
  206. }
  207. // KeyStrings returns all keys in the cache as string slice.
  208. func (c *cacheTagService) KeyStrings() []string {
  209. v, _ := c.cache.KeyStrings()
  210. return v
  211. }
  212. // Values returns all values in the cache as slice.
  213. func (c *cacheTagService) Values() []interface{} {
  214. v, _ := c.cache.Values()
  215. return v
  216. }
  217. // Size returns the size of the cache.
  218. func (c *cacheTagService) Size() int {
  219. v, _ := c.cache.Size()
  220. return v
  221. }