github.com/shuguocloud/go-zero@v1.3.0/core/stores/redis/redis.go (about)

     1  package redis
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"time"
     8  
     9  	red "github.com/go-redis/redis"
    10  	"github.com/shuguocloud/go-zero/core/breaker"
    11  	"github.com/shuguocloud/go-zero/core/mapping"
    12  	"github.com/shuguocloud/go-zero/core/syncx"
    13  )
    14  
    15  const (
    16  	// ClusterType means redis cluster.
    17  	ClusterType = "cluster"
    18  	// NodeType means redis node.
    19  	NodeType = "node"
    20  	// Nil is an alias of redis.Nil.
    21  	Nil = red.Nil
    22  
    23  	blockingQueryTimeout = 5 * time.Second
    24  	readWriteTimeout     = 2 * time.Second
    25  	defaultSlowThreshold = time.Millisecond * 100
    26  )
    27  
    28  var (
    29  	// ErrNilNode is an error that indicates a nil redis node.
    30  	ErrNilNode    = errors.New("nil redis node")
    31  	slowThreshold = syncx.ForAtomicDuration(defaultSlowThreshold)
    32  )
    33  
    34  type (
    35  	// Option defines the method to customize a Redis.
    36  	Option func(r *Redis)
    37  
    38  	// A Pair is a key/pair set used in redis zset.
    39  	Pair struct {
    40  		Key   string
    41  		Score int64
    42  	}
    43  
    44  	// Redis defines a redis node/cluster. It is thread-safe.
    45  	Redis struct {
    46  		Addr string
    47  		Type string
    48  		Pass string
    49  		tls  bool
    50  		brk  breaker.Breaker
    51  	}
    52  
    53  	// RedisNode interface represents a redis node.
    54  	RedisNode interface {
    55  		red.Cmdable
    56  	}
    57  
    58  	// GeoLocation is used with GeoAdd to add geospatial location.
    59  	GeoLocation = red.GeoLocation
    60  	// GeoRadiusQuery is used with GeoRadius to query geospatial index.
    61  	GeoRadiusQuery = red.GeoRadiusQuery
    62  	// GeoPos is used to represent a geo position.
    63  	GeoPos = red.GeoPos
    64  
    65  	// Pipeliner is an alias of redis.Pipeliner.
    66  	Pipeliner = red.Pipeliner
    67  
    68  	// Z represents sorted set member.
    69  	Z = red.Z
    70  	// ZStore is an alias of redis.ZStore.
    71  	ZStore = red.ZStore
    72  
    73  	// IntCmd is an alias of redis.IntCmd.
    74  	IntCmd = red.IntCmd
    75  	// FloatCmd is an alias of redis.FloatCmd.
    76  	FloatCmd = red.FloatCmd
    77  	// StringCmd is an alias of redis.StringCmd.
    78  	StringCmd = red.StringCmd
    79  )
    80  
    81  // New returns a Redis with given options.
    82  func New(addr string, opts ...Option) *Redis {
    83  	r := &Redis{
    84  		Addr: addr,
    85  		Type: NodeType,
    86  		brk:  breaker.NewBreaker(),
    87  	}
    88  
    89  	for _, opt := range opts {
    90  		opt(r)
    91  	}
    92  
    93  	return r
    94  }
    95  
    96  // NewRedis returns a Redis.
    97  // Deprecated: use New instead, will be removed in v2.
    98  func NewRedis(redisAddr, redisType string, redisPass ...string) *Redis {
    99  	var opts []Option
   100  	if redisType == ClusterType {
   101  		opts = append(opts, Cluster())
   102  	}
   103  	for _, v := range redisPass {
   104  		opts = append(opts, WithPass(v))
   105  	}
   106  
   107  	return New(redisAddr, opts...)
   108  }
   109  
   110  // BitCount is redis bitcount command implementation.
   111  func (s *Redis) BitCount(key string, start, end int64) (val int64, err error) {
   112  	err = s.brk.DoWithAcceptable(func() error {
   113  		conn, err := getRedis(s)
   114  		if err != nil {
   115  			return err
   116  		}
   117  
   118  		val, err = conn.BitCount(key, &red.BitCount{
   119  			Start: start,
   120  			End:   end,
   121  		}).Result()
   122  		return err
   123  	}, acceptable)
   124  
   125  	return
   126  }
   127  
   128  // BitOpAnd is redis bit operation (and) command implementation.
   129  func (s *Redis) BitOpAnd(destKey string, keys ...string) (val int64, err error) {
   130  	err = s.brk.DoWithAcceptable(func() error {
   131  		conn, err := getRedis(s)
   132  		if err != nil {
   133  			return err
   134  		}
   135  
   136  		val, err = conn.BitOpAnd(destKey, keys...).Result()
   137  		return err
   138  	}, acceptable)
   139  
   140  	return
   141  }
   142  
   143  // BitOpNot is redis bit operation (not) command implementation.
   144  func (s *Redis) BitOpNot(destKey, key string) (val int64, err error) {
   145  	err = s.brk.DoWithAcceptable(func() error {
   146  		conn, err := getRedis(s)
   147  		if err != nil {
   148  			return err
   149  		}
   150  
   151  		val, err = conn.BitOpNot(destKey, key).Result()
   152  		return err
   153  	}, acceptable)
   154  
   155  	return
   156  }
   157  
   158  // BitOpOr is redis bit operation (or) command implementation.
   159  func (s *Redis) BitOpOr(destKey string, keys ...string) (val int64, err error) {
   160  	err = s.brk.DoWithAcceptable(func() error {
   161  		conn, err := getRedis(s)
   162  		if err != nil {
   163  			return err
   164  		}
   165  
   166  		val, err = conn.BitOpOr(destKey, keys...).Result()
   167  		return err
   168  	}, acceptable)
   169  
   170  	return
   171  }
   172  
   173  // BitOpXor is redis bit operation (xor) command implementation.
   174  func (s *Redis) BitOpXor(destKey string, keys ...string) (val int64, err error) {
   175  	err = s.brk.DoWithAcceptable(func() error {
   176  		conn, err := getRedis(s)
   177  		if err != nil {
   178  			return err
   179  		}
   180  
   181  		val, err = conn.BitOpXor(destKey, keys...).Result()
   182  		return err
   183  	}, acceptable)
   184  
   185  	return
   186  }
   187  
   188  // BitPos is redis bitpos command implementation.
   189  func (s *Redis) BitPos(key string, bit, start, end int64) (val int64, err error) {
   190  	err = s.brk.DoWithAcceptable(func() error {
   191  		conn, err := getRedis(s)
   192  		if err != nil {
   193  			return err
   194  		}
   195  
   196  		val, err = conn.BitPos(key, bit, start, end).Result()
   197  		return err
   198  	}, acceptable)
   199  
   200  	return
   201  }
   202  
   203  // Blpop uses passed in redis connection to execute blocking queries.
   204  // Doesn't benefit from pooling redis connections of blocking queries
   205  func (s *Redis) Blpop(redisNode RedisNode, key string) (string, error) {
   206  	if redisNode == nil {
   207  		return "", ErrNilNode
   208  	}
   209  
   210  	vals, err := redisNode.BLPop(blockingQueryTimeout, key).Result()
   211  	if err != nil {
   212  		return "", err
   213  	}
   214  
   215  	if len(vals) < 2 {
   216  		return "", fmt.Errorf("no value on key: %s", key)
   217  	}
   218  
   219  	return vals[1], nil
   220  }
   221  
   222  // BlpopEx uses passed in redis connection to execute blpop command.
   223  // The difference against Blpop is that this method returns a bool to indicate success.
   224  func (s *Redis) BlpopEx(redisNode RedisNode, key string) (string, bool, error) {
   225  	if redisNode == nil {
   226  		return "", false, ErrNilNode
   227  	}
   228  
   229  	vals, err := redisNode.BLPop(blockingQueryTimeout, key).Result()
   230  	if err != nil {
   231  		return "", false, err
   232  	}
   233  
   234  	if len(vals) < 2 {
   235  		return "", false, fmt.Errorf("no value on key: %s", key)
   236  	}
   237  
   238  	return vals[1], true, nil
   239  }
   240  
   241  // Decr is the implementation of redis decr command.
   242  func (s *Redis) Decr(key string) (val int64, err error) {
   243  	err = s.brk.DoWithAcceptable(func() error {
   244  		conn, err := getRedis(s)
   245  		if err != nil {
   246  			return err
   247  		}
   248  
   249  		val, err = conn.Decr(key).Result()
   250  		return err
   251  	}, acceptable)
   252  
   253  	return
   254  }
   255  
   256  // Decrby is the implementation of redis decrby command.
   257  func (s *Redis) Decrby(key string, increment int64) (val int64, err error) {
   258  	err = s.brk.DoWithAcceptable(func() error {
   259  		conn, err := getRedis(s)
   260  		if err != nil {
   261  			return err
   262  		}
   263  
   264  		val, err = conn.DecrBy(key, increment).Result()
   265  		return err
   266  	}, acceptable)
   267  
   268  	return
   269  }
   270  
   271  // Del deletes keys.
   272  func (s *Redis) Del(keys ...string) (val int, err error) {
   273  	err = s.brk.DoWithAcceptable(func() error {
   274  		conn, err := getRedis(s)
   275  		if err != nil {
   276  			return err
   277  		}
   278  
   279  		v, err := conn.Del(keys...).Result()
   280  		if err != nil {
   281  			return err
   282  		}
   283  
   284  		val = int(v)
   285  		return nil
   286  	}, acceptable)
   287  
   288  	return
   289  }
   290  
   291  // Eval is the implementation of redis eval command.
   292  func (s *Redis) Eval(script string, keys []string, args ...interface{}) (val interface{}, err error) {
   293  	err = s.brk.DoWithAcceptable(func() error {
   294  		conn, err := getRedis(s)
   295  		if err != nil {
   296  			return err
   297  		}
   298  
   299  		val, err = conn.Eval(script, keys, args...).Result()
   300  		return err
   301  	}, acceptable)
   302  
   303  	return
   304  }
   305  
   306  // EvalSha is the implementation of redis evalsha command.
   307  func (s *Redis) EvalSha(sha string, keys []string, args ...interface{}) (val interface{}, err error) {
   308  	err = s.brk.DoWithAcceptable(func() error {
   309  		conn, err := getRedis(s)
   310  		if err != nil {
   311  			return err
   312  		}
   313  
   314  		val, err = conn.EvalSha(sha, keys, args...).Result()
   315  		return err
   316  	}, acceptable)
   317  
   318  	return
   319  }
   320  
   321  // Exists is the implementation of redis exists command.
   322  func (s *Redis) Exists(key string) (val bool, err error) {
   323  	err = s.brk.DoWithAcceptable(func() error {
   324  		conn, err := getRedis(s)
   325  		if err != nil {
   326  			return err
   327  		}
   328  
   329  		v, err := conn.Exists(key).Result()
   330  		if err != nil {
   331  			return err
   332  		}
   333  
   334  		val = v == 1
   335  		return nil
   336  	}, acceptable)
   337  
   338  	return
   339  }
   340  
   341  // Expire is the implementation of redis expire command.
   342  func (s *Redis) Expire(key string, seconds int) error {
   343  	return s.brk.DoWithAcceptable(func() error {
   344  		conn, err := getRedis(s)
   345  		if err != nil {
   346  			return err
   347  		}
   348  
   349  		return conn.Expire(key, time.Duration(seconds)*time.Second).Err()
   350  	}, acceptable)
   351  }
   352  
   353  // Expireat is the implementation of redis expireat command.
   354  func (s *Redis) Expireat(key string, expireTime int64) error {
   355  	return s.brk.DoWithAcceptable(func() error {
   356  		conn, err := getRedis(s)
   357  		if err != nil {
   358  			return err
   359  		}
   360  
   361  		return conn.ExpireAt(key, time.Unix(expireTime, 0)).Err()
   362  	}, acceptable)
   363  }
   364  
   365  // GeoAdd is the implementation of redis geoadd command.
   366  func (s *Redis) GeoAdd(key string, geoLocation ...*GeoLocation) (val int64, err error) {
   367  	err = s.brk.DoWithAcceptable(func() error {
   368  		conn, err := getRedis(s)
   369  		if err != nil {
   370  			return err
   371  		}
   372  
   373  		v, err := conn.GeoAdd(key, geoLocation...).Result()
   374  		if err != nil {
   375  			return err
   376  		}
   377  
   378  		val = v
   379  		return nil
   380  	}, acceptable)
   381  	return
   382  }
   383  
   384  // GeoDist is the implementation of redis geodist command.
   385  func (s *Redis) GeoDist(key, member1, member2, unit string) (val float64, err error) {
   386  	err = s.brk.DoWithAcceptable(func() error {
   387  		conn, err := getRedis(s)
   388  		if err != nil {
   389  			return err
   390  		}
   391  
   392  		v, err := conn.GeoDist(key, member1, member2, unit).Result()
   393  		if err != nil {
   394  			return err
   395  		}
   396  
   397  		val = v
   398  		return nil
   399  	}, acceptable)
   400  	return
   401  }
   402  
   403  // GeoHash is the implementation of redis geohash command.
   404  func (s *Redis) GeoHash(key string, members ...string) (val []string, err error) {
   405  	err = s.brk.DoWithAcceptable(func() error {
   406  		conn, err := getRedis(s)
   407  		if err != nil {
   408  			return err
   409  		}
   410  
   411  		v, err := conn.GeoHash(key, members...).Result()
   412  		if err != nil {
   413  			return err
   414  		}
   415  
   416  		val = v
   417  		return nil
   418  	}, acceptable)
   419  	return
   420  }
   421  
   422  // GeoRadius is the implementation of redis georadius command.
   423  func (s *Redis) GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) (val []GeoLocation, err error) {
   424  	err = s.brk.DoWithAcceptable(func() error {
   425  		conn, err := getRedis(s)
   426  		if err != nil {
   427  			return err
   428  		}
   429  
   430  		v, err := conn.GeoRadius(key, longitude, latitude, query).Result()
   431  		if err != nil {
   432  			return err
   433  		}
   434  
   435  		val = v
   436  		return nil
   437  	}, acceptable)
   438  	return
   439  }
   440  
   441  // GeoRadiusByMember is the implementation of redis georadiusbymember command.
   442  func (s *Redis) GeoRadiusByMember(key, member string, query *GeoRadiusQuery) (val []GeoLocation, err error) {
   443  	err = s.brk.DoWithAcceptable(func() error {
   444  		conn, err := getRedis(s)
   445  		if err != nil {
   446  			return err
   447  		}
   448  
   449  		v, err := conn.GeoRadiusByMember(key, member, query).Result()
   450  		if err != nil {
   451  			return err
   452  		}
   453  
   454  		val = v
   455  		return nil
   456  	}, acceptable)
   457  	return
   458  }
   459  
   460  // GeoPos is the implementation of redis geopos command.
   461  func (s *Redis) GeoPos(key string, members ...string) (val []*GeoPos, err error) {
   462  	err = s.brk.DoWithAcceptable(func() error {
   463  		conn, err := getRedis(s)
   464  		if err != nil {
   465  			return err
   466  		}
   467  
   468  		v, err := conn.GeoPos(key, members...).Result()
   469  		if err != nil {
   470  			return err
   471  		}
   472  
   473  		val = v
   474  		return nil
   475  	}, acceptable)
   476  	return
   477  }
   478  
   479  // Get is the implementation of redis get command.
   480  func (s *Redis) Get(key string) (val string, err error) {
   481  	err = s.brk.DoWithAcceptable(func() error {
   482  		conn, err := getRedis(s)
   483  		if err != nil {
   484  			return err
   485  		}
   486  
   487  		if val, err = conn.Get(key).Result(); err == red.Nil {
   488  			return nil
   489  		} else if err != nil {
   490  			return err
   491  		} else {
   492  			return nil
   493  		}
   494  	}, acceptable)
   495  
   496  	return
   497  }
   498  
   499  // GetBit is the implementation of redis getbit command.
   500  func (s *Redis) GetBit(key string, offset int64) (val int, err error) {
   501  	err = s.brk.DoWithAcceptable(func() error {
   502  		conn, err := getRedis(s)
   503  		if err != nil {
   504  			return err
   505  		}
   506  
   507  		v, err := conn.GetBit(key, offset).Result()
   508  		if err != nil {
   509  			return err
   510  		}
   511  
   512  		val = int(v)
   513  		return nil
   514  	}, acceptable)
   515  
   516  	return
   517  }
   518  
   519  // Hdel is the implementation of redis hdel command.
   520  func (s *Redis) Hdel(key string, fields ...string) (val bool, err error) {
   521  	err = s.brk.DoWithAcceptable(func() error {
   522  		conn, err := getRedis(s)
   523  		if err != nil {
   524  			return err
   525  		}
   526  
   527  		v, err := conn.HDel(key, fields...).Result()
   528  		if err != nil {
   529  			return err
   530  		}
   531  
   532  		val = v == 1
   533  		return nil
   534  	}, acceptable)
   535  
   536  	return
   537  }
   538  
   539  // Hexists is the implementation of redis hexists command.
   540  func (s *Redis) Hexists(key, field string) (val bool, err error) {
   541  	err = s.brk.DoWithAcceptable(func() error {
   542  		conn, err := getRedis(s)
   543  		if err != nil {
   544  			return err
   545  		}
   546  
   547  		val, err = conn.HExists(key, field).Result()
   548  		return err
   549  	}, acceptable)
   550  
   551  	return
   552  }
   553  
   554  // Hget is the implementation of redis hget command.
   555  func (s *Redis) Hget(key, field string) (val string, err error) {
   556  	err = s.brk.DoWithAcceptable(func() error {
   557  		conn, err := getRedis(s)
   558  		if err != nil {
   559  			return err
   560  		}
   561  
   562  		val, err = conn.HGet(key, field).Result()
   563  		return err
   564  	}, acceptable)
   565  
   566  	return
   567  }
   568  
   569  // Hgetall is the implementation of redis hgetall command.
   570  func (s *Redis) Hgetall(key string) (val map[string]string, err error) {
   571  	err = s.brk.DoWithAcceptable(func() error {
   572  		conn, err := getRedis(s)
   573  		if err != nil {
   574  			return err
   575  		}
   576  
   577  		val, err = conn.HGetAll(key).Result()
   578  		return err
   579  	}, acceptable)
   580  
   581  	return
   582  }
   583  
   584  // Hincrby is the implementation of redis hincrby command.
   585  func (s *Redis) Hincrby(key, field string, increment int) (val int, err error) {
   586  	err = s.brk.DoWithAcceptable(func() error {
   587  		conn, err := getRedis(s)
   588  		if err != nil {
   589  			return err
   590  		}
   591  
   592  		v, err := conn.HIncrBy(key, field, int64(increment)).Result()
   593  		if err != nil {
   594  			return err
   595  		}
   596  
   597  		val = int(v)
   598  		return nil
   599  	}, acceptable)
   600  
   601  	return
   602  }
   603  
   604  // Hkeys is the implementation of redis hkeys command.
   605  func (s *Redis) Hkeys(key string) (val []string, err error) {
   606  	err = s.brk.DoWithAcceptable(func() error {
   607  		conn, err := getRedis(s)
   608  		if err != nil {
   609  			return err
   610  		}
   611  
   612  		val, err = conn.HKeys(key).Result()
   613  		return err
   614  	}, acceptable)
   615  
   616  	return
   617  }
   618  
   619  // Hlen is the implementation of redis hlen command.
   620  func (s *Redis) Hlen(key string) (val int, err error) {
   621  	err = s.brk.DoWithAcceptable(func() error {
   622  		conn, err := getRedis(s)
   623  		if err != nil {
   624  			return err
   625  		}
   626  
   627  		v, err := conn.HLen(key).Result()
   628  		if err != nil {
   629  			return err
   630  		}
   631  
   632  		val = int(v)
   633  		return nil
   634  	}, acceptable)
   635  
   636  	return
   637  }
   638  
   639  // Hmget is the implementation of redis hmget command.
   640  func (s *Redis) Hmget(key string, fields ...string) (val []string, err error) {
   641  	err = s.brk.DoWithAcceptable(func() error {
   642  		conn, err := getRedis(s)
   643  		if err != nil {
   644  			return err
   645  		}
   646  
   647  		v, err := conn.HMGet(key, fields...).Result()
   648  		if err != nil {
   649  			return err
   650  		}
   651  
   652  		val = toStrings(v)
   653  		return nil
   654  	}, acceptable)
   655  
   656  	return
   657  }
   658  
   659  // Hset is the implementation of redis hset command.
   660  func (s *Redis) Hset(key, field, value string) error {
   661  	return s.brk.DoWithAcceptable(func() error {
   662  		conn, err := getRedis(s)
   663  		if err != nil {
   664  			return err
   665  		}
   666  
   667  		return conn.HSet(key, field, value).Err()
   668  	}, acceptable)
   669  }
   670  
   671  // Hsetnx is the implementation of redis hsetnx command.
   672  func (s *Redis) Hsetnx(key, field, value string) (val bool, err error) {
   673  	err = s.brk.DoWithAcceptable(func() error {
   674  		conn, err := getRedis(s)
   675  		if err != nil {
   676  			return err
   677  		}
   678  
   679  		val, err = conn.HSetNX(key, field, value).Result()
   680  		return err
   681  	}, acceptable)
   682  
   683  	return
   684  }
   685  
   686  // Hmset is the implementation of redis hmset command.
   687  func (s *Redis) Hmset(key string, fieldsAndValues map[string]string) error {
   688  	return s.brk.DoWithAcceptable(func() error {
   689  		conn, err := getRedis(s)
   690  		if err != nil {
   691  			return err
   692  		}
   693  
   694  		vals := make(map[string]interface{}, len(fieldsAndValues))
   695  		for k, v := range fieldsAndValues {
   696  			vals[k] = v
   697  		}
   698  
   699  		return conn.HMSet(key, vals).Err()
   700  	}, acceptable)
   701  }
   702  
   703  // Hscan is the implementation of redis hscan command.
   704  func (s *Redis) Hscan(key string, cursor uint64, match string, count int64) (keys []string, cur uint64, err error) {
   705  	err = s.brk.DoWithAcceptable(func() error {
   706  		conn, err := getRedis(s)
   707  		if err != nil {
   708  			return err
   709  		}
   710  
   711  		keys, cur, err = conn.HScan(key, cursor, match, count).Result()
   712  		return err
   713  	}, acceptable)
   714  
   715  	return
   716  }
   717  
   718  // Hvals is the implementation of redis hvals command.
   719  func (s *Redis) Hvals(key string) (val []string, err error) {
   720  	err = s.brk.DoWithAcceptable(func() error {
   721  		conn, err := getRedis(s)
   722  		if err != nil {
   723  			return err
   724  		}
   725  
   726  		val, err = conn.HVals(key).Result()
   727  		return err
   728  	}, acceptable)
   729  
   730  	return
   731  }
   732  
   733  // Incr is the implementation of redis incr command.
   734  func (s *Redis) Incr(key string) (val int64, err error) {
   735  	err = s.brk.DoWithAcceptable(func() error {
   736  		conn, err := getRedis(s)
   737  		if err != nil {
   738  			return err
   739  		}
   740  
   741  		val, err = conn.Incr(key).Result()
   742  		return err
   743  	}, acceptable)
   744  
   745  	return
   746  }
   747  
   748  // Incrby is the implementation of redis incrby command.
   749  func (s *Redis) Incrby(key string, increment int64) (val int64, err error) {
   750  	err = s.brk.DoWithAcceptable(func() error {
   751  		conn, err := getRedis(s)
   752  		if err != nil {
   753  			return err
   754  		}
   755  
   756  		val, err = conn.IncrBy(key, int64(increment)).Result()
   757  		return err
   758  	}, acceptable)
   759  
   760  	return
   761  }
   762  
   763  // Keys is the implementation of redis keys command.
   764  func (s *Redis) Keys(pattern string) (val []string, err error) {
   765  	err = s.brk.DoWithAcceptable(func() error {
   766  		conn, err := getRedis(s)
   767  		if err != nil {
   768  			return err
   769  		}
   770  
   771  		val, err = conn.Keys(pattern).Result()
   772  		return err
   773  	}, acceptable)
   774  
   775  	return
   776  }
   777  
   778  // Llen is the implementation of redis llen command.
   779  func (s *Redis) Llen(key string) (val int, err error) {
   780  	err = s.brk.DoWithAcceptable(func() error {
   781  		conn, err := getRedis(s)
   782  		if err != nil {
   783  			return err
   784  		}
   785  
   786  		v, err := conn.LLen(key).Result()
   787  		if err != nil {
   788  			return err
   789  		}
   790  
   791  		val = int(v)
   792  		return nil
   793  	}, acceptable)
   794  
   795  	return
   796  }
   797  
   798  // Lindex is the implementation of redis lindex command.
   799  func (s *Redis) Lindex(key string, index int64) (val string, err error) {
   800  	err = s.brk.DoWithAcceptable(func() error {
   801  		conn, err := getRedis(s)
   802  		if err != nil {
   803  			return err
   804  		}
   805  
   806  		val, err = conn.LIndex(key, index).Result()
   807  		return err
   808  	}, acceptable)
   809  
   810  	return
   811  }
   812  
   813  // Lpop is the implementation of redis lpop command.
   814  func (s *Redis) Lpop(key string) (val string, err error) {
   815  	err = s.brk.DoWithAcceptable(func() error {
   816  		conn, err := getRedis(s)
   817  		if err != nil {
   818  			return err
   819  		}
   820  
   821  		val, err = conn.LPop(key).Result()
   822  		return err
   823  	}, acceptable)
   824  
   825  	return
   826  }
   827  
   828  // Lpush is the implementation of redis lpush command.
   829  func (s *Redis) Lpush(key string, values ...interface{}) (val int, err error) {
   830  	err = s.brk.DoWithAcceptable(func() error {
   831  		conn, err := getRedis(s)
   832  		if err != nil {
   833  			return err
   834  		}
   835  
   836  		v, err := conn.LPush(key, values...).Result()
   837  		if err != nil {
   838  			return err
   839  		}
   840  
   841  		val = int(v)
   842  		return nil
   843  	}, acceptable)
   844  
   845  	return
   846  }
   847  
   848  // Lrange is the implementation of redis lrange command.
   849  func (s *Redis) Lrange(key string, start, stop int) (val []string, err error) {
   850  	err = s.brk.DoWithAcceptable(func() error {
   851  		conn, err := getRedis(s)
   852  		if err != nil {
   853  			return err
   854  		}
   855  
   856  		val, err = conn.LRange(key, int64(start), int64(stop)).Result()
   857  		return err
   858  	}, acceptable)
   859  
   860  	return
   861  }
   862  
   863  // Lrem is the implementation of redis lrem command.
   864  func (s *Redis) Lrem(key string, count int, value string) (val int, err error) {
   865  	err = s.brk.DoWithAcceptable(func() error {
   866  		conn, err := getRedis(s)
   867  		if err != nil {
   868  			return err
   869  		}
   870  
   871  		v, err := conn.LRem(key, int64(count), value).Result()
   872  		if err != nil {
   873  			return err
   874  		}
   875  
   876  		val = int(v)
   877  		return nil
   878  	}, acceptable)
   879  
   880  	return
   881  }
   882  
   883  // Ltrim is the implementation of redis ltrim command.
   884  func (s *Redis) Ltrim(key string, start, stop int64) error {
   885  	return s.brk.DoWithAcceptable(func() error {
   886  		conn, err := getRedis(s)
   887  		if err != nil {
   888  			return err
   889  		}
   890  
   891  		return conn.LTrim(key, start, stop).Err()
   892  	}, acceptable)
   893  }
   894  
   895  // Mget is the implementation of redis mget command.
   896  func (s *Redis) Mget(keys ...string) (val []string, err error) {
   897  	err = s.brk.DoWithAcceptable(func() error {
   898  		conn, err := getRedis(s)
   899  		if err != nil {
   900  			return err
   901  		}
   902  
   903  		v, err := conn.MGet(keys...).Result()
   904  		if err != nil {
   905  			return err
   906  		}
   907  
   908  		val = toStrings(v)
   909  		return nil
   910  	}, acceptable)
   911  
   912  	return
   913  }
   914  
   915  // Persist is the implementation of redis persist command.
   916  func (s *Redis) Persist(key string) (val bool, err error) {
   917  	err = s.brk.DoWithAcceptable(func() error {
   918  		conn, err := getRedis(s)
   919  		if err != nil {
   920  			return err
   921  		}
   922  
   923  		val, err = conn.Persist(key).Result()
   924  		return err
   925  	}, acceptable)
   926  
   927  	return
   928  }
   929  
   930  // Pfadd is the implementation of redis pfadd command.
   931  func (s *Redis) Pfadd(key string, values ...interface{}) (val bool, err error) {
   932  	err = s.brk.DoWithAcceptable(func() error {
   933  		conn, err := getRedis(s)
   934  		if err != nil {
   935  			return err
   936  		}
   937  
   938  		v, err := conn.PFAdd(key, values...).Result()
   939  		if err != nil {
   940  			return err
   941  		}
   942  
   943  		val = v == 1
   944  		return nil
   945  	}, acceptable)
   946  
   947  	return
   948  }
   949  
   950  // Pfcount is the implementation of redis pfcount command.
   951  func (s *Redis) Pfcount(key string) (val int64, err error) {
   952  	err = s.brk.DoWithAcceptable(func() error {
   953  		conn, err := getRedis(s)
   954  		if err != nil {
   955  			return err
   956  		}
   957  
   958  		val, err = conn.PFCount(key).Result()
   959  		return err
   960  	}, acceptable)
   961  
   962  	return
   963  }
   964  
   965  // Pfmerge is the implementation of redis pfmerge command.
   966  func (s *Redis) Pfmerge(dest string, keys ...string) error {
   967  	return s.brk.DoWithAcceptable(func() error {
   968  		conn, err := getRedis(s)
   969  		if err != nil {
   970  			return err
   971  		}
   972  
   973  		_, err = conn.PFMerge(dest, keys...).Result()
   974  		return err
   975  	}, acceptable)
   976  }
   977  
   978  // Ping is the implementation of redis ping command.
   979  func (s *Redis) Ping() (val bool) {
   980  	// ignore error, error means false
   981  	_ = s.brk.DoWithAcceptable(func() error {
   982  		conn, err := getRedis(s)
   983  		if err != nil {
   984  			val = false
   985  			return nil
   986  		}
   987  
   988  		v, err := conn.Ping().Result()
   989  		if err != nil {
   990  			val = false
   991  			return nil
   992  		}
   993  
   994  		val = v == "PONG"
   995  		return nil
   996  	}, acceptable)
   997  
   998  	return
   999  }
  1000  
  1001  // Pipelined lets fn to execute pipelined commands.
  1002  func (s *Redis) Pipelined(fn func(Pipeliner) error) (err error) {
  1003  	err = s.brk.DoWithAcceptable(func() error {
  1004  		conn, err := getRedis(s)
  1005  		if err != nil {
  1006  			return err
  1007  		}
  1008  
  1009  		_, err = conn.Pipelined(fn)
  1010  		return err
  1011  	}, acceptable)
  1012  
  1013  	return
  1014  }
  1015  
  1016  // Rpop is the implementation of redis rpop command.
  1017  func (s *Redis) Rpop(key string) (val string, err error) {
  1018  	err = s.brk.DoWithAcceptable(func() error {
  1019  		conn, err := getRedis(s)
  1020  		if err != nil {
  1021  			return err
  1022  		}
  1023  
  1024  		val, err = conn.RPop(key).Result()
  1025  		return err
  1026  	}, acceptable)
  1027  
  1028  	return
  1029  }
  1030  
  1031  // Rpush is the implementation of redis rpush command.
  1032  func (s *Redis) Rpush(key string, values ...interface{}) (val int, err error) {
  1033  	err = s.brk.DoWithAcceptable(func() error {
  1034  		conn, err := getRedis(s)
  1035  		if err != nil {
  1036  			return err
  1037  		}
  1038  
  1039  		v, err := conn.RPush(key, values...).Result()
  1040  		if err != nil {
  1041  			return err
  1042  		}
  1043  
  1044  		val = int(v)
  1045  		return nil
  1046  	}, acceptable)
  1047  
  1048  	return
  1049  }
  1050  
  1051  // Sadd is the implementation of redis sadd command.
  1052  func (s *Redis) Sadd(key string, values ...interface{}) (val int, err error) {
  1053  	err = s.brk.DoWithAcceptable(func() error {
  1054  		conn, err := getRedis(s)
  1055  		if err != nil {
  1056  			return err
  1057  		}
  1058  
  1059  		v, err := conn.SAdd(key, values...).Result()
  1060  		if err != nil {
  1061  			return err
  1062  		}
  1063  
  1064  		val = int(v)
  1065  		return nil
  1066  	}, acceptable)
  1067  
  1068  	return
  1069  }
  1070  
  1071  // Scan is the implementation of redis scan command.
  1072  func (s *Redis) Scan(cursor uint64, match string, count int64) (keys []string, cur uint64, err error) {
  1073  	err = s.brk.DoWithAcceptable(func() error {
  1074  		conn, err := getRedis(s)
  1075  		if err != nil {
  1076  			return err
  1077  		}
  1078  
  1079  		keys, cur, err = conn.Scan(cursor, match, count).Result()
  1080  		return err
  1081  	}, acceptable)
  1082  
  1083  	return
  1084  }
  1085  
  1086  // SetBit is the implementation of redis setbit command.
  1087  func (s *Redis) SetBit(key string, offset int64, value int) error {
  1088  	return s.brk.DoWithAcceptable(func() error {
  1089  		conn, err := getRedis(s)
  1090  		if err != nil {
  1091  			return err
  1092  		}
  1093  
  1094  		_, err = conn.SetBit(key, offset, value).Result()
  1095  		return err
  1096  	}, acceptable)
  1097  }
  1098  
  1099  // Sscan is the implementation of redis sscan command.
  1100  func (s *Redis) Sscan(key string, cursor uint64, match string, count int64) (keys []string, cur uint64, err error) {
  1101  	err = s.brk.DoWithAcceptable(func() error {
  1102  		conn, err := getRedis(s)
  1103  		if err != nil {
  1104  			return err
  1105  		}
  1106  
  1107  		keys, cur, err = conn.SScan(key, cursor, match, count).Result()
  1108  		return err
  1109  	}, acceptable)
  1110  
  1111  	return
  1112  }
  1113  
  1114  // Scard is the implementation of redis scard command.
  1115  func (s *Redis) Scard(key string) (val int64, err error) {
  1116  	err = s.brk.DoWithAcceptable(func() error {
  1117  		conn, err := getRedis(s)
  1118  		if err != nil {
  1119  			return err
  1120  		}
  1121  
  1122  		val, err = conn.SCard(key).Result()
  1123  		return err
  1124  	}, acceptable)
  1125  
  1126  	return
  1127  }
  1128  
  1129  // ScriptLoad is the implementation of redis script load command.
  1130  func (s *Redis) ScriptLoad(script string) (string, error) {
  1131  	conn, err := getRedis(s)
  1132  	if err != nil {
  1133  		return "", err
  1134  	}
  1135  
  1136  	return conn.ScriptLoad(script).Result()
  1137  }
  1138  
  1139  // Set is the implementation of redis set command.
  1140  func (s *Redis) Set(key, value string) error {
  1141  	return s.brk.DoWithAcceptable(func() error {
  1142  		conn, err := getRedis(s)
  1143  		if err != nil {
  1144  			return err
  1145  		}
  1146  
  1147  		return conn.Set(key, value, 0).Err()
  1148  	}, acceptable)
  1149  }
  1150  
  1151  // Setex is the implementation of redis setex command.
  1152  func (s *Redis) Setex(key, value string, seconds int) error {
  1153  	return s.brk.DoWithAcceptable(func() error {
  1154  		conn, err := getRedis(s)
  1155  		if err != nil {
  1156  			return err
  1157  		}
  1158  
  1159  		return conn.Set(key, value, time.Duration(seconds)*time.Second).Err()
  1160  	}, acceptable)
  1161  }
  1162  
  1163  // Setnx is the implementation of redis setnx command.
  1164  func (s *Redis) Setnx(key, value string) (val bool, err error) {
  1165  	err = s.brk.DoWithAcceptable(func() error {
  1166  		conn, err := getRedis(s)
  1167  		if err != nil {
  1168  			return err
  1169  		}
  1170  
  1171  		val, err = conn.SetNX(key, value, 0).Result()
  1172  		return err
  1173  	}, acceptable)
  1174  
  1175  	return
  1176  }
  1177  
  1178  // SetnxEx is the implementation of redis setnx command with expire.
  1179  func (s *Redis) SetnxEx(key, value string, seconds int) (val bool, err error) {
  1180  	err = s.brk.DoWithAcceptable(func() error {
  1181  		conn, err := getRedis(s)
  1182  		if err != nil {
  1183  			return err
  1184  		}
  1185  
  1186  		val, err = conn.SetNX(key, value, time.Duration(seconds)*time.Second).Result()
  1187  		return err
  1188  	}, acceptable)
  1189  
  1190  	return
  1191  }
  1192  
  1193  // Sismember is the implementation of redis sismember command.
  1194  func (s *Redis) Sismember(key string, value interface{}) (val bool, err error) {
  1195  	err = s.brk.DoWithAcceptable(func() error {
  1196  		conn, err := getRedis(s)
  1197  		if err != nil {
  1198  			return err
  1199  		}
  1200  
  1201  		val, err = conn.SIsMember(key, value).Result()
  1202  		return err
  1203  	}, acceptable)
  1204  
  1205  	return
  1206  }
  1207  
  1208  // Smembers is the implementation of redis smembers command.
  1209  func (s *Redis) Smembers(key string) (val []string, err error) {
  1210  	err = s.brk.DoWithAcceptable(func() error {
  1211  		conn, err := getRedis(s)
  1212  		if err != nil {
  1213  			return err
  1214  		}
  1215  
  1216  		val, err = conn.SMembers(key).Result()
  1217  		return err
  1218  	}, acceptable)
  1219  
  1220  	return
  1221  }
  1222  
  1223  // Spop is the implementation of redis spop command.
  1224  func (s *Redis) Spop(key string) (val string, err error) {
  1225  	err = s.brk.DoWithAcceptable(func() error {
  1226  		conn, err := getRedis(s)
  1227  		if err != nil {
  1228  			return err
  1229  		}
  1230  
  1231  		val, err = conn.SPop(key).Result()
  1232  		return err
  1233  	}, acceptable)
  1234  
  1235  	return
  1236  }
  1237  
  1238  // Srandmember is the implementation of redis srandmember command.
  1239  func (s *Redis) Srandmember(key string, count int) (val []string, err error) {
  1240  	err = s.brk.DoWithAcceptable(func() error {
  1241  		conn, err := getRedis(s)
  1242  		if err != nil {
  1243  			return err
  1244  		}
  1245  
  1246  		val, err = conn.SRandMemberN(key, int64(count)).Result()
  1247  		return err
  1248  	}, acceptable)
  1249  
  1250  	return
  1251  }
  1252  
  1253  // Srem is the implementation of redis srem command.
  1254  func (s *Redis) Srem(key string, values ...interface{}) (val int, err error) {
  1255  	err = s.brk.DoWithAcceptable(func() error {
  1256  		conn, err := getRedis(s)
  1257  		if err != nil {
  1258  			return err
  1259  		}
  1260  
  1261  		v, err := conn.SRem(key, values...).Result()
  1262  		if err != nil {
  1263  			return err
  1264  		}
  1265  
  1266  		val = int(v)
  1267  		return nil
  1268  	}, acceptable)
  1269  
  1270  	return
  1271  }
  1272  
  1273  // String returns the string representation of s.
  1274  func (s *Redis) String() string {
  1275  	return s.Addr
  1276  }
  1277  
  1278  // Sunion is the implementation of redis sunion command.
  1279  func (s *Redis) Sunion(keys ...string) (val []string, err error) {
  1280  	err = s.brk.DoWithAcceptable(func() error {
  1281  		conn, err := getRedis(s)
  1282  		if err != nil {
  1283  			return err
  1284  		}
  1285  
  1286  		val, err = conn.SUnion(keys...).Result()
  1287  		return err
  1288  	}, acceptable)
  1289  
  1290  	return
  1291  }
  1292  
  1293  // Sunionstore is the implementation of redis sunionstore command.
  1294  func (s *Redis) Sunionstore(destination string, keys ...string) (val int, err error) {
  1295  	err = s.brk.DoWithAcceptable(func() error {
  1296  		conn, err := getRedis(s)
  1297  		if err != nil {
  1298  			return err
  1299  		}
  1300  
  1301  		v, err := conn.SUnionStore(destination, keys...).Result()
  1302  		if err != nil {
  1303  			return err
  1304  		}
  1305  
  1306  		val = int(v)
  1307  		return nil
  1308  	}, acceptable)
  1309  
  1310  	return
  1311  }
  1312  
  1313  // Sdiff is the implementation of redis sdiff command.
  1314  func (s *Redis) Sdiff(keys ...string) (val []string, err error) {
  1315  	err = s.brk.DoWithAcceptable(func() error {
  1316  		conn, err := getRedis(s)
  1317  		if err != nil {
  1318  			return err
  1319  		}
  1320  
  1321  		val, err = conn.SDiff(keys...).Result()
  1322  		return err
  1323  	}, acceptable)
  1324  
  1325  	return
  1326  }
  1327  
  1328  // Sdiffstore is the implementation of redis sdiffstore command.
  1329  func (s *Redis) Sdiffstore(destination string, keys ...string) (val int, err error) {
  1330  	err = s.brk.DoWithAcceptable(func() error {
  1331  		conn, err := getRedis(s)
  1332  		if err != nil {
  1333  			return err
  1334  		}
  1335  
  1336  		v, err := conn.SDiffStore(destination, keys...).Result()
  1337  		if err != nil {
  1338  			return err
  1339  		}
  1340  
  1341  		val = int(v)
  1342  		return nil
  1343  	}, acceptable)
  1344  
  1345  	return
  1346  }
  1347  
  1348  // Sinter is the implementation of redis sinter command.
  1349  func (s *Redis) Sinter(keys ...string) (val []string, err error) {
  1350  	err = s.brk.DoWithAcceptable(func() error {
  1351  		conn, err := getRedis(s)
  1352  		if err != nil {
  1353  			return err
  1354  		}
  1355  
  1356  		val, err = conn.SInter(keys...).Result()
  1357  		return err
  1358  	}, acceptable)
  1359  
  1360  	return
  1361  }
  1362  
  1363  // Sinterstore is the implementation of redis sinterstore command.
  1364  func (s *Redis) Sinterstore(destination string, keys ...string) (val int, err error) {
  1365  	err = s.brk.DoWithAcceptable(func() error {
  1366  		conn, err := getRedis(s)
  1367  		if err != nil {
  1368  			return err
  1369  		}
  1370  
  1371  		v, err := conn.SInterStore(destination, keys...).Result()
  1372  		if err != nil {
  1373  			return err
  1374  		}
  1375  
  1376  		val = int(v)
  1377  		return nil
  1378  	}, acceptable)
  1379  
  1380  	return
  1381  }
  1382  
  1383  // Ttl is the implementation of redis ttl command.
  1384  func (s *Redis) Ttl(key string) (val int, err error) {
  1385  	err = s.brk.DoWithAcceptable(func() error {
  1386  		conn, err := getRedis(s)
  1387  		if err != nil {
  1388  			return err
  1389  		}
  1390  
  1391  		duration, err := conn.TTL(key).Result()
  1392  		if err != nil {
  1393  			return err
  1394  		}
  1395  
  1396  		val = int(duration / time.Second)
  1397  		return nil
  1398  	}, acceptable)
  1399  
  1400  	return
  1401  }
  1402  
  1403  // Zadd is the implementation of redis zadd command.
  1404  func (s *Redis) Zadd(key string, score int64, value string) (val bool, err error) {
  1405  	err = s.brk.DoWithAcceptable(func() error {
  1406  		conn, err := getRedis(s)
  1407  		if err != nil {
  1408  			return err
  1409  		}
  1410  
  1411  		v, err := conn.ZAdd(key, red.Z{
  1412  			Score:  float64(score),
  1413  			Member: value,
  1414  		}).Result()
  1415  		if err != nil {
  1416  			return err
  1417  		}
  1418  
  1419  		val = v == 1
  1420  		return nil
  1421  	}, acceptable)
  1422  
  1423  	return
  1424  }
  1425  
  1426  // Zadds is the implementation of redis zadds command.
  1427  func (s *Redis) Zadds(key string, ps ...Pair) (val int64, err error) {
  1428  	err = s.brk.DoWithAcceptable(func() error {
  1429  		conn, err := getRedis(s)
  1430  		if err != nil {
  1431  			return err
  1432  		}
  1433  
  1434  		var zs []red.Z
  1435  		for _, p := range ps {
  1436  			z := red.Z{Score: float64(p.Score), Member: p.Key}
  1437  			zs = append(zs, z)
  1438  		}
  1439  
  1440  		v, err := conn.ZAdd(key, zs...).Result()
  1441  		if err != nil {
  1442  			return err
  1443  		}
  1444  
  1445  		val = v
  1446  		return nil
  1447  	}, acceptable)
  1448  
  1449  	return
  1450  }
  1451  
  1452  // Zcard is the implementation of redis zcard command.
  1453  func (s *Redis) Zcard(key string) (val int, err error) {
  1454  	err = s.brk.DoWithAcceptable(func() error {
  1455  		conn, err := getRedis(s)
  1456  		if err != nil {
  1457  			return err
  1458  		}
  1459  
  1460  		v, err := conn.ZCard(key).Result()
  1461  		if err != nil {
  1462  			return err
  1463  		}
  1464  
  1465  		val = int(v)
  1466  		return nil
  1467  	}, acceptable)
  1468  
  1469  	return
  1470  }
  1471  
  1472  // Zcount is the implementation of redis zcount command.
  1473  func (s *Redis) Zcount(key string, start, stop int64) (val int, err error) {
  1474  	err = s.brk.DoWithAcceptable(func() error {
  1475  		conn, err := getRedis(s)
  1476  		if err != nil {
  1477  			return err
  1478  		}
  1479  
  1480  		v, err := conn.ZCount(key, strconv.FormatInt(start, 10), strconv.FormatInt(stop, 10)).Result()
  1481  		if err != nil {
  1482  			return err
  1483  		}
  1484  
  1485  		val = int(v)
  1486  		return nil
  1487  	}, acceptable)
  1488  
  1489  	return
  1490  }
  1491  
  1492  // Zincrby is the implementation of redis zincrby command.
  1493  func (s *Redis) Zincrby(key string, increment int64, field string) (val int64, err error) {
  1494  	err = s.brk.DoWithAcceptable(func() error {
  1495  		conn, err := getRedis(s)
  1496  		if err != nil {
  1497  			return err
  1498  		}
  1499  
  1500  		v, err := conn.ZIncrBy(key, float64(increment), field).Result()
  1501  		if err != nil {
  1502  			return err
  1503  		}
  1504  
  1505  		val = int64(v)
  1506  		return nil
  1507  	}, acceptable)
  1508  
  1509  	return
  1510  }
  1511  
  1512  // Zscore is the implementation of redis zscore command.
  1513  func (s *Redis) Zscore(key, value string) (val int64, err error) {
  1514  	err = s.brk.DoWithAcceptable(func() error {
  1515  		conn, err := getRedis(s)
  1516  		if err != nil {
  1517  			return err
  1518  		}
  1519  
  1520  		v, err := conn.ZScore(key, value).Result()
  1521  		if err != nil {
  1522  			return err
  1523  		}
  1524  
  1525  		val = int64(v)
  1526  		return nil
  1527  	}, acceptable)
  1528  
  1529  	return
  1530  }
  1531  
  1532  // Zrank is the implementation of redis zrank command.
  1533  func (s *Redis) Zrank(key, field string) (val int64, err error) {
  1534  	err = s.brk.DoWithAcceptable(func() error {
  1535  		conn, err := getRedis(s)
  1536  		if err != nil {
  1537  			return err
  1538  		}
  1539  
  1540  		val, err = conn.ZRank(key, field).Result()
  1541  		return err
  1542  	}, acceptable)
  1543  
  1544  	return
  1545  }
  1546  
  1547  // Zrem is the implementation of redis zrem command.
  1548  func (s *Redis) Zrem(key string, values ...interface{}) (val int, err error) {
  1549  	err = s.brk.DoWithAcceptable(func() error {
  1550  		conn, err := getRedis(s)
  1551  		if err != nil {
  1552  			return err
  1553  		}
  1554  
  1555  		v, err := conn.ZRem(key, values...).Result()
  1556  		if err != nil {
  1557  			return err
  1558  		}
  1559  
  1560  		val = int(v)
  1561  		return nil
  1562  	}, acceptable)
  1563  
  1564  	return
  1565  }
  1566  
  1567  // Zremrangebyscore is the implementation of redis zremrangebyscore command.
  1568  func (s *Redis) Zremrangebyscore(key string, start, stop int64) (val int, err error) {
  1569  	err = s.brk.DoWithAcceptable(func() error {
  1570  		conn, err := getRedis(s)
  1571  		if err != nil {
  1572  			return err
  1573  		}
  1574  
  1575  		v, err := conn.ZRemRangeByScore(key, strconv.FormatInt(start, 10),
  1576  			strconv.FormatInt(stop, 10)).Result()
  1577  		if err != nil {
  1578  			return err
  1579  		}
  1580  
  1581  		val = int(v)
  1582  		return nil
  1583  	}, acceptable)
  1584  
  1585  	return
  1586  }
  1587  
  1588  // Zremrangebyrank is the implementation of redis zremrangebyrank command.
  1589  func (s *Redis) Zremrangebyrank(key string, start, stop int64) (val int, err error) {
  1590  	err = s.brk.DoWithAcceptable(func() error {
  1591  		conn, err := getRedis(s)
  1592  		if err != nil {
  1593  			return err
  1594  		}
  1595  
  1596  		v, err := conn.ZRemRangeByRank(key, start, stop).Result()
  1597  		if err != nil {
  1598  			return err
  1599  		}
  1600  
  1601  		val = int(v)
  1602  		return nil
  1603  	}, acceptable)
  1604  
  1605  	return
  1606  }
  1607  
  1608  // Zrange is the implementation of redis zrange command.
  1609  func (s *Redis) Zrange(key string, start, stop int64) (val []string, err error) {
  1610  	err = s.brk.DoWithAcceptable(func() error {
  1611  		conn, err := getRedis(s)
  1612  		if err != nil {
  1613  			return err
  1614  		}
  1615  
  1616  		val, err = conn.ZRange(key, start, stop).Result()
  1617  		return err
  1618  	}, acceptable)
  1619  
  1620  	return
  1621  }
  1622  
  1623  // ZrangeWithScores is the implementation of redis zrange command with scores.
  1624  func (s *Redis) ZrangeWithScores(key string, start, stop int64) (val []Pair, err error) {
  1625  	err = s.brk.DoWithAcceptable(func() error {
  1626  		conn, err := getRedis(s)
  1627  		if err != nil {
  1628  			return err
  1629  		}
  1630  
  1631  		v, err := conn.ZRangeWithScores(key, start, stop).Result()
  1632  		if err != nil {
  1633  			return err
  1634  		}
  1635  
  1636  		val = toPairs(v)
  1637  		return nil
  1638  	}, acceptable)
  1639  
  1640  	return
  1641  }
  1642  
  1643  // ZRevRangeWithScores is the implementation of redis zrevrange command with scores.
  1644  func (s *Redis) ZRevRangeWithScores(key string, start, stop int64) (val []Pair, err error) {
  1645  	err = s.brk.DoWithAcceptable(func() error {
  1646  		conn, err := getRedis(s)
  1647  		if err != nil {
  1648  			return err
  1649  		}
  1650  
  1651  		v, err := conn.ZRevRangeWithScores(key, start, stop).Result()
  1652  		if err != nil {
  1653  			return err
  1654  		}
  1655  
  1656  		val = toPairs(v)
  1657  		return nil
  1658  	}, acceptable)
  1659  
  1660  	return
  1661  }
  1662  
  1663  // ZrangebyscoreWithScores is the implementation of redis zrangebyscore command with scores.
  1664  func (s *Redis) ZrangebyscoreWithScores(key string, start, stop int64) (val []Pair, err error) {
  1665  	err = s.brk.DoWithAcceptable(func() error {
  1666  		conn, err := getRedis(s)
  1667  		if err != nil {
  1668  			return err
  1669  		}
  1670  
  1671  		v, err := conn.ZRangeByScoreWithScores(key, red.ZRangeBy{
  1672  			Min: strconv.FormatInt(start, 10),
  1673  			Max: strconv.FormatInt(stop, 10),
  1674  		}).Result()
  1675  		if err != nil {
  1676  			return err
  1677  		}
  1678  
  1679  		val = toPairs(v)
  1680  		return nil
  1681  	}, acceptable)
  1682  
  1683  	return
  1684  }
  1685  
  1686  // ZrangebyscoreWithScoresAndLimit is the implementation of redis zrangebyscore command with scores and limit.
  1687  func (s *Redis) ZrangebyscoreWithScoresAndLimit(key string, start, stop int64, page, size int) (
  1688  	val []Pair, err error) {
  1689  	err = s.brk.DoWithAcceptable(func() error {
  1690  		if size <= 0 {
  1691  			return nil
  1692  		}
  1693  
  1694  		conn, err := getRedis(s)
  1695  		if err != nil {
  1696  			return err
  1697  		}
  1698  
  1699  		v, err := conn.ZRangeByScoreWithScores(key, red.ZRangeBy{
  1700  			Min:    strconv.FormatInt(start, 10),
  1701  			Max:    strconv.FormatInt(stop, 10),
  1702  			Offset: int64(page * size),
  1703  			Count:  int64(size),
  1704  		}).Result()
  1705  		if err != nil {
  1706  			return err
  1707  		}
  1708  
  1709  		val = toPairs(v)
  1710  		return nil
  1711  	}, acceptable)
  1712  
  1713  	return
  1714  }
  1715  
  1716  // Zrevrange is the implementation of redis zrevrange command.
  1717  func (s *Redis) Zrevrange(key string, start, stop int64) (val []string, err error) {
  1718  	err = s.brk.DoWithAcceptable(func() error {
  1719  		conn, err := getRedis(s)
  1720  		if err != nil {
  1721  			return err
  1722  		}
  1723  
  1724  		val, err = conn.ZRevRange(key, start, stop).Result()
  1725  		return err
  1726  	}, acceptable)
  1727  
  1728  	return
  1729  }
  1730  
  1731  // ZrevrangebyscoreWithScores is the implementation of redis zrevrangebyscore command with scores.
  1732  func (s *Redis) ZrevrangebyscoreWithScores(key string, start, stop int64) (val []Pair, err error) {
  1733  	err = s.brk.DoWithAcceptable(func() error {
  1734  		conn, err := getRedis(s)
  1735  		if err != nil {
  1736  			return err
  1737  		}
  1738  
  1739  		v, err := conn.ZRevRangeByScoreWithScores(key, red.ZRangeBy{
  1740  			Min: strconv.FormatInt(start, 10),
  1741  			Max: strconv.FormatInt(stop, 10),
  1742  		}).Result()
  1743  		if err != nil {
  1744  			return err
  1745  		}
  1746  
  1747  		val = toPairs(v)
  1748  		return nil
  1749  	}, acceptable)
  1750  
  1751  	return
  1752  }
  1753  
  1754  // ZrevrangebyscoreWithScoresAndLimit is the implementation of redis zrevrangebyscore command with scores and limit.
  1755  func (s *Redis) ZrevrangebyscoreWithScoresAndLimit(key string, start, stop int64, page, size int) (
  1756  	val []Pair, err error) {
  1757  	err = s.brk.DoWithAcceptable(func() error {
  1758  		if size <= 0 {
  1759  			return nil
  1760  		}
  1761  
  1762  		conn, err := getRedis(s)
  1763  		if err != nil {
  1764  			return err
  1765  		}
  1766  
  1767  		v, err := conn.ZRevRangeByScoreWithScores(key, red.ZRangeBy{
  1768  			Min:    strconv.FormatInt(start, 10),
  1769  			Max:    strconv.FormatInt(stop, 10),
  1770  			Offset: int64(page * size),
  1771  			Count:  int64(size),
  1772  		}).Result()
  1773  		if err != nil {
  1774  			return err
  1775  		}
  1776  
  1777  		val = toPairs(v)
  1778  		return nil
  1779  	}, acceptable)
  1780  
  1781  	return
  1782  }
  1783  
  1784  // Zrevrank is the implementation of redis zrevrank command.
  1785  func (s *Redis) Zrevrank(key, field string) (val int64, err error) {
  1786  	err = s.brk.DoWithAcceptable(func() error {
  1787  		conn, err := getRedis(s)
  1788  		if err != nil {
  1789  			return err
  1790  		}
  1791  
  1792  		val, err = conn.ZRevRank(key, field).Result()
  1793  		return err
  1794  	}, acceptable)
  1795  
  1796  	return
  1797  }
  1798  
  1799  // Zunionstore is the implementation of redis zunionstore command.
  1800  func (s *Redis) Zunionstore(dest string, store ZStore, keys ...string) (val int64, err error) {
  1801  	err = s.brk.DoWithAcceptable(func() error {
  1802  		conn, err := getRedis(s)
  1803  		if err != nil {
  1804  			return err
  1805  		}
  1806  
  1807  		val, err = conn.ZUnionStore(dest, store, keys...).Result()
  1808  		return err
  1809  	}, acceptable)
  1810  
  1811  	return
  1812  }
  1813  
  1814  // Cluster customizes the given Redis as a cluster.
  1815  func Cluster() Option {
  1816  	return func(r *Redis) {
  1817  		r.Type = ClusterType
  1818  	}
  1819  }
  1820  
  1821  // SetSlowThreshold sets the slow threshold.
  1822  func SetSlowThreshold(threshold time.Duration) {
  1823  	slowThreshold.Set(threshold)
  1824  }
  1825  
  1826  // WithPass customizes the given Redis with given password.
  1827  func WithPass(pass string) Option {
  1828  	return func(r *Redis) {
  1829  		r.Pass = pass
  1830  	}
  1831  }
  1832  
  1833  // WithTLS customizes the given Redis with TLS enabled.
  1834  func WithTLS() Option {
  1835  	return func(r *Redis) {
  1836  		r.tls = true
  1837  	}
  1838  }
  1839  
  1840  func acceptable(err error) bool {
  1841  	return err == nil || err == red.Nil
  1842  }
  1843  
  1844  func getRedis(r *Redis) (RedisNode, error) {
  1845  	switch r.Type {
  1846  	case ClusterType:
  1847  		return getCluster(r)
  1848  	case NodeType:
  1849  		return getClient(r)
  1850  	default:
  1851  		return nil, fmt.Errorf("redis type '%s' is not supported", r.Type)
  1852  	}
  1853  }
  1854  
  1855  func toPairs(vals []red.Z) []Pair {
  1856  	pairs := make([]Pair, len(vals))
  1857  	for i, val := range vals {
  1858  		switch member := val.Member.(type) {
  1859  		case string:
  1860  			pairs[i] = Pair{
  1861  				Key:   member,
  1862  				Score: int64(val.Score),
  1863  			}
  1864  		default:
  1865  			pairs[i] = Pair{
  1866  				Key:   mapping.Repr(val.Member),
  1867  				Score: int64(val.Score),
  1868  			}
  1869  		}
  1870  	}
  1871  	return pairs
  1872  }
  1873  
  1874  func toStrings(vals []interface{}) []string {
  1875  	ret := make([]string, len(vals))
  1876  	for i, val := range vals {
  1877  		if val == nil {
  1878  			ret[i] = ""
  1879  		} else {
  1880  			switch val := val.(type) {
  1881  			case string:
  1882  				ret[i] = val
  1883  			default:
  1884  				ret[i] = mapping.Repr(val)
  1885  			}
  1886  		}
  1887  	}
  1888  	return ret
  1889  }