github.com/shuguocloud/go-zero@v1.3.0/core/stores/cache/cache.go (about) 1 package cache 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/shuguocloud/go-zero/core/errorx" 9 "github.com/shuguocloud/go-zero/core/hash" 10 "github.com/shuguocloud/go-zero/core/syncx" 11 ) 12 13 type ( 14 // Cache interface is used to define the cache implementation. 15 Cache interface { 16 Del(keys ...string) error 17 Get(key string, v interface{}) error 18 IsNotFound(err error) bool 19 Set(key string, v interface{}) error 20 SetWithExpire(key string, v interface{}, expire time.Duration) error 21 Take(v interface{}, key string, query func(v interface{}) error) error 22 TakeWithExpire(v interface{}, key string, query func(v interface{}, expire time.Duration) error) error 23 } 24 25 cacheCluster struct { 26 dispatcher *hash.ConsistentHash 27 errNotFound error 28 } 29 ) 30 31 // New returns a Cache. 32 func New(c ClusterConf, barrier syncx.SingleFlight, st *Stat, errNotFound error, 33 opts ...Option) Cache { 34 if len(c) == 0 || TotalWeights(c) <= 0 { 35 log.Fatal("no cache nodes") 36 } 37 38 if len(c) == 1 { 39 return NewNode(c[0].NewRedis(), barrier, st, errNotFound, opts...) 40 } 41 42 dispatcher := hash.NewConsistentHash() 43 for _, node := range c { 44 cn := NewNode(node.NewRedis(), barrier, st, errNotFound, opts...) 45 dispatcher.AddWithWeight(cn, node.Weight) 46 } 47 48 return cacheCluster{ 49 dispatcher: dispatcher, 50 errNotFound: errNotFound, 51 } 52 } 53 54 func (cc cacheCluster) Del(keys ...string) error { 55 switch len(keys) { 56 case 0: 57 return nil 58 case 1: 59 key := keys[0] 60 c, ok := cc.dispatcher.Get(key) 61 if !ok { 62 return cc.errNotFound 63 } 64 65 return c.(Cache).Del(key) 66 default: 67 var be errorx.BatchError 68 nodes := make(map[interface{}][]string) 69 for _, key := range keys { 70 c, ok := cc.dispatcher.Get(key) 71 if !ok { 72 be.Add(fmt.Errorf("key %q not found", key)) 73 continue 74 } 75 76 nodes[c] = append(nodes[c], key) 77 } 78 for c, ks := range nodes { 79 if err := c.(Cache).Del(ks...); err != nil { 80 be.Add(err) 81 } 82 } 83 84 return be.Err() 85 } 86 } 87 88 func (cc cacheCluster) Get(key string, v interface{}) error { 89 c, ok := cc.dispatcher.Get(key) 90 if !ok { 91 return cc.errNotFound 92 } 93 94 return c.(Cache).Get(key, v) 95 } 96 97 func (cc cacheCluster) IsNotFound(err error) bool { 98 return err == cc.errNotFound 99 } 100 101 func (cc cacheCluster) Set(key string, v interface{}) error { 102 c, ok := cc.dispatcher.Get(key) 103 if !ok { 104 return cc.errNotFound 105 } 106 107 return c.(Cache).Set(key, v) 108 } 109 110 func (cc cacheCluster) SetWithExpire(key string, v interface{}, expire time.Duration) error { 111 c, ok := cc.dispatcher.Get(key) 112 if !ok { 113 return cc.errNotFound 114 } 115 116 return c.(Cache).SetWithExpire(key, v, expire) 117 } 118 119 func (cc cacheCluster) Take(v interface{}, key string, query func(v interface{}) error) error { 120 c, ok := cc.dispatcher.Get(key) 121 if !ok { 122 return cc.errNotFound 123 } 124 125 return c.(Cache).Take(v, key, query) 126 } 127 128 func (cc cacheCluster) TakeWithExpire(v interface{}, key string, 129 query func(v interface{}, expire time.Duration) error) error { 130 c, ok := cc.dispatcher.Get(key) 131 if !ok { 132 return cc.errNotFound 133 } 134 135 return c.(Cache).TakeWithExpire(v, key, query) 136 }