You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cache_redis.go 3.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cache
  5. import (
  6. "fmt"
  7. "time"
  8. "code.gitea.io/gitea/modules/nosql"
  9. "gitea.com/macaron/cache"
  10. "github.com/go-redis/redis/v7"
  11. "github.com/unknwon/com"
  12. )
  13. // RedisCacher represents a redis cache adapter implementation.
  14. type RedisCacher struct {
  15. c redis.UniversalClient
  16. prefix string
  17. hsetName string
  18. occupyMode bool
  19. }
  20. // Put puts value into cache with key and expire time.
  21. // If expired is 0, it lives forever.
  22. func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
  23. key = c.prefix + key
  24. if expire == 0 {
  25. if err := c.c.Set(key, com.ToStr(val), 0).Err(); err != nil {
  26. return err
  27. }
  28. } else {
  29. dur, err := time.ParseDuration(com.ToStr(expire) + "s")
  30. if err != nil {
  31. return err
  32. }
  33. if err = c.c.Set(key, com.ToStr(val), dur).Err(); err != nil {
  34. return err
  35. }
  36. }
  37. if c.occupyMode {
  38. return nil
  39. }
  40. return c.c.HSet(c.hsetName, key, "0").Err()
  41. }
  42. // Get gets cached value by given key.
  43. func (c *RedisCacher) Get(key string) interface{} {
  44. val, err := c.c.Get(c.prefix + key).Result()
  45. if err != nil {
  46. return nil
  47. }
  48. return val
  49. }
  50. // Delete deletes cached value by given key.
  51. func (c *RedisCacher) Delete(key string) error {
  52. key = c.prefix + key
  53. if err := c.c.Del(key).Err(); err != nil {
  54. return err
  55. }
  56. if c.occupyMode {
  57. return nil
  58. }
  59. return c.c.HDel(c.hsetName, key).Err()
  60. }
  61. // Incr increases cached int-type value by given key as a counter.
  62. func (c *RedisCacher) Incr(key string) error {
  63. if !c.IsExist(key) {
  64. return fmt.Errorf("key '%s' not exist", key)
  65. }
  66. return c.c.Incr(c.prefix + key).Err()
  67. }
  68. // Decr decreases cached int-type value by given key as a counter.
  69. func (c *RedisCacher) Decr(key string) error {
  70. if !c.IsExist(key) {
  71. return fmt.Errorf("key '%s' not exist", key)
  72. }
  73. return c.c.Decr(c.prefix + key).Err()
  74. }
  75. // IsExist returns true if cached value exists.
  76. func (c *RedisCacher) IsExist(key string) bool {
  77. if c.c.Exists(c.prefix+key).Val() == 1 {
  78. return true
  79. }
  80. if !c.occupyMode {
  81. c.c.HDel(c.hsetName, c.prefix+key)
  82. }
  83. return false
  84. }
  85. // Flush deletes all cached data.
  86. func (c *RedisCacher) Flush() error {
  87. if c.occupyMode {
  88. return c.c.FlushDB().Err()
  89. }
  90. keys, err := c.c.HKeys(c.hsetName).Result()
  91. if err != nil {
  92. return err
  93. }
  94. if err = c.c.Del(keys...).Err(); err != nil {
  95. return err
  96. }
  97. return c.c.Del(c.hsetName).Err()
  98. }
  99. // StartAndGC starts GC routine based on config string settings.
  100. // AdapterConfig: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180,hset_name=MacaronCache,prefix=cache:
  101. func (c *RedisCacher) StartAndGC(opts cache.Options) error {
  102. c.hsetName = "MacaronCache"
  103. c.occupyMode = opts.OccupyMode
  104. uri := nosql.ToRedisURI(opts.AdapterConfig)
  105. c.c = nosql.GetManager().GetRedisClient(uri.String())
  106. for k, v := range uri.Query() {
  107. switch k {
  108. case "hset_name":
  109. c.hsetName = v[0]
  110. case "prefix":
  111. c.prefix = v[0]
  112. }
  113. }
  114. return c.c.Ping().Err()
  115. }
  116. func init() {
  117. cache.Register("redis", &RedisCacher{})
  118. }