redis.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package cache
  2. import (
  3. "context"
  4. "time"
  5. "git.bvbej.com/bvbej/base-golang/pkg/errors"
  6. "git.bvbej.com/bvbej/base-golang/pkg/time_parse"
  7. "git.bvbej.com/bvbej/base-golang/pkg/trace"
  8. "github.com/go-redis/redis/v8"
  9. )
  10. type Option func(*option)
  11. type Trace = trace.T
  12. type option struct {
  13. Trace *trace.Trace
  14. Redis *trace.Redis
  15. }
  16. func newOption() *option {
  17. return &option{}
  18. }
  19. var _ Repo = (*cacheRepo)(nil)
  20. type Repo interface {
  21. i()
  22. Set(key, value string, ttl time.Duration, options ...Option) error
  23. Get(key string, options ...Option) (string, error)
  24. TTL(key string) (time.Duration, error)
  25. Expire(key string, ttl time.Duration) bool
  26. ExpireAt(key string, ttl time.Time) bool
  27. Del(key string, options ...Option) bool
  28. Exists(keys ...string) bool
  29. Incr(key string, options ...Option) int64
  30. HGet(key, field string, options ...Option) (string, error)
  31. HSet(key, field, value string, options ...Option) error
  32. Close() error
  33. }
  34. type cacheRepo struct {
  35. client *redis.Client
  36. ctx context.Context
  37. }
  38. func New(addr, pass string, db, maxRetries, poolSize, minIdleConn int) (Repo, error) {
  39. client := redis.NewClient(&redis.Options{
  40. Addr: addr,
  41. Password: pass,
  42. DB: db,
  43. MaxRetries: maxRetries,
  44. PoolSize: poolSize,
  45. MinIdleConns: minIdleConn,
  46. })
  47. ctx := context.TODO()
  48. if err := client.Ping(ctx).Err(); err != nil {
  49. return nil, errors.Wrap(err, "ping redis err")
  50. }
  51. return &cacheRepo{
  52. client: client,
  53. ctx: ctx,
  54. }, nil
  55. }
  56. func WithTrace(t Trace) Option {
  57. return func(opt *option) {
  58. if t != nil {
  59. opt.Trace = t.(*trace.Trace)
  60. opt.Redis = new(trace.Redis)
  61. }
  62. }
  63. }
  64. func (c *cacheRepo) i() {}
  65. func (c *cacheRepo) Set(key, value string, ttl time.Duration, options ...Option) error {
  66. ts := time.Now()
  67. opt := newOption()
  68. defer func() {
  69. if opt.Trace != nil {
  70. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  71. opt.Redis.Handle = "set"
  72. opt.Redis.Key = key
  73. opt.Redis.Value = value
  74. opt.Redis.TTL = ttl.Minutes()
  75. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  76. opt.Trace.AppendRedis(opt.Redis)
  77. }
  78. }()
  79. for _, f := range options {
  80. f(opt)
  81. }
  82. if err := c.client.Set(c.ctx, key, value, ttl).Err(); err != nil {
  83. return errors.Wrapf(err, "redis set key: %s err", key)
  84. }
  85. return nil
  86. }
  87. func (c *cacheRepo) Get(key string, options ...Option) (string, error) {
  88. ts := time.Now()
  89. opt := newOption()
  90. defer func() {
  91. if opt.Trace != nil {
  92. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  93. opt.Redis.Handle = "get"
  94. opt.Redis.Key = key
  95. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  96. opt.Trace.AppendRedis(opt.Redis)
  97. }
  98. }()
  99. for _, f := range options {
  100. f(opt)
  101. }
  102. value, err := c.client.Get(c.ctx, key).Result()
  103. if err != nil {
  104. return "", errors.Wrapf(err, "redis get key: %s err", key)
  105. }
  106. return value, nil
  107. }
  108. func (c *cacheRepo) TTL(key string) (time.Duration, error) {
  109. ttl, err := c.client.TTL(c.ctx, key).Result()
  110. if err != nil {
  111. return -1, errors.Wrapf(err, "redis get key: %s err", key)
  112. }
  113. return ttl, nil
  114. }
  115. func (c *cacheRepo) Expire(key string, ttl time.Duration) bool {
  116. ok, _ := c.client.Expire(c.ctx, key, ttl).Result()
  117. return ok
  118. }
  119. func (c *cacheRepo) ExpireAt(key string, ttl time.Time) bool {
  120. ok, _ := c.client.ExpireAt(c.ctx, key, ttl).Result()
  121. return ok
  122. }
  123. func (c *cacheRepo) Exists(keys ...string) bool {
  124. if len(keys) == 0 {
  125. return true
  126. }
  127. value, _ := c.client.Exists(c.ctx, keys...).Result()
  128. return value > 0
  129. }
  130. func (c *cacheRepo) Del(key string, options ...Option) bool {
  131. ts := time.Now()
  132. opt := newOption()
  133. defer func() {
  134. if opt.Trace != nil {
  135. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  136. opt.Redis.Handle = "del"
  137. opt.Redis.Key = key
  138. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  139. opt.Trace.AppendRedis(opt.Redis)
  140. }
  141. }()
  142. for _, f := range options {
  143. f(opt)
  144. }
  145. if key == "" {
  146. return true
  147. }
  148. value, _ := c.client.Del(c.ctx, key).Result()
  149. return value > 0
  150. }
  151. func (c *cacheRepo) Incr(key string, options ...Option) int64 {
  152. ts := time.Now()
  153. opt := newOption()
  154. defer func() {
  155. if opt.Trace != nil {
  156. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  157. opt.Redis.Handle = "incr"
  158. opt.Redis.Key = key
  159. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  160. opt.Trace.AppendRedis(opt.Redis)
  161. }
  162. }()
  163. for _, f := range options {
  164. f(opt)
  165. }
  166. value, _ := c.client.Incr(c.ctx, key).Result()
  167. return value
  168. }
  169. func (c *cacheRepo) HGet(key, field string, options ...Option) (string, error) {
  170. ts := time.Now()
  171. opt := newOption()
  172. defer func() {
  173. if opt.Trace != nil {
  174. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  175. opt.Redis.Handle = "get"
  176. opt.Redis.Key = key
  177. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  178. opt.Trace.AppendRedis(opt.Redis)
  179. }
  180. }()
  181. for _, f := range options {
  182. f(opt)
  183. }
  184. value, err := c.client.HGet(c.ctx, key, field).Result()
  185. if err != nil {
  186. return "", errors.Wrapf(err, "redis hget key: %s field: %s", key, field)
  187. }
  188. return value, nil
  189. }
  190. func (c *cacheRepo) HSet(key, field, value string, options ...Option) error {
  191. ts := time.Now()
  192. opt := newOption()
  193. defer func() {
  194. if opt.Trace != nil {
  195. opt.Redis.Timestamp = time_parse.CSTLayoutString()
  196. opt.Redis.Handle = "set"
  197. opt.Redis.Key = key
  198. opt.Redis.Value = value
  199. opt.Redis.CostSeconds = time.Since(ts).Seconds()
  200. opt.Trace.AppendRedis(opt.Redis)
  201. }
  202. }()
  203. for _, f := range options {
  204. f(opt)
  205. }
  206. if err := c.client.HSet(c.ctx, key, field, value).Err(); err != nil {
  207. return errors.Wrapf(err, "redis set key: %s field: %s err", key, field)
  208. }
  209. return nil
  210. }
  211. func (c *cacheRepo) Close() error {
  212. return c.client.Close()
  213. }