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

325 regels
9.0 KiB

  1. package cache
  2. import (
  3. "errors"
  4. "log"
  5. "strings"
  6. "time"
  7. redigo "github.com/gomodule/redigo/redis"
  8. )
  9. type RedisPool struct {
  10. *redigo.Pool
  11. }
  12. func NewRedisPool(cfg *Config) *RedisPool {
  13. return &RedisPool{&redigo.Pool{
  14. MaxIdle: cfg.MaxIdle,
  15. IdleTimeout: cfg.IdleTimeout,
  16. MaxActive: cfg.MaxActive,
  17. Wait: cfg.Wait,
  18. Dial: func() (redigo.Conn, error) {
  19. c, err := redigo.Dial("tcp", cfg.Server)
  20. if err != nil {
  21. log.Println("Redis Dial failed: ", err)
  22. return nil, err
  23. }
  24. if cfg.Password != "" {
  25. if _, err := c.Do("AUTH", cfg.Password); err != nil {
  26. c.Close()
  27. log.Println("Redis AUTH failed: ", err)
  28. return nil, err
  29. }
  30. }
  31. return c, err
  32. },
  33. TestOnBorrow: func(c redigo.Conn, t time.Time) error {
  34. _, err := c.Do("PING")
  35. if err != nil {
  36. log.Println("Unable to ping to redis server:", err)
  37. }
  38. return err
  39. },
  40. }}
  41. }
  42. func (p *RedisPool) Do(cmd string, args ...interface{}) (reply interface{}, err error) {
  43. conn := pool.Get()
  44. defer conn.Close()
  45. return conn.Do(cmd, args...)
  46. }
  47. func (p *RedisPool) GetPool() *redigo.Pool {
  48. return pool
  49. }
  50. func (p *RedisPool) ParseKey(key string, vars []string) (string, error) {
  51. arr := strings.Split(key, conf.KeyPlaceholder)
  52. actualKey := ""
  53. if len(arr) != len(vars)+1 {
  54. return "", errors.New("redis/connection.go: Insufficient arguments to parse key")
  55. } else {
  56. for index, val := range arr {
  57. if index == 0 {
  58. actualKey = arr[index]
  59. } else {
  60. actualKey += vars[index-1] + val
  61. }
  62. }
  63. }
  64. return getPrefixedKey(actualKey), nil
  65. }
  66. func (p *RedisPool) getPrefixedKey(key string) string {
  67. return conf.KeyPrefix + conf.KeyDelimiter + key
  68. }
  69. func (p *RedisPool) StripEnvKey(key string) string {
  70. return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter)
  71. }
  72. func (p *RedisPool) SplitKey(key string) []string {
  73. return strings.Split(key, conf.KeyDelimiter)
  74. }
  75. func (p *RedisPool) Expire(key string, ttl int) (interface{}, error) {
  76. return Do("EXPIRE", key, ttl)
  77. }
  78. func (p *RedisPool) Persist(key string) (interface{}, error) {
  79. return Do("PERSIST", key)
  80. }
  81. func (p *RedisPool) Del(key string) (interface{}, error) {
  82. return Do("DEL", key)
  83. }
  84. func (p *RedisPool) Set(key string, data interface{}) (interface{}, error) {
  85. // set
  86. return Do("SET", key, data)
  87. }
  88. func (p *RedisPool) SetNX(key string, data interface{}) (interface{}, error) {
  89. return Do("SETNX", key, data)
  90. }
  91. func (p *RedisPool) SetEx(key string, data interface{}, ttl int) (interface{}, error) {
  92. return Do("SETEX", key, ttl, data)
  93. }
  94. func (p *RedisPool) Get(key string) (interface{}, error) {
  95. // get
  96. return Do("GET", key)
  97. }
  98. func (p *RedisPool) GetStringMap(key string) (map[string]string, error) {
  99. // get
  100. return redigo.StringMap(Do("GET", key))
  101. }
  102. func (p *RedisPool) GetTTL(key string) (time.Duration, error) {
  103. ttl, err := redigo.Int64(Do("TTL", key))
  104. return time.Duration(ttl) * time.Second, err
  105. }
  106. func (p *RedisPool) GetBytes(key string) ([]byte, error) {
  107. return redigo.Bytes(Do("GET", key))
  108. }
  109. func (p *RedisPool) GetString(key string) (string, error) {
  110. return redigo.String(Do("GET", key))
  111. }
  112. func (p *RedisPool) GetInt(key string) (int, error) {
  113. return redigo.Int(Do("GET", key))
  114. }
  115. func (p *RedisPool) GetStringLength(key string) (int, error) {
  116. return redigo.Int(Do("STRLEN", key))
  117. }
  118. func (p *RedisPool) ZAdd(key string, score float64, data interface{}) (interface{}, error) {
  119. return Do("ZADD", key, score, data)
  120. }
  121. func (p *RedisPool) ZRem(key string, data interface{}) (interface{}, error) {
  122. return Do("ZREM", key, data)
  123. }
  124. func (p *RedisPool) ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) {
  125. if withScores {
  126. return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES"))
  127. }
  128. return redigo.Values(Do("ZRANGE", key, start, end))
  129. }
  130. func (p *RedisPool) SAdd(setName string, data interface{}) (interface{}, error) {
  131. return Do("SADD", setName, data)
  132. }
  133. func (p *RedisPool) SCard(setName string) (int64, error) {
  134. return redigo.Int64(Do("SCARD", setName))
  135. }
  136. func (p *RedisPool) SIsMember(setName string, data interface{}) (bool, error) {
  137. return redigo.Bool(Do("SISMEMBER", setName, data))
  138. }
  139. func (p *RedisPool) SMembers(setName string) ([]string, error) {
  140. return redigo.Strings(Do("SMEMBERS", setName))
  141. }
  142. func (p *RedisPool) SRem(setName string, data interface{}) (interface{}, error) {
  143. return Do("SREM", setName, data)
  144. }
  145. func (p *RedisPool) HSet(key string, HKey string, data interface{}) (interface{}, error) {
  146. return Do("HSET", key, HKey, data)
  147. }
  148. func (p *RedisPool) HGet(key string, HKey string) (interface{}, error) {
  149. return Do("HGET", key, HKey)
  150. }
  151. func (p *RedisPool) HMGet(key string, hashKeys ...string) ([]interface{}, error) {
  152. ret, err := Do("HMGET", key, hashKeys)
  153. if err != nil {
  154. return nil, err
  155. }
  156. reta, ok := ret.([]interface{})
  157. if !ok {
  158. return nil, errors.New("result not an array")
  159. }
  160. return reta, nil
  161. }
  162. func (p *RedisPool) HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) {
  163. if len(hashKeys) == 0 || len(hashKeys) != len(vals) {
  164. var ret interface{}
  165. return ret, errors.New("bad length")
  166. }
  167. input := []interface{}{key}
  168. for i, v := range hashKeys {
  169. input = append(input, v, vals[i])
  170. }
  171. return Do("HMSET", input...)
  172. }
  173. func (p *RedisPool) HGetString(key string, HKey string) (string, error) {
  174. return redigo.String(Do("HGET", key, HKey))
  175. }
  176. func (p *RedisPool) HGetFloat(key string, HKey string) (float64, error) {
  177. f, err := redigo.Float64(Do("HGET", key, HKey))
  178. return float64(f), err
  179. }
  180. func (p *RedisPool) HGetInt(key string, HKey string) (int, error) {
  181. return redigo.Int(Do("HGET", key, HKey))
  182. }
  183. func (p *RedisPool) HGetInt64(key string, HKey string) (int64, error) {
  184. return redigo.Int64(Do("HGET", key, HKey))
  185. }
  186. func (p *RedisPool) HGetBool(key string, HKey string) (bool, error) {
  187. return redigo.Bool(Do("HGET", key, HKey))
  188. }
  189. func (p *RedisPool) HDel(key string, HKey string) (interface{}, error) {
  190. return Do("HDEL", key, HKey)
  191. }
  192. func (p *RedisPool) HGetAll(key string) (map[string]interface{}, error) {
  193. vals, err := redigo.Values(Do("HGETALL", key))
  194. if err != nil {
  195. return nil, err
  196. }
  197. num := len(vals) / 2
  198. result := make(map[string]interface{}, num)
  199. for i := 0; i < num; i++ {
  200. key, _ := redigo.String(vals[2*i], nil)
  201. result[key] = vals[2*i+1]
  202. }
  203. return result, nil
  204. }
  205. // NOTE: Use this in production environment with extreme care.
  206. // Read more here:https://redigo.io/commands/keys
  207. func (p *RedisPool) Keys(pattern string) ([]string, error) {
  208. return redigo.Strings(Do("KEYS", pattern))
  209. }
  210. func (p *RedisPool) HKeys(key string) ([]string, error) {
  211. return redigo.Strings(Do("HKEYS", key))
  212. }
  213. func (p *RedisPool) Exists(key string) (bool, error) {
  214. count, err := redigo.Int(Do("EXISTS", key))
  215. if count == 0 {
  216. return false, err
  217. } else {
  218. return true, err
  219. }
  220. }
  221. func (p *RedisPool) Incr(key string) (int64, error) {
  222. return redigo.Int64(Do("INCR", key))
  223. }
  224. func (p *RedisPool) Decr(key string) (int64, error) {
  225. return redigo.Int64(Do("DECR", key))
  226. }
  227. func (p *RedisPool) IncrBy(key string, incBy int64) (int64, error) {
  228. return redigo.Int64(Do("INCRBY", key, incBy))
  229. }
  230. func (p *RedisPool) DecrBy(key string, decrBy int64) (int64, error) {
  231. return redigo.Int64(Do("DECRBY", key))
  232. }
  233. func (p *RedisPool) IncrByFloat(key string, incBy float64) (float64, error) {
  234. return redigo.Float64(Do("INCRBYFLOAT", key, incBy))
  235. }
  236. func (p *RedisPool) DecrByFloat(key string, decrBy float64) (float64, error) {
  237. return redigo.Float64(Do("DECRBYFLOAT", key, decrBy))
  238. }
  239. // use for message queue
  240. func (p *RedisPool) LPush(key string, data interface{}) (interface{}, error) {
  241. // set
  242. return Do("LPUSH", key, data)
  243. }
  244. func (p *RedisPool) LPop(key string) (interface{}, error) {
  245. return Do("LPOP", key)
  246. }
  247. func (p *RedisPool) LPopString(key string) (string, error) {
  248. return redigo.String(Do("LPOP", key))
  249. }
  250. func (p *RedisPool) LPopFloat(key string) (float64, error) {
  251. f, err := redigo.Float64(Do("LPOP", key))
  252. return float64(f), err
  253. }
  254. func (p *RedisPool) LPopInt(key string) (int, error) {
  255. return redigo.Int(Do("LPOP", key))
  256. }
  257. func (p *RedisPool) LPopInt64(key string) (int64, error) {
  258. return redigo.Int64(Do("LPOP", key))
  259. }
  260. func (p *RedisPool) RPush(key string, data interface{}) (interface{}, error) {
  261. // set
  262. return Do("RPUSH", key, data)
  263. }
  264. func (p *RedisPool) RPop(key string) (interface{}, error) {
  265. return Do("RPOP", key)
  266. }
  267. func (p *RedisPool) RPopString(key string) (string, error) {
  268. return redigo.String(Do("RPOP", key))
  269. }
  270. func (p *RedisPool) RPopFloat(key string) (float64, error) {
  271. f, err := redigo.Float64(Do("RPOP", key))
  272. return float64(f), err
  273. }
  274. func (p *RedisPool) RPopInt(key string) (int, error) {
  275. return redigo.Int(Do("RPOP", key))
  276. }
  277. func (p *RedisPool) RPopInt64(key string) (int64, error) {
  278. return redigo.Int64(Do("RPOP", key))
  279. }
  280. func (p *RedisPool) Scan(cursor int64, pattern string, count int64) (int64, []string, error) {
  281. var items []string
  282. var newCursor int64
  283. values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count))
  284. if err != nil {
  285. return 0, nil, err
  286. }
  287. values, err = redigo.Scan(values, &newCursor, &items)
  288. if err != nil {
  289. return 0, nil, err
  290. }
  291. return newCursor, items, nil
  292. }