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 }