123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- package cache
- import (
- "context"
- "time"
- "git.bvbej.com/bvbej/base-golang/pkg/errors"
- "git.bvbej.com/bvbej/base-golang/pkg/time_parse"
- "git.bvbej.com/bvbej/base-golang/pkg/trace"
- "github.com/go-redis/redis/v8"
- )
- type Option func(*option)
- type Trace = trace.T
- type option struct {
- Trace *trace.Trace
- Redis *trace.Redis
- }
- func newOption() *option {
- return &option{}
- }
- var _ Repo = (*cacheRepo)(nil)
- type Repo interface {
- i()
- Set(key, value string, ttl time.Duration, options ...Option) error
- Get(key string, options ...Option) (string, error)
- TTL(key string) (time.Duration, error)
- Expire(key string, ttl time.Duration) bool
- ExpireAt(key string, ttl time.Time) bool
- Del(key string, options ...Option) bool
- Exists(keys ...string) bool
- Incr(key string, options ...Option) int64
- HGet(key, field string, options ...Option) (string, error)
- HSet(key, field, value string, options ...Option) error
- Close() error
- }
- type cacheRepo struct {
- client *redis.Client
- ctx context.Context
- }
- func New(addr, pass string, db, maxRetries, poolSize, minIdleConn int) (Repo, error) {
- client := redis.NewClient(&redis.Options{
- Addr: addr,
- Password: pass,
- DB: db,
- MaxRetries: maxRetries,
- PoolSize: poolSize,
- MinIdleConns: minIdleConn,
- })
- ctx := context.TODO()
- if err := client.Ping(ctx).Err(); err != nil {
- return nil, errors.Wrap(err, "ping redis err")
- }
- return &cacheRepo{
- client: client,
- ctx: ctx,
- }, nil
- }
- func WithTrace(t Trace) Option {
- return func(opt *option) {
- if t != nil {
- opt.Trace = t.(*trace.Trace)
- opt.Redis = new(trace.Redis)
- }
- }
- }
- func (c *cacheRepo) i() {}
- func (c *cacheRepo) Set(key, value string, ttl time.Duration, options ...Option) error {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "set"
- opt.Redis.Key = key
- opt.Redis.Value = value
- opt.Redis.TTL = ttl.Minutes()
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- if err := c.client.Set(c.ctx, key, value, ttl).Err(); err != nil {
- return errors.Wrapf(err, "redis set key: %s err", key)
- }
- return nil
- }
- func (c *cacheRepo) Get(key string, options ...Option) (string, error) {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "get"
- opt.Redis.Key = key
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- value, err := c.client.Get(c.ctx, key).Result()
- if err != nil {
- return "", errors.Wrapf(err, "redis get key: %s err", key)
- }
- return value, nil
- }
- func (c *cacheRepo) TTL(key string) (time.Duration, error) {
- ttl, err := c.client.TTL(c.ctx, key).Result()
- if err != nil {
- return -1, errors.Wrapf(err, "redis get key: %s err", key)
- }
- return ttl, nil
- }
- func (c *cacheRepo) Expire(key string, ttl time.Duration) bool {
- ok, _ := c.client.Expire(c.ctx, key, ttl).Result()
- return ok
- }
- func (c *cacheRepo) ExpireAt(key string, ttl time.Time) bool {
- ok, _ := c.client.ExpireAt(c.ctx, key, ttl).Result()
- return ok
- }
- func (c *cacheRepo) Exists(keys ...string) bool {
- if len(keys) == 0 {
- return true
- }
- value, _ := c.client.Exists(c.ctx, keys...).Result()
- return value > 0
- }
- func (c *cacheRepo) Del(key string, options ...Option) bool {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "del"
- opt.Redis.Key = key
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- if key == "" {
- return true
- }
- value, _ := c.client.Del(c.ctx, key).Result()
- return value > 0
- }
- func (c *cacheRepo) Incr(key string, options ...Option) int64 {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "incr"
- opt.Redis.Key = key
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- value, _ := c.client.Incr(c.ctx, key).Result()
- return value
- }
- func (c *cacheRepo) HGet(key, field string, options ...Option) (string, error) {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "get"
- opt.Redis.Key = key
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- value, err := c.client.HGet(c.ctx, key, field).Result()
- if err != nil {
- return "", errors.Wrapf(err, "redis hget key: %s field: %s", key, field)
- }
- return value, nil
- }
- func (c *cacheRepo) HSet(key, field, value string, options ...Option) error {
- ts := time.Now()
- opt := newOption()
- defer func() {
- if opt.Trace != nil {
- opt.Redis.Timestamp = time_parse.CSTLayoutString()
- opt.Redis.Handle = "set"
- opt.Redis.Key = key
- opt.Redis.Value = value
- opt.Redis.CostSeconds = time.Since(ts).Seconds()
- opt.Trace.AppendRedis(opt.Redis)
- }
- }()
- for _, f := range options {
- f(opt)
- }
- if err := c.client.HSet(c.ctx, key, field, value).Err(); err != nil {
- return errors.Wrapf(err, "redis set key: %s field: %s err", key, field)
- }
- return nil
- }
- func (c *cacheRepo) Close() error {
- return c.client.Close()
- }
|