github.com/lingyao2333/mo-zero@v1.4.1/core/stores/redis/redis.go (about)

     1  package redis
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strconv"
     8  	"time"
     9  
    10  	red "github.com/go-redis/redis/v8"
    11  	"github.com/lingyao2333/mo-zero/core/breaker"
    12  	"github.com/lingyao2333/mo-zero/core/mapping"
    13  	"github.com/lingyao2333/mo-zero/core/syncx"
    14  )
    15  
    16  const (
    17  	// ClusterType means redis cluster.
    18  	ClusterType = "cluster"
    19  	// NodeType means redis node.
    20  	NodeType = "node"
    21  	// Nil is an alias of redis.Nil.
    22  	Nil = red.Nil
    23  
    24  	blockingQueryTimeout = 5 * time.Second
    25  	readWriteTimeout     = 2 * time.Second
    26  	defaultSlowThreshold = time.Millisecond * 100
    27  )
    28  
    29  var (
    30  	// ErrNilNode is an error that indicates a nil redis node.
    31  	ErrNilNode    = errors.New("nil redis node")
    32  	slowThreshold = syncx.ForAtomicDuration(defaultSlowThreshold)
    33  )
    34  
    35  type (
    36  	// Option defines the method to customize a Redis.
    37  	Option func(r *Redis)
    38  
    39  	// A Pair is a key/pair set used in redis zset.
    40  	Pair struct {
    41  		Key   string
    42  		Score int64
    43  	}
    44  
    45  	// Redis defines a redis node/cluster. It is thread-safe.
    46  	Redis struct {
    47  		Addr string
    48  		Type string
    49  		Pass string
    50  		tls  bool
    51  		brk  breaker.Breaker
    52  	}
    53  
    54  	// RedisNode interface represents a redis node.
    55  	RedisNode interface {
    56  		red.Cmdable
    57  	}
    58  
    59  	// GeoLocation is used with GeoAdd to add geospatial location.
    60  	GeoLocation = red.GeoLocation
    61  	// GeoRadiusQuery is used with GeoRadius to query geospatial index.
    62  	GeoRadiusQuery = red.GeoRadiusQuery
    63  	// GeoPos is used to represent a geo position.
    64  	GeoPos = red.GeoPos
    65  
    66  	// Pipeliner is an alias of redis.Pipeliner.
    67  	Pipeliner = red.Pipeliner
    68  
    69  	// Z represents sorted set member.
    70  	Z = red.Z
    71  	// ZStore is an alias of redis.ZStore.
    72  	ZStore = red.ZStore
    73  
    74  	// IntCmd is an alias of redis.IntCmd.
    75  	IntCmd = red.IntCmd
    76  	// FloatCmd is an alias of redis.FloatCmd.
    77  	FloatCmd = red.FloatCmd
    78  	// StringCmd is an alias of redis.StringCmd.
    79  	StringCmd = red.StringCmd
    80  )
    81  
    82  // New returns a Redis with given options.
    83  func New(addr string, opts ...Option) *Redis {
    84  	r := &Redis{
    85  		Addr: addr,
    86  		Type: NodeType,
    87  		brk:  breaker.NewBreaker(),
    88  	}
    89  
    90  	for _, opt := range opts {
    91  		opt(r)
    92  	}
    93  
    94  	return r
    95  }
    96  
    97  // BitCount is redis bitcount command implementation.
    98  func (s *Redis) BitCount(key string, start, end int64) (int64, error) {
    99  	return s.BitCountCtx(context.Background(), key, start, end)
   100  }
   101  
   102  // BitCountCtx is redis bitcount command implementation.
   103  func (s *Redis) BitCountCtx(ctx context.Context, key string, start, end int64) (val int64, err error) {
   104  	err = s.brk.DoWithAcceptable(func() error {
   105  		conn, err := getRedis(s)
   106  		if err != nil {
   107  			return err
   108  		}
   109  
   110  		val, err = conn.BitCount(ctx, key, &red.BitCount{
   111  			Start: start,
   112  			End:   end,
   113  		}).Result()
   114  		return err
   115  	}, acceptable)
   116  
   117  	return
   118  }
   119  
   120  // BitOpAnd is redis bit operation (and) command implementation.
   121  func (s *Redis) BitOpAnd(destKey string, keys ...string) (int64, error) {
   122  	return s.BitOpAndCtx(context.Background(), destKey, keys...)
   123  }
   124  
   125  // BitOpAndCtx is redis bit operation (and) command implementation.
   126  func (s *Redis) BitOpAndCtx(ctx context.Context, destKey string, keys ...string) (val int64, err error) {
   127  	err = s.brk.DoWithAcceptable(func() error {
   128  		conn, err := getRedis(s)
   129  		if err != nil {
   130  			return err
   131  		}
   132  
   133  		val, err = conn.BitOpAnd(ctx, destKey, keys...).Result()
   134  		return err
   135  	}, acceptable)
   136  
   137  	return
   138  }
   139  
   140  // BitOpNot is redis bit operation (not) command implementation.
   141  func (s *Redis) BitOpNot(destKey, key string) (int64, error) {
   142  	return s.BitOpNotCtx(context.Background(), destKey, key)
   143  }
   144  
   145  // BitOpNotCtx is redis bit operation (not) command implementation.
   146  func (s *Redis) BitOpNotCtx(ctx context.Context, destKey, key string) (val int64, err error) {
   147  	err = s.brk.DoWithAcceptable(func() error {
   148  		conn, err := getRedis(s)
   149  		if err != nil {
   150  			return err
   151  		}
   152  
   153  		val, err = conn.BitOpNot(ctx, destKey, key).Result()
   154  		return err
   155  	}, acceptable)
   156  
   157  	return
   158  }
   159  
   160  // BitOpOr is redis bit operation (or) command implementation.
   161  func (s *Redis) BitOpOr(destKey string, keys ...string) (int64, error) {
   162  	return s.BitOpOrCtx(context.Background(), destKey, keys...)
   163  }
   164  
   165  // BitOpOrCtx is redis bit operation (or) command implementation.
   166  func (s *Redis) BitOpOrCtx(ctx context.Context, destKey string, keys ...string) (val int64, err error) {
   167  	err = s.brk.DoWithAcceptable(func() error {
   168  		conn, err := getRedis(s)
   169  		if err != nil {
   170  			return err
   171  		}
   172  
   173  		val, err = conn.BitOpOr(ctx, destKey, keys...).Result()
   174  		return err
   175  	}, acceptable)
   176  
   177  	return
   178  }
   179  
   180  // BitOpXor is redis bit operation (xor) command implementation.
   181  func (s *Redis) BitOpXor(destKey string, keys ...string) (int64, error) {
   182  	return s.BitOpXorCtx(context.Background(), destKey, keys...)
   183  }
   184  
   185  // BitOpXorCtx is redis bit operation (xor) command implementation.
   186  func (s *Redis) BitOpXorCtx(ctx context.Context, destKey string, keys ...string) (val int64, err error) {
   187  	err = s.brk.DoWithAcceptable(func() error {
   188  		conn, err := getRedis(s)
   189  		if err != nil {
   190  			return err
   191  		}
   192  
   193  		val, err = conn.BitOpXor(ctx, destKey, keys...).Result()
   194  		return err
   195  	}, acceptable)
   196  
   197  	return
   198  }
   199  
   200  // BitPos is redis bitpos command implementation.
   201  func (s *Redis) BitPos(key string, bit, start, end int64) (int64, error) {
   202  	return s.BitPosCtx(context.Background(), key, bit, start, end)
   203  }
   204  
   205  // BitPosCtx is redis bitpos command implementation.
   206  func (s *Redis) BitPosCtx(ctx context.Context, key string, bit, start, end int64) (val int64, err error) {
   207  	err = s.brk.DoWithAcceptable(func() error {
   208  		conn, err := getRedis(s)
   209  		if err != nil {
   210  			return err
   211  		}
   212  
   213  		val, err = conn.BitPos(ctx, key, bit, start, end).Result()
   214  		return err
   215  	}, acceptable)
   216  
   217  	return
   218  }
   219  
   220  // Blpop uses passed in redis connection to execute blocking queries.
   221  // Doesn't benefit from pooling redis connections of blocking queries
   222  func (s *Redis) Blpop(node RedisNode, key string) (string, error) {
   223  	return s.BlpopCtx(context.Background(), node, key)
   224  }
   225  
   226  // BlpopCtx uses passed in redis connection to execute blocking queries.
   227  // Doesn't benefit from pooling redis connections of blocking queries
   228  func (s *Redis) BlpopCtx(ctx context.Context, node RedisNode, key string) (string, error) {
   229  	return s.BlpopWithTimeoutCtx(ctx, node, blockingQueryTimeout, key)
   230  }
   231  
   232  // BlpopEx uses passed in redis connection to execute blpop command.
   233  // The difference against Blpop is that this method returns a bool to indicate success.
   234  func (s *Redis) BlpopEx(node RedisNode, key string) (string, bool, error) {
   235  	return s.BlpopExCtx(context.Background(), node, key)
   236  }
   237  
   238  // BlpopExCtx uses passed in redis connection to execute blpop command.
   239  // The difference against Blpop is that this method returns a bool to indicate success.
   240  func (s *Redis) BlpopExCtx(ctx context.Context, node RedisNode, key string) (string, bool, error) {
   241  	if node == nil {
   242  		return "", false, ErrNilNode
   243  	}
   244  
   245  	vals, err := node.BLPop(ctx, blockingQueryTimeout, key).Result()
   246  	if err != nil {
   247  		return "", false, err
   248  	}
   249  
   250  	if len(vals) < 2 {
   251  		return "", false, fmt.Errorf("no value on key: %s", key)
   252  	}
   253  
   254  	return vals[1], true, nil
   255  }
   256  
   257  // BlpopWithTimeout uses passed in redis connection to execute blpop command.
   258  // Control blocking query timeout
   259  func (s *Redis) BlpopWithTimeout(node RedisNode, timeout time.Duration, key string) (string, error) {
   260  	return s.BlpopWithTimeoutCtx(context.Background(), node, timeout, key)
   261  }
   262  
   263  // BlpopWithTimeoutCtx uses passed in redis connection to execute blpop command.
   264  // Control blocking query timeout
   265  func (s *Redis) BlpopWithTimeoutCtx(ctx context.Context, node RedisNode, timeout time.Duration,
   266  	key string) (string, error) {
   267  	if node == nil {
   268  		return "", ErrNilNode
   269  	}
   270  
   271  	vals, err := node.BLPop(ctx, timeout, key).Result()
   272  	if err != nil {
   273  		return "", err
   274  	}
   275  
   276  	if len(vals) < 2 {
   277  		return "", fmt.Errorf("no value on key: %s", key)
   278  	}
   279  
   280  	return vals[1], nil
   281  }
   282  
   283  // Decr is the implementation of redis decr command.
   284  func (s *Redis) Decr(key string) (int64, error) {
   285  	return s.DecrCtx(context.Background(), key)
   286  }
   287  
   288  // DecrCtx is the implementation of redis decr command.
   289  func (s *Redis) DecrCtx(ctx context.Context, key string) (val int64, err error) {
   290  	err = s.brk.DoWithAcceptable(func() error {
   291  		conn, err := getRedis(s)
   292  		if err != nil {
   293  			return err
   294  		}
   295  
   296  		val, err = conn.Decr(ctx, key).Result()
   297  		return err
   298  	}, acceptable)
   299  
   300  	return
   301  }
   302  
   303  // Decrby is the implementation of redis decrby command.
   304  func (s *Redis) Decrby(key string, decrement int64) (int64, error) {
   305  	return s.DecrbyCtx(context.Background(), key, decrement)
   306  }
   307  
   308  // DecrbyCtx is the implementation of redis decrby command.
   309  func (s *Redis) DecrbyCtx(ctx context.Context, key string, decrement int64) (val int64, err error) {
   310  	err = s.brk.DoWithAcceptable(func() error {
   311  		conn, err := getRedis(s)
   312  		if err != nil {
   313  			return err
   314  		}
   315  
   316  		val, err = conn.DecrBy(ctx, key, decrement).Result()
   317  		return err
   318  	}, acceptable)
   319  
   320  	return
   321  }
   322  
   323  // Del deletes keys.
   324  func (s *Redis) Del(keys ...string) (int, error) {
   325  	return s.DelCtx(context.Background(), keys...)
   326  }
   327  
   328  // DelCtx deletes keys.
   329  func (s *Redis) DelCtx(ctx context.Context, keys ...string) (val int, err error) {
   330  	err = s.brk.DoWithAcceptable(func() error {
   331  		conn, err := getRedis(s)
   332  		if err != nil {
   333  			return err
   334  		}
   335  
   336  		v, err := conn.Del(ctx, keys...).Result()
   337  		if err != nil {
   338  			return err
   339  		}
   340  
   341  		val = int(v)
   342  		return nil
   343  	}, acceptable)
   344  
   345  	return
   346  }
   347  
   348  // Eval is the implementation of redis eval command.
   349  func (s *Redis) Eval(script string, keys []string, args ...interface{}) (interface{}, error) {
   350  	return s.EvalCtx(context.Background(), script, keys, args...)
   351  }
   352  
   353  // EvalCtx is the implementation of redis eval command.
   354  func (s *Redis) EvalCtx(ctx context.Context, script string, keys []string,
   355  	args ...interface{}) (val interface{}, err error) {
   356  	err = s.brk.DoWithAcceptable(func() error {
   357  		conn, err := getRedis(s)
   358  		if err != nil {
   359  			return err
   360  		}
   361  
   362  		val, err = conn.Eval(ctx, script, keys, args...).Result()
   363  		return err
   364  	}, acceptable)
   365  
   366  	return
   367  }
   368  
   369  // EvalSha is the implementation of redis evalsha command.
   370  func (s *Redis) EvalSha(sha string, keys []string, args ...interface{}) (interface{}, error) {
   371  	return s.EvalShaCtx(context.Background(), sha, keys, args...)
   372  }
   373  
   374  // EvalShaCtx is the implementation of redis evalsha command.
   375  func (s *Redis) EvalShaCtx(ctx context.Context, sha string, keys []string,
   376  	args ...interface{}) (val interface{}, err error) {
   377  	err = s.brk.DoWithAcceptable(func() error {
   378  		conn, err := getRedis(s)
   379  		if err != nil {
   380  			return err
   381  		}
   382  
   383  		val, err = conn.EvalSha(ctx, sha, keys, args...).Result()
   384  		return err
   385  	}, acceptable)
   386  
   387  	return
   388  }
   389  
   390  // Exists is the implementation of redis exists command.
   391  func (s *Redis) Exists(key string) (bool, error) {
   392  	return s.ExistsCtx(context.Background(), key)
   393  }
   394  
   395  // ExistsCtx is the implementation of redis exists command.
   396  func (s *Redis) ExistsCtx(ctx context.Context, key string) (val bool, err error) {
   397  	err = s.brk.DoWithAcceptable(func() error {
   398  		conn, err := getRedis(s)
   399  		if err != nil {
   400  			return err
   401  		}
   402  
   403  		v, err := conn.Exists(ctx, key).Result()
   404  		if err != nil {
   405  			return err
   406  		}
   407  
   408  		val = v == 1
   409  		return nil
   410  	}, acceptable)
   411  
   412  	return
   413  }
   414  
   415  // Expire is the implementation of redis expire command.
   416  func (s *Redis) Expire(key string, seconds int) error {
   417  	return s.ExpireCtx(context.Background(), key, seconds)
   418  }
   419  
   420  // ExpireCtx is the implementation of redis expire command.
   421  func (s *Redis) ExpireCtx(ctx context.Context, key string, seconds int) error {
   422  	return s.brk.DoWithAcceptable(func() error {
   423  		conn, err := getRedis(s)
   424  		if err != nil {
   425  			return err
   426  		}
   427  
   428  		return conn.Expire(ctx, key, time.Duration(seconds)*time.Second).Err()
   429  	}, acceptable)
   430  }
   431  
   432  // Expireat is the implementation of redis expireat command.
   433  func (s *Redis) Expireat(key string, expireTime int64) error {
   434  	return s.ExpireatCtx(context.Background(), key, expireTime)
   435  }
   436  
   437  // ExpireatCtx is the implementation of redis expireat command.
   438  func (s *Redis) ExpireatCtx(ctx context.Context, key string, expireTime int64) error {
   439  	return s.brk.DoWithAcceptable(func() error {
   440  		conn, err := getRedis(s)
   441  		if err != nil {
   442  			return err
   443  		}
   444  
   445  		return conn.ExpireAt(ctx, key, time.Unix(expireTime, 0)).Err()
   446  	}, acceptable)
   447  }
   448  
   449  // GeoAdd is the implementation of redis geoadd command.
   450  func (s *Redis) GeoAdd(key string, geoLocation ...*GeoLocation) (int64, error) {
   451  	return s.GeoAddCtx(context.Background(), key, geoLocation...)
   452  }
   453  
   454  // GeoAddCtx is the implementation of redis geoadd command.
   455  func (s *Redis) GeoAddCtx(ctx context.Context, key string, geoLocation ...*GeoLocation) (
   456  	val int64, err error) {
   457  	err = s.brk.DoWithAcceptable(func() error {
   458  		conn, err := getRedis(s)
   459  		if err != nil {
   460  			return err
   461  		}
   462  
   463  		v, err := conn.GeoAdd(ctx, key, geoLocation...).Result()
   464  		if err != nil {
   465  			return err
   466  		}
   467  
   468  		val = v
   469  		return nil
   470  	}, acceptable)
   471  
   472  	return
   473  }
   474  
   475  // GeoDist is the implementation of redis geodist command.
   476  func (s *Redis) GeoDist(key, member1, member2, unit string) (float64, error) {
   477  	return s.GeoDistCtx(context.Background(), key, member1, member2, unit)
   478  }
   479  
   480  // GeoDistCtx is the implementation of redis geodist command.
   481  func (s *Redis) GeoDistCtx(ctx context.Context, key, member1, member2, unit string) (
   482  	val float64, err error) {
   483  	err = s.brk.DoWithAcceptable(func() error {
   484  		conn, err := getRedis(s)
   485  		if err != nil {
   486  			return err
   487  		}
   488  
   489  		v, err := conn.GeoDist(ctx, key, member1, member2, unit).Result()
   490  		if err != nil {
   491  			return err
   492  		}
   493  
   494  		val = v
   495  		return nil
   496  	}, acceptable)
   497  
   498  	return
   499  }
   500  
   501  // GeoHash is the implementation of redis geohash command.
   502  func (s *Redis) GeoHash(key string, members ...string) ([]string, error) {
   503  	return s.GeoHashCtx(context.Background(), key, members...)
   504  }
   505  
   506  // GeoHashCtx is the implementation of redis geohash command.
   507  func (s *Redis) GeoHashCtx(ctx context.Context, key string, members ...string) (
   508  	val []string, err error) {
   509  	err = s.brk.DoWithAcceptable(func() error {
   510  		conn, err := getRedis(s)
   511  		if err != nil {
   512  			return err
   513  		}
   514  
   515  		v, err := conn.GeoHash(ctx, key, members...).Result()
   516  		if err != nil {
   517  			return err
   518  		}
   519  
   520  		val = v
   521  		return nil
   522  	}, acceptable)
   523  
   524  	return
   525  }
   526  
   527  // GeoRadius is the implementation of redis georadius command.
   528  func (s *Redis) GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) (
   529  	[]GeoLocation, error) {
   530  	return s.GeoRadiusCtx(context.Background(), key, longitude, latitude, query)
   531  }
   532  
   533  // GeoRadiusCtx is the implementation of redis georadius command.
   534  func (s *Redis) GeoRadiusCtx(ctx context.Context, key string, longitude, latitude float64,
   535  	query *GeoRadiusQuery) (val []GeoLocation, err error) {
   536  	err = s.brk.DoWithAcceptable(func() error {
   537  		conn, err := getRedis(s)
   538  		if err != nil {
   539  			return err
   540  		}
   541  
   542  		v, err := conn.GeoRadius(ctx, key, longitude, latitude, query).Result()
   543  		if err != nil {
   544  			return err
   545  		}
   546  
   547  		val = v
   548  		return nil
   549  	}, acceptable)
   550  
   551  	return
   552  }
   553  
   554  // GeoRadiusByMember is the implementation of redis georadiusbymember command.
   555  func (s *Redis) GeoRadiusByMember(key, member string, query *GeoRadiusQuery) ([]GeoLocation, error) {
   556  	return s.GeoRadiusByMemberCtx(context.Background(), key, member, query)
   557  }
   558  
   559  // GeoRadiusByMemberCtx is the implementation of redis georadiusbymember command.
   560  func (s *Redis) GeoRadiusByMemberCtx(ctx context.Context, key, member string,
   561  	query *GeoRadiusQuery) (val []GeoLocation, err error) {
   562  	err = s.brk.DoWithAcceptable(func() error {
   563  		conn, err := getRedis(s)
   564  		if err != nil {
   565  			return err
   566  		}
   567  
   568  		v, err := conn.GeoRadiusByMember(ctx, key, member, query).Result()
   569  		if err != nil {
   570  			return err
   571  		}
   572  
   573  		val = v
   574  		return nil
   575  	}, acceptable)
   576  
   577  	return
   578  }
   579  
   580  // GeoPos is the implementation of redis geopos command.
   581  func (s *Redis) GeoPos(key string, members ...string) ([]*GeoPos, error) {
   582  	return s.GeoPosCtx(context.Background(), key, members...)
   583  }
   584  
   585  // GeoPosCtx is the implementation of redis geopos command.
   586  func (s *Redis) GeoPosCtx(ctx context.Context, key string, members ...string) (
   587  	val []*GeoPos, err error) {
   588  	err = s.brk.DoWithAcceptable(func() error {
   589  		conn, err := getRedis(s)
   590  		if err != nil {
   591  			return err
   592  		}
   593  
   594  		v, err := conn.GeoPos(ctx, key, members...).Result()
   595  		if err != nil {
   596  			return err
   597  		}
   598  
   599  		val = v
   600  		return nil
   601  	}, acceptable)
   602  
   603  	return
   604  }
   605  
   606  // Get is the implementation of redis get command.
   607  func (s *Redis) Get(key string) (string, error) {
   608  	return s.GetCtx(context.Background(), key)
   609  }
   610  
   611  // GetCtx is the implementation of redis get command.
   612  func (s *Redis) GetCtx(ctx context.Context, key string) (val string, err error) {
   613  	err = s.brk.DoWithAcceptable(func() error {
   614  		conn, err := getRedis(s)
   615  		if err != nil {
   616  			return err
   617  		}
   618  
   619  		if val, err = conn.Get(ctx, key).Result(); err == red.Nil {
   620  			return nil
   621  		} else if err != nil {
   622  			return err
   623  		} else {
   624  			return nil
   625  		}
   626  	}, acceptable)
   627  
   628  	return
   629  }
   630  
   631  // GetBit is the implementation of redis getbit command.
   632  func (s *Redis) GetBit(key string, offset int64) (int, error) {
   633  	return s.GetBitCtx(context.Background(), key, offset)
   634  }
   635  
   636  // GetBitCtx is the implementation of redis getbit command.
   637  func (s *Redis) GetBitCtx(ctx context.Context, key string, offset int64) (val int, err error) {
   638  	err = s.brk.DoWithAcceptable(func() error {
   639  		conn, err := getRedis(s)
   640  		if err != nil {
   641  			return err
   642  		}
   643  
   644  		v, err := conn.GetBit(ctx, key, offset).Result()
   645  		if err != nil {
   646  			return err
   647  		}
   648  
   649  		val = int(v)
   650  		return nil
   651  	}, acceptable)
   652  
   653  	return
   654  }
   655  
   656  // GetSet is the implementation of redis getset command.
   657  func (s *Redis) GetSet(key, value string) (string, error) {
   658  	return s.GetSetCtx(context.Background(), key, value)
   659  }
   660  
   661  // GetSetCtx is the implementation of redis getset command.
   662  func (s *Redis) GetSetCtx(ctx context.Context, key, value string) (val string, err error) {
   663  	err = s.brk.DoWithAcceptable(func() error {
   664  		conn, err := getRedis(s)
   665  		if err != nil {
   666  			return err
   667  		}
   668  
   669  		if val, err = conn.GetSet(ctx, key, value).Result(); err == red.Nil {
   670  			return nil
   671  		}
   672  
   673  		return err
   674  	}, acceptable)
   675  
   676  	return
   677  }
   678  
   679  // Hdel is the implementation of redis hdel command.
   680  func (s *Redis) Hdel(key string, fields ...string) (bool, error) {
   681  	return s.HdelCtx(context.Background(), key, fields...)
   682  }
   683  
   684  // HdelCtx is the implementation of redis hdel command.
   685  func (s *Redis) HdelCtx(ctx context.Context, key string, fields ...string) (val bool, err error) {
   686  	err = s.brk.DoWithAcceptable(func() error {
   687  		conn, err := getRedis(s)
   688  		if err != nil {
   689  			return err
   690  		}
   691  
   692  		v, err := conn.HDel(ctx, key, fields...).Result()
   693  		if err != nil {
   694  			return err
   695  		}
   696  
   697  		val = v >= 1
   698  		return nil
   699  	}, acceptable)
   700  
   701  	return
   702  }
   703  
   704  // Hexists is the implementation of redis hexists command.
   705  func (s *Redis) Hexists(key, field string) (bool, error) {
   706  	return s.HexistsCtx(context.Background(), key, field)
   707  }
   708  
   709  // HexistsCtx is the implementation of redis hexists command.
   710  func (s *Redis) HexistsCtx(ctx context.Context, key, field string) (val bool, err error) {
   711  	err = s.brk.DoWithAcceptable(func() error {
   712  		conn, err := getRedis(s)
   713  		if err != nil {
   714  			return err
   715  		}
   716  
   717  		val, err = conn.HExists(ctx, key, field).Result()
   718  		return err
   719  	}, acceptable)
   720  
   721  	return
   722  }
   723  
   724  // Hget is the implementation of redis hget command.
   725  func (s *Redis) Hget(key, field string) (string, error) {
   726  	return s.HgetCtx(context.Background(), key, field)
   727  }
   728  
   729  // HgetCtx is the implementation of redis hget command.
   730  func (s *Redis) HgetCtx(ctx context.Context, key, field string) (val string, err error) {
   731  	err = s.brk.DoWithAcceptable(func() error {
   732  		conn, err := getRedis(s)
   733  		if err != nil {
   734  			return err
   735  		}
   736  
   737  		val, err = conn.HGet(ctx, key, field).Result()
   738  		return err
   739  	}, acceptable)
   740  
   741  	return
   742  }
   743  
   744  // Hgetall is the implementation of redis hgetall command.
   745  func (s *Redis) Hgetall(key string) (map[string]string, error) {
   746  	return s.HgetallCtx(context.Background(), key)
   747  }
   748  
   749  // HgetallCtx is the implementation of redis hgetall command.
   750  func (s *Redis) HgetallCtx(ctx context.Context, key string) (val map[string]string, err error) {
   751  	err = s.brk.DoWithAcceptable(func() error {
   752  		conn, err := getRedis(s)
   753  		if err != nil {
   754  			return err
   755  		}
   756  
   757  		val, err = conn.HGetAll(ctx, key).Result()
   758  		return err
   759  	}, acceptable)
   760  
   761  	return
   762  }
   763  
   764  // Hincrby is the implementation of redis hincrby command.
   765  func (s *Redis) Hincrby(key, field string, increment int) (int, error) {
   766  	return s.HincrbyCtx(context.Background(), key, field, increment)
   767  }
   768  
   769  // HincrbyCtx is the implementation of redis hincrby command.
   770  func (s *Redis) HincrbyCtx(ctx context.Context, key, field string, increment int) (val int, err error) {
   771  	err = s.brk.DoWithAcceptable(func() error {
   772  		conn, err := getRedis(s)
   773  		if err != nil {
   774  			return err
   775  		}
   776  
   777  		v, err := conn.HIncrBy(ctx, key, field, int64(increment)).Result()
   778  		if err != nil {
   779  			return err
   780  		}
   781  
   782  		val = int(v)
   783  		return nil
   784  	}, acceptable)
   785  
   786  	return
   787  }
   788  
   789  // Hkeys is the implementation of redis hkeys command.
   790  func (s *Redis) Hkeys(key string) ([]string, error) {
   791  	return s.HkeysCtx(context.Background(), key)
   792  }
   793  
   794  // HkeysCtx is the implementation of redis hkeys command.
   795  func (s *Redis) HkeysCtx(ctx context.Context, key string) (val []string, err error) {
   796  	err = s.brk.DoWithAcceptable(func() error {
   797  		conn, err := getRedis(s)
   798  		if err != nil {
   799  			return err
   800  		}
   801  
   802  		val, err = conn.HKeys(ctx, key).Result()
   803  		return err
   804  	}, acceptable)
   805  
   806  	return
   807  }
   808  
   809  // Hlen is the implementation of redis hlen command.
   810  func (s *Redis) Hlen(key string) (int, error) {
   811  	return s.HlenCtx(context.Background(), key)
   812  }
   813  
   814  // HlenCtx is the implementation of redis hlen command.
   815  func (s *Redis) HlenCtx(ctx context.Context, key string) (val int, err error) {
   816  	err = s.brk.DoWithAcceptable(func() error {
   817  		conn, err := getRedis(s)
   818  		if err != nil {
   819  			return err
   820  		}
   821  
   822  		v, err := conn.HLen(ctx, key).Result()
   823  		if err != nil {
   824  			return err
   825  		}
   826  
   827  		val = int(v)
   828  		return nil
   829  	}, acceptable)
   830  
   831  	return
   832  }
   833  
   834  // Hmget is the implementation of redis hmget command.
   835  func (s *Redis) Hmget(key string, fields ...string) ([]string, error) {
   836  	return s.HmgetCtx(context.Background(), key, fields...)
   837  }
   838  
   839  // HmgetCtx is the implementation of redis hmget command.
   840  func (s *Redis) HmgetCtx(ctx context.Context, key string, fields ...string) (val []string, err error) {
   841  	err = s.brk.DoWithAcceptable(func() error {
   842  		conn, err := getRedis(s)
   843  		if err != nil {
   844  			return err
   845  		}
   846  
   847  		v, err := conn.HMGet(ctx, key, fields...).Result()
   848  		if err != nil {
   849  			return err
   850  		}
   851  
   852  		val = toStrings(v)
   853  		return nil
   854  	}, acceptable)
   855  
   856  	return
   857  }
   858  
   859  // Hset is the implementation of redis hset command.
   860  func (s *Redis) Hset(key, field, value string) error {
   861  	return s.HsetCtx(context.Background(), key, field, value)
   862  }
   863  
   864  // HsetCtx is the implementation of redis hset command.
   865  func (s *Redis) HsetCtx(ctx context.Context, key, field, value string) error {
   866  	return s.brk.DoWithAcceptable(func() error {
   867  		conn, err := getRedis(s)
   868  		if err != nil {
   869  			return err
   870  		}
   871  
   872  		return conn.HSet(ctx, key, field, value).Err()
   873  	}, acceptable)
   874  }
   875  
   876  // Hsetnx is the implementation of redis hsetnx command.
   877  func (s *Redis) Hsetnx(key, field, value string) (bool, error) {
   878  	return s.HsetnxCtx(context.Background(), key, field, value)
   879  }
   880  
   881  // HsetnxCtx is the implementation of redis hsetnx command.
   882  func (s *Redis) HsetnxCtx(ctx context.Context, key, field, value string) (val bool, err error) {
   883  	err = s.brk.DoWithAcceptable(func() error {
   884  		conn, err := getRedis(s)
   885  		if err != nil {
   886  			return err
   887  		}
   888  
   889  		val, err = conn.HSetNX(ctx, key, field, value).Result()
   890  		return err
   891  	}, acceptable)
   892  
   893  	return
   894  }
   895  
   896  // Hmset is the implementation of redis hmset command.
   897  func (s *Redis) Hmset(key string, fieldsAndValues map[string]string) error {
   898  	return s.HmsetCtx(context.Background(), key, fieldsAndValues)
   899  }
   900  
   901  // HmsetCtx is the implementation of redis hmset command.
   902  func (s *Redis) HmsetCtx(ctx context.Context, key string, fieldsAndValues map[string]string) error {
   903  	return s.brk.DoWithAcceptable(func() error {
   904  		conn, err := getRedis(s)
   905  		if err != nil {
   906  			return err
   907  		}
   908  
   909  		vals := make(map[string]interface{}, len(fieldsAndValues))
   910  		for k, v := range fieldsAndValues {
   911  			vals[k] = v
   912  		}
   913  
   914  		return conn.HMSet(ctx, key, vals).Err()
   915  	}, acceptable)
   916  }
   917  
   918  // Hscan is the implementation of redis hscan command.
   919  func (s *Redis) Hscan(key string, cursor uint64, match string, count int64) (
   920  	keys []string, cur uint64, err error) {
   921  	return s.HscanCtx(context.Background(), key, cursor, match, count)
   922  }
   923  
   924  // HscanCtx is the implementation of redis hscan command.
   925  func (s *Redis) HscanCtx(ctx context.Context, key string, cursor uint64, match string, count int64) (
   926  	keys []string, cur uint64, err error) {
   927  	err = s.brk.DoWithAcceptable(func() error {
   928  		conn, err := getRedis(s)
   929  		if err != nil {
   930  			return err
   931  		}
   932  
   933  		keys, cur, err = conn.HScan(ctx, key, cursor, match, count).Result()
   934  		return err
   935  	}, acceptable)
   936  
   937  	return
   938  }
   939  
   940  // Hvals is the implementation of redis hvals command.
   941  func (s *Redis) Hvals(key string) ([]string, error) {
   942  	return s.HvalsCtx(context.Background(), key)
   943  }
   944  
   945  // HvalsCtx is the implementation of redis hvals command.
   946  func (s *Redis) HvalsCtx(ctx context.Context, key string) (val []string, err error) {
   947  	err = s.brk.DoWithAcceptable(func() error {
   948  		conn, err := getRedis(s)
   949  		if err != nil {
   950  			return err
   951  		}
   952  
   953  		val, err = conn.HVals(ctx, key).Result()
   954  		return err
   955  	}, acceptable)
   956  
   957  	return
   958  }
   959  
   960  // Incr is the implementation of redis incr command.
   961  func (s *Redis) Incr(key string) (int64, error) {
   962  	return s.IncrCtx(context.Background(), key)
   963  }
   964  
   965  // IncrCtx is the implementation of redis incr command.
   966  func (s *Redis) IncrCtx(ctx context.Context, key string) (val int64, err error) {
   967  	err = s.brk.DoWithAcceptable(func() error {
   968  		conn, err := getRedis(s)
   969  		if err != nil {
   970  			return err
   971  		}
   972  
   973  		val, err = conn.Incr(ctx, key).Result()
   974  		return err
   975  	}, acceptable)
   976  
   977  	return
   978  }
   979  
   980  // Incrby is the implementation of redis incrby command.
   981  func (s *Redis) Incrby(key string, increment int64) (int64, error) {
   982  	return s.IncrbyCtx(context.Background(), key, increment)
   983  }
   984  
   985  // IncrbyCtx is the implementation of redis incrby command.
   986  func (s *Redis) IncrbyCtx(ctx context.Context, key string, increment int64) (val int64, err error) {
   987  	err = s.brk.DoWithAcceptable(func() error {
   988  		conn, err := getRedis(s)
   989  		if err != nil {
   990  			return err
   991  		}
   992  
   993  		val, err = conn.IncrBy(ctx, key, increment).Result()
   994  		return err
   995  	}, acceptable)
   996  
   997  	return
   998  }
   999  
  1000  // Keys is the implementation of redis keys command.
  1001  func (s *Redis) Keys(pattern string) ([]string, error) {
  1002  	return s.KeysCtx(context.Background(), pattern)
  1003  }
  1004  
  1005  // KeysCtx is the implementation of redis keys command.
  1006  func (s *Redis) KeysCtx(ctx context.Context, pattern string) (val []string, err error) {
  1007  	err = s.brk.DoWithAcceptable(func() error {
  1008  		conn, err := getRedis(s)
  1009  		if err != nil {
  1010  			return err
  1011  		}
  1012  
  1013  		val, err = conn.Keys(ctx, pattern).Result()
  1014  		return err
  1015  	}, acceptable)
  1016  
  1017  	return
  1018  }
  1019  
  1020  // Llen is the implementation of redis llen command.
  1021  func (s *Redis) Llen(key string) (int, error) {
  1022  	return s.LlenCtx(context.Background(), key)
  1023  }
  1024  
  1025  // LlenCtx is the implementation of redis llen command.
  1026  func (s *Redis) LlenCtx(ctx context.Context, key string) (val int, err error) {
  1027  	err = s.brk.DoWithAcceptable(func() error {
  1028  		conn, err := getRedis(s)
  1029  		if err != nil {
  1030  			return err
  1031  		}
  1032  
  1033  		v, err := conn.LLen(ctx, key).Result()
  1034  		if err != nil {
  1035  			return err
  1036  		}
  1037  
  1038  		val = int(v)
  1039  		return nil
  1040  	}, acceptable)
  1041  
  1042  	return
  1043  }
  1044  
  1045  // Lindex is the implementation of redis lindex command.
  1046  func (s *Redis) Lindex(key string, index int64) (string, error) {
  1047  	return s.LindexCtx(context.Background(), key, index)
  1048  }
  1049  
  1050  // LindexCtx is the implementation of redis lindex command.
  1051  func (s *Redis) LindexCtx(ctx context.Context, key string, index int64) (val string, err error) {
  1052  	err = s.brk.DoWithAcceptable(func() error {
  1053  		conn, err := getRedis(s)
  1054  		if err != nil {
  1055  			return err
  1056  		}
  1057  
  1058  		val, err = conn.LIndex(ctx, key, index).Result()
  1059  		return err
  1060  	}, acceptable)
  1061  
  1062  	return
  1063  }
  1064  
  1065  // Lpop is the implementation of redis lpop command.
  1066  func (s *Redis) Lpop(key string) (string, error) {
  1067  	return s.LpopCtx(context.Background(), key)
  1068  }
  1069  
  1070  // LpopCtx is the implementation of redis lpop command.
  1071  func (s *Redis) LpopCtx(ctx context.Context, key string) (val string, err error) {
  1072  	err = s.brk.DoWithAcceptable(func() error {
  1073  		conn, err := getRedis(s)
  1074  		if err != nil {
  1075  			return err
  1076  		}
  1077  
  1078  		val, err = conn.LPop(ctx, key).Result()
  1079  		return err
  1080  	}, acceptable)
  1081  
  1082  	return
  1083  }
  1084  
  1085  // Lpush is the implementation of redis lpush command.
  1086  func (s *Redis) Lpush(key string, values ...interface{}) (int, error) {
  1087  	return s.LpushCtx(context.Background(), key, values...)
  1088  }
  1089  
  1090  // LpushCtx is the implementation of redis lpush command.
  1091  func (s *Redis) LpushCtx(ctx context.Context, key string, values ...interface{}) (val int, err error) {
  1092  	err = s.brk.DoWithAcceptable(func() error {
  1093  		conn, err := getRedis(s)
  1094  		if err != nil {
  1095  			return err
  1096  		}
  1097  
  1098  		v, err := conn.LPush(ctx, key, values...).Result()
  1099  		if err != nil {
  1100  			return err
  1101  		}
  1102  
  1103  		val = int(v)
  1104  		return nil
  1105  	}, acceptable)
  1106  
  1107  	return
  1108  }
  1109  
  1110  // Lrange is the implementation of redis lrange command.
  1111  func (s *Redis) Lrange(key string, start, stop int) ([]string, error) {
  1112  	return s.LrangeCtx(context.Background(), key, start, stop)
  1113  }
  1114  
  1115  // LrangeCtx is the implementation of redis lrange command.
  1116  func (s *Redis) LrangeCtx(ctx context.Context, key string, start, stop int) (val []string, err error) {
  1117  	err = s.brk.DoWithAcceptable(func() error {
  1118  		conn, err := getRedis(s)
  1119  		if err != nil {
  1120  			return err
  1121  		}
  1122  
  1123  		val, err = conn.LRange(ctx, key, int64(start), int64(stop)).Result()
  1124  		return err
  1125  	}, acceptable)
  1126  
  1127  	return
  1128  }
  1129  
  1130  // Lrem is the implementation of redis lrem command.
  1131  func (s *Redis) Lrem(key string, count int, value string) (int, error) {
  1132  	return s.LremCtx(context.Background(), key, count, value)
  1133  }
  1134  
  1135  // LremCtx is the implementation of redis lrem command.
  1136  func (s *Redis) LremCtx(ctx context.Context, key string, count int, value string) (val int, err error) {
  1137  	err = s.brk.DoWithAcceptable(func() error {
  1138  		conn, err := getRedis(s)
  1139  		if err != nil {
  1140  			return err
  1141  		}
  1142  
  1143  		v, err := conn.LRem(ctx, key, int64(count), value).Result()
  1144  		if err != nil {
  1145  			return err
  1146  		}
  1147  
  1148  		val = int(v)
  1149  		return nil
  1150  	}, acceptable)
  1151  
  1152  	return
  1153  }
  1154  
  1155  // Ltrim is the implementation of redis ltrim command.
  1156  func (s *Redis) Ltrim(key string, start, stop int64) error {
  1157  	return s.LtrimCtx(context.Background(), key, start, stop)
  1158  }
  1159  
  1160  // LtrimCtx is the implementation of redis ltrim command.
  1161  func (s *Redis) LtrimCtx(ctx context.Context, key string, start, stop int64) error {
  1162  	return s.brk.DoWithAcceptable(func() error {
  1163  		conn, err := getRedis(s)
  1164  		if err != nil {
  1165  			return err
  1166  		}
  1167  
  1168  		return conn.LTrim(ctx, key, start, stop).Err()
  1169  	}, acceptable)
  1170  }
  1171  
  1172  // Mget is the implementation of redis mget command.
  1173  func (s *Redis) Mget(keys ...string) ([]string, error) {
  1174  	return s.MgetCtx(context.Background(), keys...)
  1175  }
  1176  
  1177  // MgetCtx is the implementation of redis mget command.
  1178  func (s *Redis) MgetCtx(ctx context.Context, keys ...string) (val []string, err error) {
  1179  	err = s.brk.DoWithAcceptable(func() error {
  1180  		conn, err := getRedis(s)
  1181  		if err != nil {
  1182  			return err
  1183  		}
  1184  
  1185  		v, err := conn.MGet(ctx, keys...).Result()
  1186  		if err != nil {
  1187  			return err
  1188  		}
  1189  
  1190  		val = toStrings(v)
  1191  		return nil
  1192  	}, acceptable)
  1193  
  1194  	return
  1195  }
  1196  
  1197  // Persist is the implementation of redis persist command.
  1198  func (s *Redis) Persist(key string) (bool, error) {
  1199  	return s.PersistCtx(context.Background(), key)
  1200  }
  1201  
  1202  // PersistCtx is the implementation of redis persist command.
  1203  func (s *Redis) PersistCtx(ctx context.Context, key string) (val bool, err error) {
  1204  	err = s.brk.DoWithAcceptable(func() error {
  1205  		conn, err := getRedis(s)
  1206  		if err != nil {
  1207  			return err
  1208  		}
  1209  
  1210  		val, err = conn.Persist(ctx, key).Result()
  1211  		return err
  1212  	}, acceptable)
  1213  
  1214  	return
  1215  }
  1216  
  1217  // Pfadd is the implementation of redis pfadd command.
  1218  func (s *Redis) Pfadd(key string, values ...interface{}) (bool, error) {
  1219  	return s.PfaddCtx(context.Background(), key, values...)
  1220  }
  1221  
  1222  // PfaddCtx is the implementation of redis pfadd command.
  1223  func (s *Redis) PfaddCtx(ctx context.Context, key string, values ...interface{}) (val bool, err error) {
  1224  	err = s.brk.DoWithAcceptable(func() error {
  1225  		conn, err := getRedis(s)
  1226  		if err != nil {
  1227  			return err
  1228  		}
  1229  
  1230  		v, err := conn.PFAdd(ctx, key, values...).Result()
  1231  		if err != nil {
  1232  			return err
  1233  		}
  1234  
  1235  		val = v >= 1
  1236  		return nil
  1237  	}, acceptable)
  1238  
  1239  	return
  1240  }
  1241  
  1242  // Pfcount is the implementation of redis pfcount command.
  1243  func (s *Redis) Pfcount(key string) (int64, error) {
  1244  	return s.PfcountCtx(context.Background(), key)
  1245  }
  1246  
  1247  // PfcountCtx is the implementation of redis pfcount command.
  1248  func (s *Redis) PfcountCtx(ctx context.Context, key string) (val int64, err error) {
  1249  	err = s.brk.DoWithAcceptable(func() error {
  1250  		conn, err := getRedis(s)
  1251  		if err != nil {
  1252  			return err
  1253  		}
  1254  
  1255  		val, err = conn.PFCount(ctx, key).Result()
  1256  		return err
  1257  	}, acceptable)
  1258  
  1259  	return
  1260  }
  1261  
  1262  // Pfmerge is the implementation of redis pfmerge command.
  1263  func (s *Redis) Pfmerge(dest string, keys ...string) error {
  1264  	return s.PfmergeCtx(context.Background(), dest, keys...)
  1265  }
  1266  
  1267  // PfmergeCtx is the implementation of redis pfmerge command.
  1268  func (s *Redis) PfmergeCtx(ctx context.Context, dest string, keys ...string) error {
  1269  	return s.brk.DoWithAcceptable(func() error {
  1270  		conn, err := getRedis(s)
  1271  		if err != nil {
  1272  			return err
  1273  		}
  1274  
  1275  		_, err = conn.PFMerge(ctx, dest, keys...).Result()
  1276  		return err
  1277  	}, acceptable)
  1278  }
  1279  
  1280  // Ping is the implementation of redis ping command.
  1281  func (s *Redis) Ping() bool {
  1282  	return s.PingCtx(context.Background())
  1283  }
  1284  
  1285  // PingCtx is the implementation of redis ping command.
  1286  func (s *Redis) PingCtx(ctx context.Context) (val bool) {
  1287  	// ignore error, error means false
  1288  	_ = s.brk.DoWithAcceptable(func() error {
  1289  		conn, err := getRedis(s)
  1290  		if err != nil {
  1291  			val = false
  1292  			return nil
  1293  		}
  1294  
  1295  		v, err := conn.Ping(ctx).Result()
  1296  		if err != nil {
  1297  			val = false
  1298  			return nil
  1299  		}
  1300  
  1301  		val = v == "PONG"
  1302  		return nil
  1303  	}, acceptable)
  1304  
  1305  	return
  1306  }
  1307  
  1308  // Pipelined lets fn execute pipelined commands.
  1309  func (s *Redis) Pipelined(fn func(Pipeliner) error) error {
  1310  	return s.PipelinedCtx(context.Background(), fn)
  1311  }
  1312  
  1313  // PipelinedCtx lets fn execute pipelined commands.
  1314  // Results need to be retrieved by calling Pipeline.Exec()
  1315  func (s *Redis) PipelinedCtx(ctx context.Context, fn func(Pipeliner) error) error {
  1316  	return s.brk.DoWithAcceptable(func() error {
  1317  		conn, err := getRedis(s)
  1318  		if err != nil {
  1319  			return err
  1320  		}
  1321  
  1322  		_, err = conn.Pipelined(ctx, fn)
  1323  		return err
  1324  	}, acceptable)
  1325  }
  1326  
  1327  // Rpop is the implementation of redis rpop command.
  1328  func (s *Redis) Rpop(key string) (string, error) {
  1329  	return s.RpopCtx(context.Background(), key)
  1330  }
  1331  
  1332  // RpopCtx is the implementation of redis rpop command.
  1333  func (s *Redis) RpopCtx(ctx context.Context, key string) (val string, err error) {
  1334  	err = s.brk.DoWithAcceptable(func() error {
  1335  		conn, err := getRedis(s)
  1336  		if err != nil {
  1337  			return err
  1338  		}
  1339  
  1340  		val, err = conn.RPop(ctx, key).Result()
  1341  		return err
  1342  	}, acceptable)
  1343  
  1344  	return
  1345  }
  1346  
  1347  // Rpush is the implementation of redis rpush command.
  1348  func (s *Redis) Rpush(key string, values ...interface{}) (int, error) {
  1349  	return s.RpushCtx(context.Background(), key, values...)
  1350  }
  1351  
  1352  // RpushCtx is the implementation of redis rpush command.
  1353  func (s *Redis) RpushCtx(ctx context.Context, key string, values ...interface{}) (val int, err error) {
  1354  	err = s.brk.DoWithAcceptable(func() error {
  1355  		conn, err := getRedis(s)
  1356  		if err != nil {
  1357  			return err
  1358  		}
  1359  
  1360  		v, err := conn.RPush(ctx, key, values...).Result()
  1361  		if err != nil {
  1362  			return err
  1363  		}
  1364  
  1365  		val = int(v)
  1366  		return nil
  1367  	}, acceptable)
  1368  
  1369  	return
  1370  }
  1371  
  1372  // Sadd is the implementation of redis sadd command.
  1373  func (s *Redis) Sadd(key string, values ...interface{}) (int, error) {
  1374  	return s.SaddCtx(context.Background(), key, values...)
  1375  }
  1376  
  1377  // SaddCtx is the implementation of redis sadd command.
  1378  func (s *Redis) SaddCtx(ctx context.Context, key string, values ...interface{}) (val int, err error) {
  1379  	err = s.brk.DoWithAcceptable(func() error {
  1380  		conn, err := getRedis(s)
  1381  		if err != nil {
  1382  			return err
  1383  		}
  1384  
  1385  		v, err := conn.SAdd(ctx, key, values...).Result()
  1386  		if err != nil {
  1387  			return err
  1388  		}
  1389  
  1390  		val = int(v)
  1391  		return nil
  1392  	}, acceptable)
  1393  
  1394  	return
  1395  }
  1396  
  1397  // Scan is the implementation of redis scan command.
  1398  func (s *Redis) Scan(cursor uint64, match string, count int64) (keys []string, cur uint64, err error) {
  1399  	return s.ScanCtx(context.Background(), cursor, match, count)
  1400  }
  1401  
  1402  // ScanCtx is the implementation of redis scan command.
  1403  func (s *Redis) ScanCtx(ctx context.Context, cursor uint64, match string, count int64) (
  1404  	keys []string, cur uint64, err error) {
  1405  	err = s.brk.DoWithAcceptable(func() error {
  1406  		conn, err := getRedis(s)
  1407  		if err != nil {
  1408  			return err
  1409  		}
  1410  
  1411  		keys, cur, err = conn.Scan(ctx, cursor, match, count).Result()
  1412  		return err
  1413  	}, acceptable)
  1414  
  1415  	return
  1416  }
  1417  
  1418  // SetBit is the implementation of redis setbit command.
  1419  func (s *Redis) SetBit(key string, offset int64, value int) (int, error) {
  1420  	return s.SetBitCtx(context.Background(), key, offset, value)
  1421  }
  1422  
  1423  // SetBitCtx is the implementation of redis setbit command.
  1424  func (s *Redis) SetBitCtx(ctx context.Context, key string, offset int64, value int) (val int, err error) {
  1425  	err = s.brk.DoWithAcceptable(func() error {
  1426  		conn, err := getRedis(s)
  1427  		if err != nil {
  1428  			return err
  1429  		}
  1430  
  1431  		v, err := conn.SetBit(ctx, key, offset, value).Result()
  1432  		if err != nil {
  1433  			return err
  1434  		}
  1435  
  1436  		val = int(v)
  1437  		return nil
  1438  	}, acceptable)
  1439  
  1440  	return
  1441  }
  1442  
  1443  // Sscan is the implementation of redis sscan command.
  1444  func (s *Redis) Sscan(key string, cursor uint64, match string, count int64) (
  1445  	keys []string, cur uint64, err error) {
  1446  	return s.SscanCtx(context.Background(), key, cursor, match, count)
  1447  }
  1448  
  1449  // SscanCtx is the implementation of redis sscan command.
  1450  func (s *Redis) SscanCtx(ctx context.Context, key string, cursor uint64, match string, count int64) (
  1451  	keys []string, cur uint64, err error) {
  1452  	err = s.brk.DoWithAcceptable(func() error {
  1453  		conn, err := getRedis(s)
  1454  		if err != nil {
  1455  			return err
  1456  		}
  1457  
  1458  		keys, cur, err = conn.SScan(ctx, key, cursor, match, count).Result()
  1459  		return err
  1460  	}, acceptable)
  1461  
  1462  	return
  1463  }
  1464  
  1465  // Scard is the implementation of redis scard command.
  1466  func (s *Redis) Scard(key string) (int64, error) {
  1467  	return s.ScardCtx(context.Background(), key)
  1468  }
  1469  
  1470  // ScardCtx is the implementation of redis scard command.
  1471  func (s *Redis) ScardCtx(ctx context.Context, key string) (val int64, err error) {
  1472  	err = s.brk.DoWithAcceptable(func() error {
  1473  		conn, err := getRedis(s)
  1474  		if err != nil {
  1475  			return err
  1476  		}
  1477  
  1478  		val, err = conn.SCard(ctx, key).Result()
  1479  		return err
  1480  	}, acceptable)
  1481  
  1482  	return
  1483  }
  1484  
  1485  // ScriptLoad is the implementation of redis script load command.
  1486  func (s *Redis) ScriptLoad(script string) (string, error) {
  1487  	return s.ScriptLoadCtx(context.Background(), script)
  1488  }
  1489  
  1490  // ScriptLoadCtx is the implementation of redis script load command.
  1491  func (s *Redis) ScriptLoadCtx(ctx context.Context, script string) (string, error) {
  1492  	conn, err := getRedis(s)
  1493  	if err != nil {
  1494  		return "", err
  1495  	}
  1496  
  1497  	return conn.ScriptLoad(ctx, script).Result()
  1498  }
  1499  
  1500  // Set is the implementation of redis set command.
  1501  func (s *Redis) Set(key, value string) error {
  1502  	return s.SetCtx(context.Background(), key, value)
  1503  }
  1504  
  1505  // SetCtx is the implementation of redis set command.
  1506  func (s *Redis) SetCtx(ctx context.Context, key, value string) error {
  1507  	return s.brk.DoWithAcceptable(func() error {
  1508  		conn, err := getRedis(s)
  1509  		if err != nil {
  1510  			return err
  1511  		}
  1512  
  1513  		return conn.Set(ctx, key, value, 0).Err()
  1514  	}, acceptable)
  1515  }
  1516  
  1517  // Setex is the implementation of redis setex command.
  1518  func (s *Redis) Setex(key, value string, seconds int) error {
  1519  	return s.SetexCtx(context.Background(), key, value, seconds)
  1520  }
  1521  
  1522  // SetexCtx is the implementation of redis setex command.
  1523  func (s *Redis) SetexCtx(ctx context.Context, key, value string, seconds int) error {
  1524  	return s.brk.DoWithAcceptable(func() error {
  1525  		conn, err := getRedis(s)
  1526  		if err != nil {
  1527  			return err
  1528  		}
  1529  
  1530  		return conn.Set(ctx, key, value, time.Duration(seconds)*time.Second).Err()
  1531  	}, acceptable)
  1532  }
  1533  
  1534  // Setnx is the implementation of redis setnx command.
  1535  func (s *Redis) Setnx(key, value string) (bool, error) {
  1536  	return s.SetnxCtx(context.Background(), key, value)
  1537  }
  1538  
  1539  // SetnxCtx is the implementation of redis setnx command.
  1540  func (s *Redis) SetnxCtx(ctx context.Context, key, value string) (val bool, err error) {
  1541  	err = s.brk.DoWithAcceptable(func() error {
  1542  		conn, err := getRedis(s)
  1543  		if err != nil {
  1544  			return err
  1545  		}
  1546  
  1547  		val, err = conn.SetNX(ctx, key, value, 0).Result()
  1548  		return err
  1549  	}, acceptable)
  1550  
  1551  	return
  1552  }
  1553  
  1554  // SetnxEx is the implementation of redis setnx command with expire.
  1555  func (s *Redis) SetnxEx(key, value string, seconds int) (bool, error) {
  1556  	return s.SetnxExCtx(context.Background(), key, value, seconds)
  1557  }
  1558  
  1559  // SetnxExCtx is the implementation of redis setnx command with expire.
  1560  func (s *Redis) SetnxExCtx(ctx context.Context, key, value string, seconds int) (val bool, err error) {
  1561  	err = s.brk.DoWithAcceptable(func() error {
  1562  		conn, err := getRedis(s)
  1563  		if err != nil {
  1564  			return err
  1565  		}
  1566  
  1567  		val, err = conn.SetNX(ctx, key, value, time.Duration(seconds)*time.Second).Result()
  1568  		return err
  1569  	}, acceptable)
  1570  
  1571  	return
  1572  }
  1573  
  1574  // Sismember is the implementation of redis sismember command.
  1575  func (s *Redis) Sismember(key string, value interface{}) (bool, error) {
  1576  	return s.SismemberCtx(context.Background(), key, value)
  1577  }
  1578  
  1579  // SismemberCtx is the implementation of redis sismember command.
  1580  func (s *Redis) SismemberCtx(ctx context.Context, key string, value interface{}) (val bool, err error) {
  1581  	err = s.brk.DoWithAcceptable(func() error {
  1582  		conn, err := getRedis(s)
  1583  		if err != nil {
  1584  			return err
  1585  		}
  1586  
  1587  		val, err = conn.SIsMember(ctx, key, value).Result()
  1588  		return err
  1589  	}, acceptable)
  1590  
  1591  	return
  1592  }
  1593  
  1594  // Smembers is the implementation of redis smembers command.
  1595  func (s *Redis) Smembers(key string) ([]string, error) {
  1596  	return s.SmembersCtx(context.Background(), key)
  1597  }
  1598  
  1599  // SmembersCtx is the implementation of redis smembers command.
  1600  func (s *Redis) SmembersCtx(ctx context.Context, key string) (val []string, err error) {
  1601  	err = s.brk.DoWithAcceptable(func() error {
  1602  		conn, err := getRedis(s)
  1603  		if err != nil {
  1604  			return err
  1605  		}
  1606  
  1607  		val, err = conn.SMembers(ctx, key).Result()
  1608  		return err
  1609  	}, acceptable)
  1610  
  1611  	return
  1612  }
  1613  
  1614  // Spop is the implementation of redis spop command.
  1615  func (s *Redis) Spop(key string) (string, error) {
  1616  	return s.SpopCtx(context.Background(), key)
  1617  }
  1618  
  1619  // SpopCtx is the implementation of redis spop command.
  1620  func (s *Redis) SpopCtx(ctx context.Context, key string) (val string, err error) {
  1621  	err = s.brk.DoWithAcceptable(func() error {
  1622  		conn, err := getRedis(s)
  1623  		if err != nil {
  1624  			return err
  1625  		}
  1626  
  1627  		val, err = conn.SPop(ctx, key).Result()
  1628  		return err
  1629  	}, acceptable)
  1630  
  1631  	return
  1632  }
  1633  
  1634  // Srandmember is the implementation of redis srandmember command.
  1635  func (s *Redis) Srandmember(key string, count int) ([]string, error) {
  1636  	return s.SrandmemberCtx(context.Background(), key, count)
  1637  }
  1638  
  1639  // SrandmemberCtx is the implementation of redis srandmember command.
  1640  func (s *Redis) SrandmemberCtx(ctx context.Context, key string, count int) (val []string, err error) {
  1641  	err = s.brk.DoWithAcceptable(func() error {
  1642  		conn, err := getRedis(s)
  1643  		if err != nil {
  1644  			return err
  1645  		}
  1646  
  1647  		val, err = conn.SRandMemberN(ctx, key, int64(count)).Result()
  1648  		return err
  1649  	}, acceptable)
  1650  
  1651  	return
  1652  }
  1653  
  1654  // Srem is the implementation of redis srem command.
  1655  func (s *Redis) Srem(key string, values ...interface{}) (int, error) {
  1656  	return s.SremCtx(context.Background(), key, values...)
  1657  }
  1658  
  1659  // SremCtx is the implementation of redis srem command.
  1660  func (s *Redis) SremCtx(ctx context.Context, key string, values ...interface{}) (val int, err error) {
  1661  	err = s.brk.DoWithAcceptable(func() error {
  1662  		conn, err := getRedis(s)
  1663  		if err != nil {
  1664  			return err
  1665  		}
  1666  
  1667  		v, err := conn.SRem(ctx, key, values...).Result()
  1668  		if err != nil {
  1669  			return err
  1670  		}
  1671  
  1672  		val = int(v)
  1673  		return nil
  1674  	}, acceptable)
  1675  
  1676  	return
  1677  }
  1678  
  1679  // String returns the string representation of s.
  1680  func (s *Redis) String() string {
  1681  	return s.Addr
  1682  }
  1683  
  1684  // Sunion is the implementation of redis sunion command.
  1685  func (s *Redis) Sunion(keys ...string) ([]string, error) {
  1686  	return s.SunionCtx(context.Background(), keys...)
  1687  }
  1688  
  1689  // SunionCtx is the implementation of redis sunion command.
  1690  func (s *Redis) SunionCtx(ctx context.Context, keys ...string) (val []string, err error) {
  1691  	err = s.brk.DoWithAcceptable(func() error {
  1692  		conn, err := getRedis(s)
  1693  		if err != nil {
  1694  			return err
  1695  		}
  1696  
  1697  		val, err = conn.SUnion(ctx, keys...).Result()
  1698  		return err
  1699  	}, acceptable)
  1700  
  1701  	return
  1702  }
  1703  
  1704  // Sunionstore is the implementation of redis sunionstore command.
  1705  func (s *Redis) Sunionstore(destination string, keys ...string) (int, error) {
  1706  	return s.SunionstoreCtx(context.Background(), destination, keys...)
  1707  }
  1708  
  1709  // SunionstoreCtx is the implementation of redis sunionstore command.
  1710  func (s *Redis) SunionstoreCtx(ctx context.Context, destination string, keys ...string) (
  1711  	val int, err error) {
  1712  	err = s.brk.DoWithAcceptable(func() error {
  1713  		conn, err := getRedis(s)
  1714  		if err != nil {
  1715  			return err
  1716  		}
  1717  
  1718  		v, err := conn.SUnionStore(ctx, destination, keys...).Result()
  1719  		if err != nil {
  1720  			return err
  1721  		}
  1722  
  1723  		val = int(v)
  1724  		return nil
  1725  	}, acceptable)
  1726  
  1727  	return
  1728  }
  1729  
  1730  // Sdiff is the implementation of redis sdiff command.
  1731  func (s *Redis) Sdiff(keys ...string) ([]string, error) {
  1732  	return s.SdiffCtx(context.Background(), keys...)
  1733  }
  1734  
  1735  // SdiffCtx is the implementation of redis sdiff command.
  1736  func (s *Redis) SdiffCtx(ctx context.Context, keys ...string) (val []string, err error) {
  1737  	err = s.brk.DoWithAcceptable(func() error {
  1738  		conn, err := getRedis(s)
  1739  		if err != nil {
  1740  			return err
  1741  		}
  1742  
  1743  		val, err = conn.SDiff(ctx, keys...).Result()
  1744  		return err
  1745  	}, acceptable)
  1746  
  1747  	return
  1748  }
  1749  
  1750  // Sdiffstore is the implementation of redis sdiffstore command.
  1751  func (s *Redis) Sdiffstore(destination string, keys ...string) (int, error) {
  1752  	return s.SdiffstoreCtx(context.Background(), destination, keys...)
  1753  }
  1754  
  1755  // SdiffstoreCtx is the implementation of redis sdiffstore command.
  1756  func (s *Redis) SdiffstoreCtx(ctx context.Context, destination string, keys ...string) (
  1757  	val int, err error) {
  1758  	err = s.brk.DoWithAcceptable(func() error {
  1759  		conn, err := getRedis(s)
  1760  		if err != nil {
  1761  			return err
  1762  		}
  1763  
  1764  		v, err := conn.SDiffStore(ctx, destination, keys...).Result()
  1765  		if err != nil {
  1766  			return err
  1767  		}
  1768  
  1769  		val = int(v)
  1770  		return nil
  1771  	}, acceptable)
  1772  
  1773  	return
  1774  }
  1775  
  1776  // Sinter is the implementation of redis sinter command.
  1777  func (s *Redis) Sinter(keys ...string) ([]string, error) {
  1778  	return s.SinterCtx(context.Background(), keys...)
  1779  }
  1780  
  1781  // SinterCtx is the implementation of redis sinter command.
  1782  func (s *Redis) SinterCtx(ctx context.Context, keys ...string) (val []string, err error) {
  1783  	err = s.brk.DoWithAcceptable(func() error {
  1784  		conn, err := getRedis(s)
  1785  		if err != nil {
  1786  			return err
  1787  		}
  1788  
  1789  		val, err = conn.SInter(ctx, keys...).Result()
  1790  		return err
  1791  	}, acceptable)
  1792  
  1793  	return
  1794  }
  1795  
  1796  // Sinterstore is the implementation of redis sinterstore command.
  1797  func (s *Redis) Sinterstore(destination string, keys ...string) (int, error) {
  1798  	return s.SinterstoreCtx(context.Background(), destination, keys...)
  1799  }
  1800  
  1801  // SinterstoreCtx is the implementation of redis sinterstore command.
  1802  func (s *Redis) SinterstoreCtx(ctx context.Context, destination string, keys ...string) (
  1803  	val int, err error) {
  1804  	err = s.brk.DoWithAcceptable(func() error {
  1805  		conn, err := getRedis(s)
  1806  		if err != nil {
  1807  			return err
  1808  		}
  1809  
  1810  		v, err := conn.SInterStore(ctx, destination, keys...).Result()
  1811  		if err != nil {
  1812  			return err
  1813  		}
  1814  
  1815  		val = int(v)
  1816  		return nil
  1817  	}, acceptable)
  1818  
  1819  	return
  1820  }
  1821  
  1822  // Ttl is the implementation of redis ttl command.
  1823  func (s *Redis) Ttl(key string) (int, error) {
  1824  	return s.TtlCtx(context.Background(), key)
  1825  }
  1826  
  1827  // TtlCtx is the implementation of redis ttl command.
  1828  func (s *Redis) TtlCtx(ctx context.Context, key string) (val int, err error) {
  1829  	err = s.brk.DoWithAcceptable(func() error {
  1830  		conn, err := getRedis(s)
  1831  		if err != nil {
  1832  			return err
  1833  		}
  1834  
  1835  		duration, err := conn.TTL(ctx, key).Result()
  1836  		if err != nil {
  1837  			return err
  1838  		}
  1839  
  1840  		val = int(duration / time.Second)
  1841  		return nil
  1842  	}, acceptable)
  1843  
  1844  	return
  1845  }
  1846  
  1847  // Zadd is the implementation of redis zadd command.
  1848  func (s *Redis) Zadd(key string, score int64, value string) (bool, error) {
  1849  	return s.ZaddCtx(context.Background(), key, score, value)
  1850  }
  1851  
  1852  // ZaddFloat is the implementation of redis zadd command.
  1853  func (s *Redis) ZaddFloat(key string, score float64, value string) (bool, error) {
  1854  	return s.ZaddFloatCtx(context.Background(), key, score, value)
  1855  }
  1856  
  1857  // ZaddCtx is the implementation of redis zadd command.
  1858  func (s *Redis) ZaddCtx(ctx context.Context, key string, score int64, value string) (
  1859  	val bool, err error) {
  1860  	return s.ZaddFloatCtx(ctx, key, float64(score), value)
  1861  }
  1862  
  1863  // ZaddFloatCtx is the implementation of redis zadd command.
  1864  func (s *Redis) ZaddFloatCtx(ctx context.Context, key string, score float64, value string) (
  1865  	val bool, err error) {
  1866  	err = s.brk.DoWithAcceptable(func() error {
  1867  		conn, err := getRedis(s)
  1868  		if err != nil {
  1869  			return err
  1870  		}
  1871  
  1872  		v, err := conn.ZAdd(ctx, key, &red.Z{
  1873  			Score:  score,
  1874  			Member: value,
  1875  		}).Result()
  1876  		if err != nil {
  1877  			return err
  1878  		}
  1879  
  1880  		val = v == 1
  1881  		return nil
  1882  	}, acceptable)
  1883  
  1884  	return
  1885  }
  1886  
  1887  // Zadds is the implementation of redis zadds command.
  1888  func (s *Redis) Zadds(key string, ps ...Pair) (int64, error) {
  1889  	return s.ZaddsCtx(context.Background(), key, ps...)
  1890  }
  1891  
  1892  // ZaddsCtx is the implementation of redis zadds command.
  1893  func (s *Redis) ZaddsCtx(ctx context.Context, key string, ps ...Pair) (val int64, err error) {
  1894  	err = s.brk.DoWithAcceptable(func() error {
  1895  		conn, err := getRedis(s)
  1896  		if err != nil {
  1897  			return err
  1898  		}
  1899  
  1900  		var zs []*red.Z
  1901  		for _, p := range ps {
  1902  			z := &red.Z{Score: float64(p.Score), Member: p.Key}
  1903  			zs = append(zs, z)
  1904  		}
  1905  
  1906  		v, err := conn.ZAdd(ctx, key, zs...).Result()
  1907  		if err != nil {
  1908  			return err
  1909  		}
  1910  
  1911  		val = v
  1912  		return nil
  1913  	}, acceptable)
  1914  
  1915  	return
  1916  }
  1917  
  1918  // Zcard is the implementation of redis zcard command.
  1919  func (s *Redis) Zcard(key string) (int, error) {
  1920  	return s.ZcardCtx(context.Background(), key)
  1921  }
  1922  
  1923  // ZcardCtx is the implementation of redis zcard command.
  1924  func (s *Redis) ZcardCtx(ctx context.Context, key string) (val int, err error) {
  1925  	err = s.brk.DoWithAcceptable(func() error {
  1926  		conn, err := getRedis(s)
  1927  		if err != nil {
  1928  			return err
  1929  		}
  1930  
  1931  		v, err := conn.ZCard(ctx, key).Result()
  1932  		if err != nil {
  1933  			return err
  1934  		}
  1935  
  1936  		val = int(v)
  1937  		return nil
  1938  	}, acceptable)
  1939  
  1940  	return
  1941  }
  1942  
  1943  // Zcount is the implementation of redis zcount command.
  1944  func (s *Redis) Zcount(key string, start, stop int64) (int, error) {
  1945  	return s.ZcountCtx(context.Background(), key, start, stop)
  1946  }
  1947  
  1948  // ZcountCtx is the implementation of redis zcount command.
  1949  func (s *Redis) ZcountCtx(ctx context.Context, key string, start, stop int64) (val int, err error) {
  1950  	err = s.brk.DoWithAcceptable(func() error {
  1951  		conn, err := getRedis(s)
  1952  		if err != nil {
  1953  			return err
  1954  		}
  1955  
  1956  		v, err := conn.ZCount(ctx, key, strconv.FormatInt(start, 10),
  1957  			strconv.FormatInt(stop, 10)).Result()
  1958  		if err != nil {
  1959  			return err
  1960  		}
  1961  
  1962  		val = int(v)
  1963  		return nil
  1964  	}, acceptable)
  1965  
  1966  	return
  1967  }
  1968  
  1969  // Zincrby is the implementation of redis zincrby command.
  1970  func (s *Redis) Zincrby(key string, increment int64, field string) (int64, error) {
  1971  	return s.ZincrbyCtx(context.Background(), key, increment, field)
  1972  }
  1973  
  1974  // ZincrbyCtx is the implementation of redis zincrby command.
  1975  func (s *Redis) ZincrbyCtx(ctx context.Context, key string, increment int64, field string) (
  1976  	val int64, err error) {
  1977  	err = s.brk.DoWithAcceptable(func() error {
  1978  		conn, err := getRedis(s)
  1979  		if err != nil {
  1980  			return err
  1981  		}
  1982  
  1983  		v, err := conn.ZIncrBy(ctx, key, float64(increment), field).Result()
  1984  		if err != nil {
  1985  			return err
  1986  		}
  1987  
  1988  		val = int64(v)
  1989  		return nil
  1990  	}, acceptable)
  1991  
  1992  	return
  1993  }
  1994  
  1995  // Zscore is the implementation of redis zscore command.
  1996  func (s *Redis) Zscore(key, value string) (int64, error) {
  1997  	return s.ZscoreCtx(context.Background(), key, value)
  1998  }
  1999  
  2000  // ZscoreCtx is the implementation of redis zscore command.
  2001  func (s *Redis) ZscoreCtx(ctx context.Context, key, value string) (val int64, err error) {
  2002  	err = s.brk.DoWithAcceptable(func() error {
  2003  		conn, err := getRedis(s)
  2004  		if err != nil {
  2005  			return err
  2006  		}
  2007  
  2008  		v, err := conn.ZScore(ctx, key, value).Result()
  2009  		if err != nil {
  2010  			return err
  2011  		}
  2012  
  2013  		val = int64(v)
  2014  		return nil
  2015  	}, acceptable)
  2016  
  2017  	return
  2018  }
  2019  
  2020  // Zrank is the implementation of redis zrank command.
  2021  func (s *Redis) Zrank(key, field string) (int64, error) {
  2022  	return s.ZrankCtx(context.Background(), key, field)
  2023  }
  2024  
  2025  // ZrankCtx is the implementation of redis zrank command.
  2026  func (s *Redis) ZrankCtx(ctx context.Context, key, field string) (val int64, err error) {
  2027  	err = s.brk.DoWithAcceptable(func() error {
  2028  		conn, err := getRedis(s)
  2029  		if err != nil {
  2030  			return err
  2031  		}
  2032  
  2033  		val, err = conn.ZRank(ctx, key, field).Result()
  2034  		return err
  2035  	}, acceptable)
  2036  
  2037  	return
  2038  }
  2039  
  2040  // Zrem is the implementation of redis zrem command.
  2041  func (s *Redis) Zrem(key string, values ...interface{}) (int, error) {
  2042  	return s.ZremCtx(context.Background(), key, values...)
  2043  }
  2044  
  2045  // ZremCtx is the implementation of redis zrem command.
  2046  func (s *Redis) ZremCtx(ctx context.Context, key string, values ...interface{}) (val int, err error) {
  2047  	err = s.brk.DoWithAcceptable(func() error {
  2048  		conn, err := getRedis(s)
  2049  		if err != nil {
  2050  			return err
  2051  		}
  2052  
  2053  		v, err := conn.ZRem(ctx, key, values...).Result()
  2054  		if err != nil {
  2055  			return err
  2056  		}
  2057  
  2058  		val = int(v)
  2059  		return nil
  2060  	}, acceptable)
  2061  
  2062  	return
  2063  }
  2064  
  2065  // Zremrangebyscore is the implementation of redis zremrangebyscore command.
  2066  func (s *Redis) Zremrangebyscore(key string, start, stop int64) (int, error) {
  2067  	return s.ZremrangebyscoreCtx(context.Background(), key, start, stop)
  2068  }
  2069  
  2070  // ZremrangebyscoreCtx is the implementation of redis zremrangebyscore command.
  2071  func (s *Redis) ZremrangebyscoreCtx(ctx context.Context, key string, start, stop int64) (
  2072  	val int, err error) {
  2073  	err = s.brk.DoWithAcceptable(func() error {
  2074  		conn, err := getRedis(s)
  2075  		if err != nil {
  2076  			return err
  2077  		}
  2078  
  2079  		v, err := conn.ZRemRangeByScore(ctx, key, strconv.FormatInt(start, 10),
  2080  			strconv.FormatInt(stop, 10)).Result()
  2081  		if err != nil {
  2082  			return err
  2083  		}
  2084  
  2085  		val = int(v)
  2086  		return nil
  2087  	}, acceptable)
  2088  
  2089  	return
  2090  }
  2091  
  2092  // Zremrangebyrank is the implementation of redis zremrangebyrank command.
  2093  func (s *Redis) Zremrangebyrank(key string, start, stop int64) (int, error) {
  2094  	return s.ZremrangebyrankCtx(context.Background(), key, start, stop)
  2095  }
  2096  
  2097  // ZremrangebyrankCtx is the implementation of redis zremrangebyrank command.
  2098  func (s *Redis) ZremrangebyrankCtx(ctx context.Context, key string, start, stop int64) (
  2099  	val int, err error) {
  2100  	err = s.brk.DoWithAcceptable(func() error {
  2101  		conn, err := getRedis(s)
  2102  		if err != nil {
  2103  			return err
  2104  		}
  2105  
  2106  		v, err := conn.ZRemRangeByRank(ctx, key, start, stop).Result()
  2107  		if err != nil {
  2108  			return err
  2109  		}
  2110  
  2111  		val = int(v)
  2112  		return nil
  2113  	}, acceptable)
  2114  
  2115  	return
  2116  }
  2117  
  2118  // Zrange is the implementation of redis zrange command.
  2119  func (s *Redis) Zrange(key string, start, stop int64) ([]string, error) {
  2120  	return s.ZrangeCtx(context.Background(), key, start, stop)
  2121  }
  2122  
  2123  // ZrangeCtx is the implementation of redis zrange command.
  2124  func (s *Redis) ZrangeCtx(ctx context.Context, key string, start, stop int64) (
  2125  	val []string, err error) {
  2126  	err = s.brk.DoWithAcceptable(func() error {
  2127  		conn, err := getRedis(s)
  2128  		if err != nil {
  2129  			return err
  2130  		}
  2131  
  2132  		val, err = conn.ZRange(ctx, key, start, stop).Result()
  2133  		return err
  2134  	}, acceptable)
  2135  
  2136  	return
  2137  }
  2138  
  2139  // ZrangeWithScores is the implementation of redis zrange command with scores.
  2140  func (s *Redis) ZrangeWithScores(key string, start, stop int64) ([]Pair, error) {
  2141  	return s.ZrangeWithScoresCtx(context.Background(), key, start, stop)
  2142  }
  2143  
  2144  // ZrangeWithScoresCtx is the implementation of redis zrange command with scores.
  2145  func (s *Redis) ZrangeWithScoresCtx(ctx context.Context, key string, start, stop int64) (
  2146  	val []Pair, err error) {
  2147  	err = s.brk.DoWithAcceptable(func() error {
  2148  		conn, err := getRedis(s)
  2149  		if err != nil {
  2150  			return err
  2151  		}
  2152  
  2153  		v, err := conn.ZRangeWithScores(ctx, key, start, stop).Result()
  2154  		if err != nil {
  2155  			return err
  2156  		}
  2157  
  2158  		val = toPairs(v)
  2159  		return nil
  2160  	}, acceptable)
  2161  
  2162  	return
  2163  }
  2164  
  2165  // ZRevRangeWithScores is the implementation of redis zrevrange command with scores.
  2166  func (s *Redis) ZRevRangeWithScores(key string, start, stop int64) ([]Pair, error) {
  2167  	return s.ZRevRangeWithScoresCtx(context.Background(), key, start, stop)
  2168  }
  2169  
  2170  // ZRevRangeWithScoresCtx is the implementation of redis zrevrange command with scores.
  2171  func (s *Redis) ZRevRangeWithScoresCtx(ctx context.Context, key string, start, stop int64) (
  2172  	val []Pair, err error) {
  2173  	err = s.brk.DoWithAcceptable(func() error {
  2174  		conn, err := getRedis(s)
  2175  		if err != nil {
  2176  			return err
  2177  		}
  2178  
  2179  		v, err := conn.ZRevRangeWithScores(ctx, key, start, stop).Result()
  2180  		if err != nil {
  2181  			return err
  2182  		}
  2183  
  2184  		val = toPairs(v)
  2185  		return nil
  2186  	}, acceptable)
  2187  
  2188  	return
  2189  }
  2190  
  2191  // ZrangebyscoreWithScores is the implementation of redis zrangebyscore command with scores.
  2192  func (s *Redis) ZrangebyscoreWithScores(key string, start, stop int64) ([]Pair, error) {
  2193  	return s.ZrangebyscoreWithScoresCtx(context.Background(), key, start, stop)
  2194  }
  2195  
  2196  // ZrangebyscoreWithScoresCtx is the implementation of redis zrangebyscore command with scores.
  2197  func (s *Redis) ZrangebyscoreWithScoresCtx(ctx context.Context, key string, start, stop int64) (
  2198  	val []Pair, err error) {
  2199  	err = s.brk.DoWithAcceptable(func() error {
  2200  		conn, err := getRedis(s)
  2201  		if err != nil {
  2202  			return err
  2203  		}
  2204  
  2205  		v, err := conn.ZRangeByScoreWithScores(ctx, key, &red.ZRangeBy{
  2206  			Min: strconv.FormatInt(start, 10),
  2207  			Max: strconv.FormatInt(stop, 10),
  2208  		}).Result()
  2209  		if err != nil {
  2210  			return err
  2211  		}
  2212  
  2213  		val = toPairs(v)
  2214  		return nil
  2215  	}, acceptable)
  2216  
  2217  	return
  2218  }
  2219  
  2220  // ZrangebyscoreWithScoresAndLimit is the implementation of redis zrangebyscore command
  2221  // with scores and limit.
  2222  func (s *Redis) ZrangebyscoreWithScoresAndLimit(key string, start, stop int64,
  2223  	page, size int) ([]Pair, error) {
  2224  	return s.ZrangebyscoreWithScoresAndLimitCtx(context.Background(), key, start, stop, page, size)
  2225  }
  2226  
  2227  // ZrangebyscoreWithScoresAndLimitCtx is the implementation of redis zrangebyscore command
  2228  // with scores and limit.
  2229  func (s *Redis) ZrangebyscoreWithScoresAndLimitCtx(ctx context.Context, key string, start,
  2230  	stop int64, page, size int) (val []Pair, err error) {
  2231  	err = s.brk.DoWithAcceptable(func() error {
  2232  		if size <= 0 {
  2233  			return nil
  2234  		}
  2235  
  2236  		conn, err := getRedis(s)
  2237  		if err != nil {
  2238  			return err
  2239  		}
  2240  
  2241  		v, err := conn.ZRangeByScoreWithScores(ctx, key, &red.ZRangeBy{
  2242  			Min:    strconv.FormatInt(start, 10),
  2243  			Max:    strconv.FormatInt(stop, 10),
  2244  			Offset: int64(page * size),
  2245  			Count:  int64(size),
  2246  		}).Result()
  2247  		if err != nil {
  2248  			return err
  2249  		}
  2250  
  2251  		val = toPairs(v)
  2252  		return nil
  2253  	}, acceptable)
  2254  
  2255  	return
  2256  }
  2257  
  2258  // Zrevrange is the implementation of redis zrevrange command.
  2259  func (s *Redis) Zrevrange(key string, start, stop int64) ([]string, error) {
  2260  	return s.ZrevrangeCtx(context.Background(), key, start, stop)
  2261  }
  2262  
  2263  // ZrevrangeCtx is the implementation of redis zrevrange command.
  2264  func (s *Redis) ZrevrangeCtx(ctx context.Context, key string, start, stop int64) (
  2265  	val []string, err error) {
  2266  	err = s.brk.DoWithAcceptable(func() error {
  2267  		conn, err := getRedis(s)
  2268  		if err != nil {
  2269  			return err
  2270  		}
  2271  
  2272  		val, err = conn.ZRevRange(ctx, key, start, stop).Result()
  2273  		return err
  2274  	}, acceptable)
  2275  
  2276  	return
  2277  }
  2278  
  2279  // ZrevrangebyscoreWithScores is the implementation of redis zrevrangebyscore command with scores.
  2280  func (s *Redis) ZrevrangebyscoreWithScores(key string, start, stop int64) ([]Pair, error) {
  2281  	return s.ZrevrangebyscoreWithScoresCtx(context.Background(), key, start, stop)
  2282  }
  2283  
  2284  // ZrevrangebyscoreWithScoresCtx is the implementation of redis zrevrangebyscore command with scores.
  2285  func (s *Redis) ZrevrangebyscoreWithScoresCtx(ctx context.Context, key string, start, stop int64) (
  2286  	val []Pair, err error) {
  2287  	err = s.brk.DoWithAcceptable(func() error {
  2288  		conn, err := getRedis(s)
  2289  		if err != nil {
  2290  			return err
  2291  		}
  2292  
  2293  		v, err := conn.ZRevRangeByScoreWithScores(ctx, key, &red.ZRangeBy{
  2294  			Min: strconv.FormatInt(start, 10),
  2295  			Max: strconv.FormatInt(stop, 10),
  2296  		}).Result()
  2297  		if err != nil {
  2298  			return err
  2299  		}
  2300  
  2301  		val = toPairs(v)
  2302  		return nil
  2303  	}, acceptable)
  2304  
  2305  	return
  2306  }
  2307  
  2308  // ZrevrangebyscoreWithScoresAndLimit is the implementation of redis zrevrangebyscore command
  2309  // with scores and limit.
  2310  func (s *Redis) ZrevrangebyscoreWithScoresAndLimit(key string, start, stop int64,
  2311  	page, size int) ([]Pair, error) {
  2312  	return s.ZrevrangebyscoreWithScoresAndLimitCtx(context.Background(), key, start, stop, page, size)
  2313  }
  2314  
  2315  // ZrevrangebyscoreWithScoresAndLimitCtx is the implementation of redis zrevrangebyscore command
  2316  // with scores and limit.
  2317  func (s *Redis) ZrevrangebyscoreWithScoresAndLimitCtx(ctx context.Context, key string,
  2318  	start, stop int64, page, size int) (val []Pair, err error) {
  2319  	err = s.brk.DoWithAcceptable(func() error {
  2320  		if size <= 0 {
  2321  			return nil
  2322  		}
  2323  
  2324  		conn, err := getRedis(s)
  2325  		if err != nil {
  2326  			return err
  2327  		}
  2328  
  2329  		v, err := conn.ZRevRangeByScoreWithScores(ctx, key, &red.ZRangeBy{
  2330  			Min:    strconv.FormatInt(start, 10),
  2331  			Max:    strconv.FormatInt(stop, 10),
  2332  			Offset: int64(page * size),
  2333  			Count:  int64(size),
  2334  		}).Result()
  2335  		if err != nil {
  2336  			return err
  2337  		}
  2338  
  2339  		val = toPairs(v)
  2340  		return nil
  2341  	}, acceptable)
  2342  
  2343  	return
  2344  }
  2345  
  2346  // Zrevrank is the implementation of redis zrevrank command.
  2347  func (s *Redis) Zrevrank(key, field string) (int64, error) {
  2348  	return s.ZrevrankCtx(context.Background(), key, field)
  2349  }
  2350  
  2351  // ZrevrankCtx is the implementation of redis zrevrank command.
  2352  func (s *Redis) ZrevrankCtx(ctx context.Context, key, field string) (val int64, err error) {
  2353  	err = s.brk.DoWithAcceptable(func() error {
  2354  		conn, err := getRedis(s)
  2355  		if err != nil {
  2356  			return err
  2357  		}
  2358  
  2359  		val, err = conn.ZRevRank(ctx, key, field).Result()
  2360  		return err
  2361  	}, acceptable)
  2362  
  2363  	return
  2364  }
  2365  
  2366  // Zunionstore is the implementation of redis zunionstore command.
  2367  func (s *Redis) Zunionstore(dest string, store *ZStore) (int64, error) {
  2368  	return s.ZunionstoreCtx(context.Background(), dest, store)
  2369  }
  2370  
  2371  // ZunionstoreCtx is the implementation of redis zunionstore command.
  2372  func (s *Redis) ZunionstoreCtx(ctx context.Context, dest string, store *ZStore) (
  2373  	val int64, err error) {
  2374  	err = s.brk.DoWithAcceptable(func() error {
  2375  		conn, err := getRedis(s)
  2376  		if err != nil {
  2377  			return err
  2378  		}
  2379  
  2380  		val, err = conn.ZUnionStore(ctx, dest, store).Result()
  2381  		return err
  2382  	}, acceptable)
  2383  
  2384  	return
  2385  }
  2386  
  2387  // Cluster customizes the given Redis as a cluster.
  2388  func Cluster() Option {
  2389  	return func(r *Redis) {
  2390  		r.Type = ClusterType
  2391  	}
  2392  }
  2393  
  2394  // SetSlowThreshold sets the slow threshold.
  2395  func SetSlowThreshold(threshold time.Duration) {
  2396  	slowThreshold.Set(threshold)
  2397  }
  2398  
  2399  // WithPass customizes the given Redis with given password.
  2400  func WithPass(pass string) Option {
  2401  	return func(r *Redis) {
  2402  		r.Pass = pass
  2403  	}
  2404  }
  2405  
  2406  // WithTLS customizes the given Redis with TLS enabled.
  2407  func WithTLS() Option {
  2408  	return func(r *Redis) {
  2409  		r.tls = true
  2410  	}
  2411  }
  2412  
  2413  func acceptable(err error) bool {
  2414  	return err == nil || err == red.Nil || err == context.Canceled
  2415  }
  2416  
  2417  func getRedis(r *Redis) (RedisNode, error) {
  2418  	switch r.Type {
  2419  	case ClusterType:
  2420  		return getCluster(r)
  2421  	case NodeType:
  2422  		return getClient(r)
  2423  	default:
  2424  		return nil, fmt.Errorf("redis type '%s' is not supported", r.Type)
  2425  	}
  2426  }
  2427  
  2428  func toPairs(vals []red.Z) []Pair {
  2429  	pairs := make([]Pair, len(vals))
  2430  	for i, val := range vals {
  2431  		switch member := val.Member.(type) {
  2432  		case string:
  2433  			pairs[i] = Pair{
  2434  				Key:   member,
  2435  				Score: int64(val.Score),
  2436  			}
  2437  		default:
  2438  			pairs[i] = Pair{
  2439  				Key:   mapping.Repr(val.Member),
  2440  				Score: int64(val.Score),
  2441  			}
  2442  		}
  2443  	}
  2444  	return pairs
  2445  }
  2446  
  2447  func toStrings(vals []interface{}) []string {
  2448  	ret := make([]string, len(vals))
  2449  	for i, val := range vals {
  2450  		if val == nil {
  2451  			ret[i] = ""
  2452  		} else {
  2453  			switch val := val.(type) {
  2454  			case string:
  2455  				ret[i] = val
  2456  			default:
  2457  				ret[i] = mapping.Repr(val)
  2458  			}
  2459  		}
  2460  	}
  2461  	return ret
  2462  }