1package redis 2 3import ( 4 "errors" 5 "io" 6 "time" 7 8 "github.com/go-redis/redis/v7/internal" 9) 10 11func usePrecise(dur time.Duration) bool { 12 return dur < time.Second || dur%time.Second != 0 13} 14 15func formatMs(dur time.Duration) int64 { 16 if dur > 0 && dur < time.Millisecond { 17 internal.Logger.Printf( 18 "specified duration is %s, but minimal supported value is %s", 19 dur, time.Millisecond, 20 ) 21 } 22 return int64(dur / time.Millisecond) 23} 24 25func formatSec(dur time.Duration) int64 { 26 if dur > 0 && dur < time.Second { 27 internal.Logger.Printf( 28 "specified duration is %s, but minimal supported value is %s", 29 dur, time.Second, 30 ) 31 } 32 return int64(dur / time.Second) 33} 34 35func appendArgs(dst, src []interface{}) []interface{} { 36 if len(src) == 1 { 37 switch v := src[0].(type) { 38 case []string: 39 for _, s := range v { 40 dst = append(dst, s) 41 } 42 return dst 43 case map[string]interface{}: 44 for k, v := range v { 45 dst = append(dst, k, v) 46 } 47 return dst 48 } 49 } 50 51 dst = append(dst, src...) 52 return dst 53} 54 55type Cmdable interface { 56 Pipeline() Pipeliner 57 Pipelined(fn func(Pipeliner) error) ([]Cmder, error) 58 59 TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) 60 TxPipeline() Pipeliner 61 62 Command() *CommandsInfoCmd 63 ClientGetName() *StringCmd 64 Echo(message interface{}) *StringCmd 65 Ping() *StatusCmd 66 Quit() *StatusCmd 67 Del(keys ...string) *IntCmd 68 Unlink(keys ...string) *IntCmd 69 Dump(key string) *StringCmd 70 Exists(keys ...string) *IntCmd 71 Expire(key string, expiration time.Duration) *BoolCmd 72 ExpireAt(key string, tm time.Time) *BoolCmd 73 Keys(pattern string) *StringSliceCmd 74 Migrate(host, port, key string, db int, timeout time.Duration) *StatusCmd 75 Move(key string, db int) *BoolCmd 76 ObjectRefCount(key string) *IntCmd 77 ObjectEncoding(key string) *StringCmd 78 ObjectIdleTime(key string) *DurationCmd 79 Persist(key string) *BoolCmd 80 PExpire(key string, expiration time.Duration) *BoolCmd 81 PExpireAt(key string, tm time.Time) *BoolCmd 82 PTTL(key string) *DurationCmd 83 RandomKey() *StringCmd 84 Rename(key, newkey string) *StatusCmd 85 RenameNX(key, newkey string) *BoolCmd 86 Restore(key string, ttl time.Duration, value string) *StatusCmd 87 RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd 88 Sort(key string, sort *Sort) *StringSliceCmd 89 SortStore(key, store string, sort *Sort) *IntCmd 90 SortInterfaces(key string, sort *Sort) *SliceCmd 91 Touch(keys ...string) *IntCmd 92 TTL(key string) *DurationCmd 93 Type(key string) *StatusCmd 94 Scan(cursor uint64, match string, count int64) *ScanCmd 95 SScan(key string, cursor uint64, match string, count int64) *ScanCmd 96 HScan(key string, cursor uint64, match string, count int64) *ScanCmd 97 ZScan(key string, cursor uint64, match string, count int64) *ScanCmd 98 Append(key, value string) *IntCmd 99 BitCount(key string, bitCount *BitCount) *IntCmd 100 BitOpAnd(destKey string, keys ...string) *IntCmd 101 BitOpOr(destKey string, keys ...string) *IntCmd 102 BitOpXor(destKey string, keys ...string) *IntCmd 103 BitOpNot(destKey string, key string) *IntCmd 104 BitPos(key string, bit int64, pos ...int64) *IntCmd 105 BitField(key string, args ...interface{}) *IntSliceCmd 106 Decr(key string) *IntCmd 107 DecrBy(key string, decrement int64) *IntCmd 108 Get(key string) *StringCmd 109 GetBit(key string, offset int64) *IntCmd 110 GetRange(key string, start, end int64) *StringCmd 111 GetSet(key string, value interface{}) *StringCmd 112 Incr(key string) *IntCmd 113 IncrBy(key string, value int64) *IntCmd 114 IncrByFloat(key string, value float64) *FloatCmd 115 MGet(keys ...string) *SliceCmd 116 MSet(values ...interface{}) *StatusCmd 117 MSetNX(values ...interface{}) *BoolCmd 118 Set(key string, value interface{}, expiration time.Duration) *StatusCmd 119 SetBit(key string, offset int64, value int) *IntCmd 120 SetNX(key string, value interface{}, expiration time.Duration) *BoolCmd 121 SetXX(key string, value interface{}, expiration time.Duration) *BoolCmd 122 SetRange(key string, offset int64, value string) *IntCmd 123 StrLen(key string) *IntCmd 124 HDel(key string, fields ...string) *IntCmd 125 HExists(key, field string) *BoolCmd 126 HGet(key, field string) *StringCmd 127 HGetAll(key string) *StringStringMapCmd 128 HIncrBy(key, field string, incr int64) *IntCmd 129 HIncrByFloat(key, field string, incr float64) *FloatCmd 130 HKeys(key string) *StringSliceCmd 131 HLen(key string) *IntCmd 132 HMGet(key string, fields ...string) *SliceCmd 133 HSet(key string, values ...interface{}) *IntCmd 134 HMSet(key string, values ...interface{}) *BoolCmd 135 HSetNX(key, field string, value interface{}) *BoolCmd 136 HVals(key string) *StringSliceCmd 137 BLPop(timeout time.Duration, keys ...string) *StringSliceCmd 138 BRPop(timeout time.Duration, keys ...string) *StringSliceCmd 139 BRPopLPush(source, destination string, timeout time.Duration) *StringCmd 140 LIndex(key string, index int64) *StringCmd 141 LInsert(key, op string, pivot, value interface{}) *IntCmd 142 LInsertBefore(key string, pivot, value interface{}) *IntCmd 143 LInsertAfter(key string, pivot, value interface{}) *IntCmd 144 LLen(key string) *IntCmd 145 LPop(key string) *StringCmd 146 LPush(key string, values ...interface{}) *IntCmd 147 LPushX(key string, values ...interface{}) *IntCmd 148 LRange(key string, start, stop int64) *StringSliceCmd 149 LRem(key string, count int64, value interface{}) *IntCmd 150 LSet(key string, index int64, value interface{}) *StatusCmd 151 LTrim(key string, start, stop int64) *StatusCmd 152 RPop(key string) *StringCmd 153 RPopLPush(source, destination string) *StringCmd 154 RPush(key string, values ...interface{}) *IntCmd 155 RPushX(key string, values ...interface{}) *IntCmd 156 SAdd(key string, members ...interface{}) *IntCmd 157 SCard(key string) *IntCmd 158 SDiff(keys ...string) *StringSliceCmd 159 SDiffStore(destination string, keys ...string) *IntCmd 160 SInter(keys ...string) *StringSliceCmd 161 SInterStore(destination string, keys ...string) *IntCmd 162 SIsMember(key string, member interface{}) *BoolCmd 163 SMembers(key string) *StringSliceCmd 164 SMembersMap(key string) *StringStructMapCmd 165 SMove(source, destination string, member interface{}) *BoolCmd 166 SPop(key string) *StringCmd 167 SPopN(key string, count int64) *StringSliceCmd 168 SRandMember(key string) *StringCmd 169 SRandMemberN(key string, count int64) *StringSliceCmd 170 SRem(key string, members ...interface{}) *IntCmd 171 SUnion(keys ...string) *StringSliceCmd 172 SUnionStore(destination string, keys ...string) *IntCmd 173 XAdd(a *XAddArgs) *StringCmd 174 XDel(stream string, ids ...string) *IntCmd 175 XLen(stream string) *IntCmd 176 XRange(stream, start, stop string) *XMessageSliceCmd 177 XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd 178 XRevRange(stream string, start, stop string) *XMessageSliceCmd 179 XRevRangeN(stream string, start, stop string, count int64) *XMessageSliceCmd 180 XRead(a *XReadArgs) *XStreamSliceCmd 181 XReadStreams(streams ...string) *XStreamSliceCmd 182 XGroupCreate(stream, group, start string) *StatusCmd 183 XGroupCreateMkStream(stream, group, start string) *StatusCmd 184 XGroupSetID(stream, group, start string) *StatusCmd 185 XGroupDestroy(stream, group string) *IntCmd 186 XGroupDelConsumer(stream, group, consumer string) *IntCmd 187 XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd 188 XAck(stream, group string, ids ...string) *IntCmd 189 XPending(stream, group string) *XPendingCmd 190 XPendingExt(a *XPendingExtArgs) *XPendingExtCmd 191 XClaim(a *XClaimArgs) *XMessageSliceCmd 192 XClaimJustID(a *XClaimArgs) *StringSliceCmd 193 XTrim(key string, maxLen int64) *IntCmd 194 XTrimApprox(key string, maxLen int64) *IntCmd 195 XInfoGroups(key string) *XInfoGroupsCmd 196 BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd 197 BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd 198 ZAdd(key string, members ...*Z) *IntCmd 199 ZAddNX(key string, members ...*Z) *IntCmd 200 ZAddXX(key string, members ...*Z) *IntCmd 201 ZAddCh(key string, members ...*Z) *IntCmd 202 ZAddNXCh(key string, members ...*Z) *IntCmd 203 ZAddXXCh(key string, members ...*Z) *IntCmd 204 ZIncr(key string, member *Z) *FloatCmd 205 ZIncrNX(key string, member *Z) *FloatCmd 206 ZIncrXX(key string, member *Z) *FloatCmd 207 ZCard(key string) *IntCmd 208 ZCount(key, min, max string) *IntCmd 209 ZLexCount(key, min, max string) *IntCmd 210 ZIncrBy(key string, increment float64, member string) *FloatCmd 211 ZInterStore(destination string, store *ZStore) *IntCmd 212 ZPopMax(key string, count ...int64) *ZSliceCmd 213 ZPopMin(key string, count ...int64) *ZSliceCmd 214 ZRange(key string, start, stop int64) *StringSliceCmd 215 ZRangeWithScores(key string, start, stop int64) *ZSliceCmd 216 ZRangeByScore(key string, opt *ZRangeBy) *StringSliceCmd 217 ZRangeByLex(key string, opt *ZRangeBy) *StringSliceCmd 218 ZRangeByScoreWithScores(key string, opt *ZRangeBy) *ZSliceCmd 219 ZRank(key, member string) *IntCmd 220 ZRem(key string, members ...interface{}) *IntCmd 221 ZRemRangeByRank(key string, start, stop int64) *IntCmd 222 ZRemRangeByScore(key, min, max string) *IntCmd 223 ZRemRangeByLex(key, min, max string) *IntCmd 224 ZRevRange(key string, start, stop int64) *StringSliceCmd 225 ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd 226 ZRevRangeByScore(key string, opt *ZRangeBy) *StringSliceCmd 227 ZRevRangeByLex(key string, opt *ZRangeBy) *StringSliceCmd 228 ZRevRangeByScoreWithScores(key string, opt *ZRangeBy) *ZSliceCmd 229 ZRevRank(key, member string) *IntCmd 230 ZScore(key, member string) *FloatCmd 231 ZUnionStore(dest string, store *ZStore) *IntCmd 232 PFAdd(key string, els ...interface{}) *IntCmd 233 PFCount(keys ...string) *IntCmd 234 PFMerge(dest string, keys ...string) *StatusCmd 235 BgRewriteAOF() *StatusCmd 236 BgSave() *StatusCmd 237 ClientKill(ipPort string) *StatusCmd 238 ClientKillByFilter(keys ...string) *IntCmd 239 ClientList() *StringCmd 240 ClientPause(dur time.Duration) *BoolCmd 241 ClientID() *IntCmd 242 ConfigGet(parameter string) *SliceCmd 243 ConfigResetStat() *StatusCmd 244 ConfigSet(parameter, value string) *StatusCmd 245 ConfigRewrite() *StatusCmd 246 DBSize() *IntCmd 247 FlushAll() *StatusCmd 248 FlushAllAsync() *StatusCmd 249 FlushDB() *StatusCmd 250 FlushDBAsync() *StatusCmd 251 Info(section ...string) *StringCmd 252 LastSave() *IntCmd 253 Save() *StatusCmd 254 Shutdown() *StatusCmd 255 ShutdownSave() *StatusCmd 256 ShutdownNoSave() *StatusCmd 257 SlaveOf(host, port string) *StatusCmd 258 Time() *TimeCmd 259 Eval(script string, keys []string, args ...interface{}) *Cmd 260 EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd 261 ScriptExists(hashes ...string) *BoolSliceCmd 262 ScriptFlush() *StatusCmd 263 ScriptKill() *StatusCmd 264 ScriptLoad(script string) *StringCmd 265 DebugObject(key string) *StringCmd 266 Publish(channel string, message interface{}) *IntCmd 267 PubSubChannels(pattern string) *StringSliceCmd 268 PubSubNumSub(channels ...string) *StringIntMapCmd 269 PubSubNumPat() *IntCmd 270 ClusterSlots() *ClusterSlotsCmd 271 ClusterNodes() *StringCmd 272 ClusterMeet(host, port string) *StatusCmd 273 ClusterForget(nodeID string) *StatusCmd 274 ClusterReplicate(nodeID string) *StatusCmd 275 ClusterResetSoft() *StatusCmd 276 ClusterResetHard() *StatusCmd 277 ClusterInfo() *StringCmd 278 ClusterKeySlot(key string) *IntCmd 279 ClusterGetKeysInSlot(slot int, count int) *StringSliceCmd 280 ClusterCountFailureReports(nodeID string) *IntCmd 281 ClusterCountKeysInSlot(slot int) *IntCmd 282 ClusterDelSlots(slots ...int) *StatusCmd 283 ClusterDelSlotsRange(min, max int) *StatusCmd 284 ClusterSaveConfig() *StatusCmd 285 ClusterSlaves(nodeID string) *StringSliceCmd 286 ClusterFailover() *StatusCmd 287 ClusterAddSlots(slots ...int) *StatusCmd 288 ClusterAddSlotsRange(min, max int) *StatusCmd 289 GeoAdd(key string, geoLocation ...*GeoLocation) *IntCmd 290 GeoPos(key string, members ...string) *GeoPosCmd 291 GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd 292 GeoRadiusStore(key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd 293 GeoRadiusByMember(key, member string, query *GeoRadiusQuery) *GeoLocationCmd 294 GeoRadiusByMemberStore(key, member string, query *GeoRadiusQuery) *IntCmd 295 GeoDist(key string, member1, member2, unit string) *FloatCmd 296 GeoHash(key string, members ...string) *StringSliceCmd 297 ReadOnly() *StatusCmd 298 ReadWrite() *StatusCmd 299 MemoryUsage(key string, samples ...int) *IntCmd 300} 301 302type StatefulCmdable interface { 303 Cmdable 304 Auth(password string) *StatusCmd 305 Select(index int) *StatusCmd 306 SwapDB(index1, index2 int) *StatusCmd 307 ClientSetName(name string) *BoolCmd 308} 309 310var _ Cmdable = (*Client)(nil) 311var _ Cmdable = (*Tx)(nil) 312var _ Cmdable = (*Ring)(nil) 313var _ Cmdable = (*ClusterClient)(nil) 314 315type cmdable func(cmd Cmder) error 316 317type statefulCmdable func(cmd Cmder) error 318 319//------------------------------------------------------------------------------ 320 321func (c statefulCmdable) Auth(password string) *StatusCmd { 322 cmd := NewStatusCmd("auth", password) 323 _ = c(cmd) 324 return cmd 325} 326 327func (c cmdable) Echo(message interface{}) *StringCmd { 328 cmd := NewStringCmd("echo", message) 329 _ = c(cmd) 330 return cmd 331} 332 333func (c cmdable) Ping() *StatusCmd { 334 cmd := NewStatusCmd("ping") 335 _ = c(cmd) 336 return cmd 337} 338 339func (c cmdable) Wait(numSlaves int, timeout time.Duration) *IntCmd { 340 cmd := NewIntCmd("wait", numSlaves, int(timeout/time.Millisecond)) 341 _ = c(cmd) 342 return cmd 343} 344 345func (c cmdable) Quit() *StatusCmd { 346 panic("not implemented") 347} 348 349func (c statefulCmdable) Select(index int) *StatusCmd { 350 cmd := NewStatusCmd("select", index) 351 _ = c(cmd) 352 return cmd 353} 354 355func (c statefulCmdable) SwapDB(index1, index2 int) *StatusCmd { 356 cmd := NewStatusCmd("swapdb", index1, index2) 357 _ = c(cmd) 358 return cmd 359} 360 361//------------------------------------------------------------------------------ 362 363func (c cmdable) Command() *CommandsInfoCmd { 364 cmd := NewCommandsInfoCmd("command") 365 _ = c(cmd) 366 return cmd 367} 368 369func (c cmdable) Del(keys ...string) *IntCmd { 370 args := make([]interface{}, 1+len(keys)) 371 args[0] = "del" 372 for i, key := range keys { 373 args[1+i] = key 374 } 375 cmd := NewIntCmd(args...) 376 _ = c(cmd) 377 return cmd 378} 379 380func (c cmdable) Unlink(keys ...string) *IntCmd { 381 args := make([]interface{}, 1+len(keys)) 382 args[0] = "unlink" 383 for i, key := range keys { 384 args[1+i] = key 385 } 386 cmd := NewIntCmd(args...) 387 _ = c(cmd) 388 return cmd 389} 390 391func (c cmdable) Dump(key string) *StringCmd { 392 cmd := NewStringCmd("dump", key) 393 _ = c(cmd) 394 return cmd 395} 396 397func (c cmdable) Exists(keys ...string) *IntCmd { 398 args := make([]interface{}, 1+len(keys)) 399 args[0] = "exists" 400 for i, key := range keys { 401 args[1+i] = key 402 } 403 cmd := NewIntCmd(args...) 404 _ = c(cmd) 405 return cmd 406} 407 408func (c cmdable) Expire(key string, expiration time.Duration) *BoolCmd { 409 cmd := NewBoolCmd("expire", key, formatSec(expiration)) 410 _ = c(cmd) 411 return cmd 412} 413 414func (c cmdable) ExpireAt(key string, tm time.Time) *BoolCmd { 415 cmd := NewBoolCmd("expireat", key, tm.Unix()) 416 _ = c(cmd) 417 return cmd 418} 419 420func (c cmdable) Keys(pattern string) *StringSliceCmd { 421 cmd := NewStringSliceCmd("keys", pattern) 422 _ = c(cmd) 423 return cmd 424} 425 426func (c cmdable) Migrate(host, port, key string, db int, timeout time.Duration) *StatusCmd { 427 cmd := NewStatusCmd( 428 "migrate", 429 host, 430 port, 431 key, 432 db, 433 formatMs(timeout), 434 ) 435 cmd.setReadTimeout(timeout) 436 _ = c(cmd) 437 return cmd 438} 439 440func (c cmdable) Move(key string, db int) *BoolCmd { 441 cmd := NewBoolCmd("move", key, db) 442 _ = c(cmd) 443 return cmd 444} 445 446func (c cmdable) ObjectRefCount(key string) *IntCmd { 447 cmd := NewIntCmd("object", "refcount", key) 448 _ = c(cmd) 449 return cmd 450} 451 452func (c cmdable) ObjectEncoding(key string) *StringCmd { 453 cmd := NewStringCmd("object", "encoding", key) 454 _ = c(cmd) 455 return cmd 456} 457 458func (c cmdable) ObjectIdleTime(key string) *DurationCmd { 459 cmd := NewDurationCmd(time.Second, "object", "idletime", key) 460 _ = c(cmd) 461 return cmd 462} 463 464func (c cmdable) Persist(key string) *BoolCmd { 465 cmd := NewBoolCmd("persist", key) 466 _ = c(cmd) 467 return cmd 468} 469 470func (c cmdable) PExpire(key string, expiration time.Duration) *BoolCmd { 471 cmd := NewBoolCmd("pexpire", key, formatMs(expiration)) 472 _ = c(cmd) 473 return cmd 474} 475 476func (c cmdable) PExpireAt(key string, tm time.Time) *BoolCmd { 477 cmd := NewBoolCmd( 478 "pexpireat", 479 key, 480 tm.UnixNano()/int64(time.Millisecond), 481 ) 482 _ = c(cmd) 483 return cmd 484} 485 486func (c cmdable) PTTL(key string) *DurationCmd { 487 cmd := NewDurationCmd(time.Millisecond, "pttl", key) 488 _ = c(cmd) 489 return cmd 490} 491 492func (c cmdable) RandomKey() *StringCmd { 493 cmd := NewStringCmd("randomkey") 494 _ = c(cmd) 495 return cmd 496} 497 498func (c cmdable) Rename(key, newkey string) *StatusCmd { 499 cmd := NewStatusCmd("rename", key, newkey) 500 _ = c(cmd) 501 return cmd 502} 503 504func (c cmdable) RenameNX(key, newkey string) *BoolCmd { 505 cmd := NewBoolCmd("renamenx", key, newkey) 506 _ = c(cmd) 507 return cmd 508} 509 510func (c cmdable) Restore(key string, ttl time.Duration, value string) *StatusCmd { 511 cmd := NewStatusCmd( 512 "restore", 513 key, 514 formatMs(ttl), 515 value, 516 ) 517 _ = c(cmd) 518 return cmd 519} 520 521func (c cmdable) RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd { 522 cmd := NewStatusCmd( 523 "restore", 524 key, 525 formatMs(ttl), 526 value, 527 "replace", 528 ) 529 _ = c(cmd) 530 return cmd 531} 532 533type Sort struct { 534 By string 535 Offset, Count int64 536 Get []string 537 Order string 538 Alpha bool 539} 540 541func (sort *Sort) args(key string) []interface{} { 542 args := []interface{}{"sort", key} 543 if sort.By != "" { 544 args = append(args, "by", sort.By) 545 } 546 if sort.Offset != 0 || sort.Count != 0 { 547 args = append(args, "limit", sort.Offset, sort.Count) 548 } 549 for _, get := range sort.Get { 550 args = append(args, "get", get) 551 } 552 if sort.Order != "" { 553 args = append(args, sort.Order) 554 } 555 if sort.Alpha { 556 args = append(args, "alpha") 557 } 558 return args 559} 560 561func (c cmdable) Sort(key string, sort *Sort) *StringSliceCmd { 562 cmd := NewStringSliceCmd(sort.args(key)...) 563 _ = c(cmd) 564 return cmd 565} 566 567func (c cmdable) SortStore(key, store string, sort *Sort) *IntCmd { 568 args := sort.args(key) 569 if store != "" { 570 args = append(args, "store", store) 571 } 572 cmd := NewIntCmd(args...) 573 _ = c(cmd) 574 return cmd 575} 576 577func (c cmdable) SortInterfaces(key string, sort *Sort) *SliceCmd { 578 cmd := NewSliceCmd(sort.args(key)...) 579 _ = c(cmd) 580 return cmd 581} 582 583func (c cmdable) Touch(keys ...string) *IntCmd { 584 args := make([]interface{}, len(keys)+1) 585 args[0] = "touch" 586 for i, key := range keys { 587 args[i+1] = key 588 } 589 cmd := NewIntCmd(args...) 590 _ = c(cmd) 591 return cmd 592} 593 594func (c cmdable) TTL(key string) *DurationCmd { 595 cmd := NewDurationCmd(time.Second, "ttl", key) 596 _ = c(cmd) 597 return cmd 598} 599 600func (c cmdable) Type(key string) *StatusCmd { 601 cmd := NewStatusCmd("type", key) 602 _ = c(cmd) 603 return cmd 604} 605 606func (c cmdable) Scan(cursor uint64, match string, count int64) *ScanCmd { 607 args := []interface{}{"scan", cursor} 608 if match != "" { 609 args = append(args, "match", match) 610 } 611 if count > 0 { 612 args = append(args, "count", count) 613 } 614 cmd := NewScanCmd(c, args...) 615 _ = c(cmd) 616 return cmd 617} 618 619func (c cmdable) SScan(key string, cursor uint64, match string, count int64) *ScanCmd { 620 args := []interface{}{"sscan", key, cursor} 621 if match != "" { 622 args = append(args, "match", match) 623 } 624 if count > 0 { 625 args = append(args, "count", count) 626 } 627 cmd := NewScanCmd(c, args...) 628 _ = c(cmd) 629 return cmd 630} 631 632func (c cmdable) HScan(key string, cursor uint64, match string, count int64) *ScanCmd { 633 args := []interface{}{"hscan", key, cursor} 634 if match != "" { 635 args = append(args, "match", match) 636 } 637 if count > 0 { 638 args = append(args, "count", count) 639 } 640 cmd := NewScanCmd(c, args...) 641 _ = c(cmd) 642 return cmd 643} 644 645func (c cmdable) ZScan(key string, cursor uint64, match string, count int64) *ScanCmd { 646 args := []interface{}{"zscan", key, cursor} 647 if match != "" { 648 args = append(args, "match", match) 649 } 650 if count > 0 { 651 args = append(args, "count", count) 652 } 653 cmd := NewScanCmd(c, args...) 654 _ = c(cmd) 655 return cmd 656} 657 658//------------------------------------------------------------------------------ 659 660func (c cmdable) Append(key, value string) *IntCmd { 661 cmd := NewIntCmd("append", key, value) 662 _ = c(cmd) 663 return cmd 664} 665 666type BitCount struct { 667 Start, End int64 668} 669 670func (c cmdable) BitCount(key string, bitCount *BitCount) *IntCmd { 671 args := []interface{}{"bitcount", key} 672 if bitCount != nil { 673 args = append( 674 args, 675 bitCount.Start, 676 bitCount.End, 677 ) 678 } 679 cmd := NewIntCmd(args...) 680 _ = c(cmd) 681 return cmd 682} 683 684func (c cmdable) bitOp(op, destKey string, keys ...string) *IntCmd { 685 args := make([]interface{}, 3+len(keys)) 686 args[0] = "bitop" 687 args[1] = op 688 args[2] = destKey 689 for i, key := range keys { 690 args[3+i] = key 691 } 692 cmd := NewIntCmd(args...) 693 _ = c(cmd) 694 return cmd 695} 696 697func (c cmdable) BitOpAnd(destKey string, keys ...string) *IntCmd { 698 return c.bitOp("and", destKey, keys...) 699} 700 701func (c cmdable) BitOpOr(destKey string, keys ...string) *IntCmd { 702 return c.bitOp("or", destKey, keys...) 703} 704 705func (c cmdable) BitOpXor(destKey string, keys ...string) *IntCmd { 706 return c.bitOp("xor", destKey, keys...) 707} 708 709func (c cmdable) BitOpNot(destKey string, key string) *IntCmd { 710 return c.bitOp("not", destKey, key) 711} 712 713func (c cmdable) BitPos(key string, bit int64, pos ...int64) *IntCmd { 714 args := make([]interface{}, 3+len(pos)) 715 args[0] = "bitpos" 716 args[1] = key 717 args[2] = bit 718 switch len(pos) { 719 case 0: 720 case 1: 721 args[3] = pos[0] 722 case 2: 723 args[3] = pos[0] 724 args[4] = pos[1] 725 default: 726 panic("too many arguments") 727 } 728 cmd := NewIntCmd(args...) 729 _ = c(cmd) 730 return cmd 731} 732 733func (c cmdable) BitField(key string, args ...interface{}) *IntSliceCmd { 734 a := make([]interface{}, 0, 2+len(args)) 735 a = append(a, "bitfield") 736 a = append(a, key) 737 a = append(a, args...) 738 cmd := NewIntSliceCmd(a...) 739 _ = c(cmd) 740 return cmd 741} 742 743func (c cmdable) Decr(key string) *IntCmd { 744 cmd := NewIntCmd("decr", key) 745 _ = c(cmd) 746 return cmd 747} 748 749func (c cmdable) DecrBy(key string, decrement int64) *IntCmd { 750 cmd := NewIntCmd("decrby", key, decrement) 751 _ = c(cmd) 752 return cmd 753} 754 755// Redis `GET key` command. It returns redis.Nil error when key does not exist. 756func (c cmdable) Get(key string) *StringCmd { 757 cmd := NewStringCmd("get", key) 758 _ = c(cmd) 759 return cmd 760} 761 762func (c cmdable) GetBit(key string, offset int64) *IntCmd { 763 cmd := NewIntCmd("getbit", key, offset) 764 _ = c(cmd) 765 return cmd 766} 767 768func (c cmdable) GetRange(key string, start, end int64) *StringCmd { 769 cmd := NewStringCmd("getrange", key, start, end) 770 _ = c(cmd) 771 return cmd 772} 773 774func (c cmdable) GetSet(key string, value interface{}) *StringCmd { 775 cmd := NewStringCmd("getset", key, value) 776 _ = c(cmd) 777 return cmd 778} 779 780func (c cmdable) Incr(key string) *IntCmd { 781 cmd := NewIntCmd("incr", key) 782 _ = c(cmd) 783 return cmd 784} 785 786func (c cmdable) IncrBy(key string, value int64) *IntCmd { 787 cmd := NewIntCmd("incrby", key, value) 788 _ = c(cmd) 789 return cmd 790} 791 792func (c cmdable) IncrByFloat(key string, value float64) *FloatCmd { 793 cmd := NewFloatCmd("incrbyfloat", key, value) 794 _ = c(cmd) 795 return cmd 796} 797 798func (c cmdable) MGet(keys ...string) *SliceCmd { 799 args := make([]interface{}, 1+len(keys)) 800 args[0] = "mget" 801 for i, key := range keys { 802 args[1+i] = key 803 } 804 cmd := NewSliceCmd(args...) 805 _ = c(cmd) 806 return cmd 807} 808 809// MSet is like Set but accepts multiple values: 810// - MSet("key1", "value1", "key2", "value2") 811// - MSet([]string{"key1", "value1", "key2", "value2"}) 812// - MSet(map[string]interface{}{"key1": "value1", "key2": "value2"}) 813func (c cmdable) MSet(values ...interface{}) *StatusCmd { 814 args := make([]interface{}, 1, 1+len(values)) 815 args[0] = "mset" 816 args = appendArgs(args, values) 817 cmd := NewStatusCmd(args...) 818 _ = c(cmd) 819 return cmd 820} 821 822// MSetNX is like SetNX but accepts multiple values: 823// - MSetNX("key1", "value1", "key2", "value2") 824// - MSetNX([]string{"key1", "value1", "key2", "value2"}) 825// - MSetNX(map[string]interface{}{"key1": "value1", "key2": "value2"}) 826func (c cmdable) MSetNX(values ...interface{}) *BoolCmd { 827 args := make([]interface{}, 1, 1+len(values)) 828 args[0] = "msetnx" 829 args = appendArgs(args, values) 830 cmd := NewBoolCmd(args...) 831 _ = c(cmd) 832 return cmd 833} 834 835// Redis `SET key value [expiration]` command. 836// 837// Use expiration for `SETEX`-like behavior. 838// Zero expiration means the key has no expiration time. 839func (c cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd { 840 args := make([]interface{}, 3, 5) 841 args[0] = "set" 842 args[1] = key 843 args[2] = value 844 if expiration > 0 { 845 if usePrecise(expiration) { 846 args = append(args, "px", formatMs(expiration)) 847 } else { 848 args = append(args, "ex", formatSec(expiration)) 849 } 850 } 851 cmd := NewStatusCmd(args...) 852 _ = c(cmd) 853 return cmd 854} 855 856func (c cmdable) SetBit(key string, offset int64, value int) *IntCmd { 857 cmd := NewIntCmd( 858 "setbit", 859 key, 860 offset, 861 value, 862 ) 863 _ = c(cmd) 864 return cmd 865} 866 867// Redis `SET key value [expiration] NX` command. 868// 869// Zero expiration means the key has no expiration time. 870func (c cmdable) SetNX(key string, value interface{}, expiration time.Duration) *BoolCmd { 871 var cmd *BoolCmd 872 if expiration == 0 { 873 // Use old `SETNX` to support old Redis versions. 874 cmd = NewBoolCmd("setnx", key, value) 875 } else { 876 if usePrecise(expiration) { 877 cmd = NewBoolCmd("set", key, value, "px", formatMs(expiration), "nx") 878 } else { 879 cmd = NewBoolCmd("set", key, value, "ex", formatSec(expiration), "nx") 880 } 881 } 882 _ = c(cmd) 883 return cmd 884} 885 886// Redis `SET key value [expiration] XX` command. 887// 888// Zero expiration means the key has no expiration time. 889func (c cmdable) SetXX(key string, value interface{}, expiration time.Duration) *BoolCmd { 890 var cmd *BoolCmd 891 if expiration == 0 { 892 cmd = NewBoolCmd("set", key, value, "xx") 893 } else { 894 if usePrecise(expiration) { 895 cmd = NewBoolCmd("set", key, value, "px", formatMs(expiration), "xx") 896 } else { 897 cmd = NewBoolCmd("set", key, value, "ex", formatSec(expiration), "xx") 898 } 899 } 900 _ = c(cmd) 901 return cmd 902} 903 904func (c cmdable) SetRange(key string, offset int64, value string) *IntCmd { 905 cmd := NewIntCmd("setrange", key, offset, value) 906 _ = c(cmd) 907 return cmd 908} 909 910func (c cmdable) StrLen(key string) *IntCmd { 911 cmd := NewIntCmd("strlen", key) 912 _ = c(cmd) 913 return cmd 914} 915 916//------------------------------------------------------------------------------ 917 918func (c cmdable) HDel(key string, fields ...string) *IntCmd { 919 args := make([]interface{}, 2+len(fields)) 920 args[0] = "hdel" 921 args[1] = key 922 for i, field := range fields { 923 args[2+i] = field 924 } 925 cmd := NewIntCmd(args...) 926 _ = c(cmd) 927 return cmd 928} 929 930func (c cmdable) HExists(key, field string) *BoolCmd { 931 cmd := NewBoolCmd("hexists", key, field) 932 _ = c(cmd) 933 return cmd 934} 935 936func (c cmdable) HGet(key, field string) *StringCmd { 937 cmd := NewStringCmd("hget", key, field) 938 _ = c(cmd) 939 return cmd 940} 941 942func (c cmdable) HGetAll(key string) *StringStringMapCmd { 943 cmd := NewStringStringMapCmd("hgetall", key) 944 _ = c(cmd) 945 return cmd 946} 947 948func (c cmdable) HIncrBy(key, field string, incr int64) *IntCmd { 949 cmd := NewIntCmd("hincrby", key, field, incr) 950 _ = c(cmd) 951 return cmd 952} 953 954func (c cmdable) HIncrByFloat(key, field string, incr float64) *FloatCmd { 955 cmd := NewFloatCmd("hincrbyfloat", key, field, incr) 956 _ = c(cmd) 957 return cmd 958} 959 960func (c cmdable) HKeys(key string) *StringSliceCmd { 961 cmd := NewStringSliceCmd("hkeys", key) 962 _ = c(cmd) 963 return cmd 964} 965 966func (c cmdable) HLen(key string) *IntCmd { 967 cmd := NewIntCmd("hlen", key) 968 _ = c(cmd) 969 return cmd 970} 971 972// HMGet returns the values for the specified fields in the hash stored at key. 973// It returns an interface{} to distinguish between empty string and nil value. 974func (c cmdable) HMGet(key string, fields ...string) *SliceCmd { 975 args := make([]interface{}, 2+len(fields)) 976 args[0] = "hmget" 977 args[1] = key 978 for i, field := range fields { 979 args[2+i] = field 980 } 981 cmd := NewSliceCmd(args...) 982 _ = c(cmd) 983 return cmd 984} 985 986// HSet accepts values in following formats: 987// - HMSet("myhash", "key1", "value1", "key2", "value2") 988// - HMSet("myhash", []string{"key1", "value1", "key2", "value2"}) 989// - HMSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"}) 990// 991// Note that it requires Redis v4 for multiple field/value pairs support. 992func (c cmdable) HSet(key string, values ...interface{}) *IntCmd { 993 args := make([]interface{}, 2, 2+len(values)) 994 args[0] = "hset" 995 args[1] = key 996 args = appendArgs(args, values) 997 cmd := NewIntCmd(args...) 998 _ = c(cmd) 999 return cmd 1000} 1001 1002// HMSet is a deprecated version of HSet left for compatibility with Redis 3. 1003func (c cmdable) HMSet(key string, values ...interface{}) *BoolCmd { 1004 args := make([]interface{}, 2, 2+len(values)) 1005 args[0] = "hmset" 1006 args[1] = key 1007 args = appendArgs(args, values) 1008 cmd := NewBoolCmd(args...) 1009 _ = c(cmd) 1010 return cmd 1011} 1012 1013func (c cmdable) HSetNX(key, field string, value interface{}) *BoolCmd { 1014 cmd := NewBoolCmd("hsetnx", key, field, value) 1015 _ = c(cmd) 1016 return cmd 1017} 1018 1019func (c cmdable) HVals(key string) *StringSliceCmd { 1020 cmd := NewStringSliceCmd("hvals", key) 1021 _ = c(cmd) 1022 return cmd 1023} 1024 1025//------------------------------------------------------------------------------ 1026 1027func (c cmdable) BLPop(timeout time.Duration, keys ...string) *StringSliceCmd { 1028 args := make([]interface{}, 1+len(keys)+1) 1029 args[0] = "blpop" 1030 for i, key := range keys { 1031 args[1+i] = key 1032 } 1033 args[len(args)-1] = formatSec(timeout) 1034 cmd := NewStringSliceCmd(args...) 1035 cmd.setReadTimeout(timeout) 1036 _ = c(cmd) 1037 return cmd 1038} 1039 1040func (c cmdable) BRPop(timeout time.Duration, keys ...string) *StringSliceCmd { 1041 args := make([]interface{}, 1+len(keys)+1) 1042 args[0] = "brpop" 1043 for i, key := range keys { 1044 args[1+i] = key 1045 } 1046 args[len(keys)+1] = formatSec(timeout) 1047 cmd := NewStringSliceCmd(args...) 1048 cmd.setReadTimeout(timeout) 1049 _ = c(cmd) 1050 return cmd 1051} 1052 1053func (c cmdable) BRPopLPush(source, destination string, timeout time.Duration) *StringCmd { 1054 cmd := NewStringCmd( 1055 "brpoplpush", 1056 source, 1057 destination, 1058 formatSec(timeout), 1059 ) 1060 cmd.setReadTimeout(timeout) 1061 _ = c(cmd) 1062 return cmd 1063} 1064 1065func (c cmdable) LIndex(key string, index int64) *StringCmd { 1066 cmd := NewStringCmd("lindex", key, index) 1067 _ = c(cmd) 1068 return cmd 1069} 1070 1071func (c cmdable) LInsert(key, op string, pivot, value interface{}) *IntCmd { 1072 cmd := NewIntCmd("linsert", key, op, pivot, value) 1073 _ = c(cmd) 1074 return cmd 1075} 1076 1077func (c cmdable) LInsertBefore(key string, pivot, value interface{}) *IntCmd { 1078 cmd := NewIntCmd("linsert", key, "before", pivot, value) 1079 _ = c(cmd) 1080 return cmd 1081} 1082 1083func (c cmdable) LInsertAfter(key string, pivot, value interface{}) *IntCmd { 1084 cmd := NewIntCmd("linsert", key, "after", pivot, value) 1085 _ = c(cmd) 1086 return cmd 1087} 1088 1089func (c cmdable) LLen(key string) *IntCmd { 1090 cmd := NewIntCmd("llen", key) 1091 _ = c(cmd) 1092 return cmd 1093} 1094 1095func (c cmdable) LPop(key string) *StringCmd { 1096 cmd := NewStringCmd("lpop", key) 1097 _ = c(cmd) 1098 return cmd 1099} 1100 1101func (c cmdable) LPush(key string, values ...interface{}) *IntCmd { 1102 args := make([]interface{}, 2, 2+len(values)) 1103 args[0] = "lpush" 1104 args[1] = key 1105 args = appendArgs(args, values) 1106 cmd := NewIntCmd(args...) 1107 _ = c(cmd) 1108 return cmd 1109} 1110 1111func (c cmdable) LPushX(key string, values ...interface{}) *IntCmd { 1112 args := make([]interface{}, 2, 2+len(values)) 1113 args[0] = "lpushx" 1114 args[1] = key 1115 args = appendArgs(args, values) 1116 cmd := NewIntCmd(args...) 1117 _ = c(cmd) 1118 return cmd 1119} 1120 1121func (c cmdable) LRange(key string, start, stop int64) *StringSliceCmd { 1122 cmd := NewStringSliceCmd( 1123 "lrange", 1124 key, 1125 start, 1126 stop, 1127 ) 1128 _ = c(cmd) 1129 return cmd 1130} 1131 1132func (c cmdable) LRem(key string, count int64, value interface{}) *IntCmd { 1133 cmd := NewIntCmd("lrem", key, count, value) 1134 _ = c(cmd) 1135 return cmd 1136} 1137 1138func (c cmdable) LSet(key string, index int64, value interface{}) *StatusCmd { 1139 cmd := NewStatusCmd("lset", key, index, value) 1140 _ = c(cmd) 1141 return cmd 1142} 1143 1144func (c cmdable) LTrim(key string, start, stop int64) *StatusCmd { 1145 cmd := NewStatusCmd( 1146 "ltrim", 1147 key, 1148 start, 1149 stop, 1150 ) 1151 _ = c(cmd) 1152 return cmd 1153} 1154 1155func (c cmdable) RPop(key string) *StringCmd { 1156 cmd := NewStringCmd("rpop", key) 1157 _ = c(cmd) 1158 return cmd 1159} 1160 1161func (c cmdable) RPopLPush(source, destination string) *StringCmd { 1162 cmd := NewStringCmd("rpoplpush", source, destination) 1163 _ = c(cmd) 1164 return cmd 1165} 1166 1167func (c cmdable) RPush(key string, values ...interface{}) *IntCmd { 1168 args := make([]interface{}, 2, 2+len(values)) 1169 args[0] = "rpush" 1170 args[1] = key 1171 args = appendArgs(args, values) 1172 cmd := NewIntCmd(args...) 1173 _ = c(cmd) 1174 return cmd 1175} 1176 1177func (c cmdable) RPushX(key string, values ...interface{}) *IntCmd { 1178 args := make([]interface{}, 2, 2+len(values)) 1179 args[0] = "rpushx" 1180 args[1] = key 1181 args = appendArgs(args, values) 1182 cmd := NewIntCmd(args...) 1183 _ = c(cmd) 1184 return cmd 1185} 1186 1187//------------------------------------------------------------------------------ 1188 1189func (c cmdable) SAdd(key string, members ...interface{}) *IntCmd { 1190 args := make([]interface{}, 2, 2+len(members)) 1191 args[0] = "sadd" 1192 args[1] = key 1193 args = appendArgs(args, members) 1194 cmd := NewIntCmd(args...) 1195 _ = c(cmd) 1196 return cmd 1197} 1198 1199func (c cmdable) SCard(key string) *IntCmd { 1200 cmd := NewIntCmd("scard", key) 1201 _ = c(cmd) 1202 return cmd 1203} 1204 1205func (c cmdable) SDiff(keys ...string) *StringSliceCmd { 1206 args := make([]interface{}, 1+len(keys)) 1207 args[0] = "sdiff" 1208 for i, key := range keys { 1209 args[1+i] = key 1210 } 1211 cmd := NewStringSliceCmd(args...) 1212 _ = c(cmd) 1213 return cmd 1214} 1215 1216func (c cmdable) SDiffStore(destination string, keys ...string) *IntCmd { 1217 args := make([]interface{}, 2+len(keys)) 1218 args[0] = "sdiffstore" 1219 args[1] = destination 1220 for i, key := range keys { 1221 args[2+i] = key 1222 } 1223 cmd := NewIntCmd(args...) 1224 _ = c(cmd) 1225 return cmd 1226} 1227 1228func (c cmdable) SInter(keys ...string) *StringSliceCmd { 1229 args := make([]interface{}, 1+len(keys)) 1230 args[0] = "sinter" 1231 for i, key := range keys { 1232 args[1+i] = key 1233 } 1234 cmd := NewStringSliceCmd(args...) 1235 _ = c(cmd) 1236 return cmd 1237} 1238 1239func (c cmdable) SInterStore(destination string, keys ...string) *IntCmd { 1240 args := make([]interface{}, 2+len(keys)) 1241 args[0] = "sinterstore" 1242 args[1] = destination 1243 for i, key := range keys { 1244 args[2+i] = key 1245 } 1246 cmd := NewIntCmd(args...) 1247 _ = c(cmd) 1248 return cmd 1249} 1250 1251func (c cmdable) SIsMember(key string, member interface{}) *BoolCmd { 1252 cmd := NewBoolCmd("sismember", key, member) 1253 _ = c(cmd) 1254 return cmd 1255} 1256 1257// Redis `SMEMBERS key` command output as a slice 1258func (c cmdable) SMembers(key string) *StringSliceCmd { 1259 cmd := NewStringSliceCmd("smembers", key) 1260 _ = c(cmd) 1261 return cmd 1262} 1263 1264// Redis `SMEMBERS key` command output as a map 1265func (c cmdable) SMembersMap(key string) *StringStructMapCmd { 1266 cmd := NewStringStructMapCmd("smembers", key) 1267 _ = c(cmd) 1268 return cmd 1269} 1270 1271func (c cmdable) SMove(source, destination string, member interface{}) *BoolCmd { 1272 cmd := NewBoolCmd("smove", source, destination, member) 1273 _ = c(cmd) 1274 return cmd 1275} 1276 1277// Redis `SPOP key` command. 1278func (c cmdable) SPop(key string) *StringCmd { 1279 cmd := NewStringCmd("spop", key) 1280 _ = c(cmd) 1281 return cmd 1282} 1283 1284// Redis `SPOP key count` command. 1285func (c cmdable) SPopN(key string, count int64) *StringSliceCmd { 1286 cmd := NewStringSliceCmd("spop", key, count) 1287 _ = c(cmd) 1288 return cmd 1289} 1290 1291// Redis `SRANDMEMBER key` command. 1292func (c cmdable) SRandMember(key string) *StringCmd { 1293 cmd := NewStringCmd("srandmember", key) 1294 _ = c(cmd) 1295 return cmd 1296} 1297 1298// Redis `SRANDMEMBER key count` command. 1299func (c cmdable) SRandMemberN(key string, count int64) *StringSliceCmd { 1300 cmd := NewStringSliceCmd("srandmember", key, count) 1301 _ = c(cmd) 1302 return cmd 1303} 1304 1305func (c cmdable) SRem(key string, members ...interface{}) *IntCmd { 1306 args := make([]interface{}, 2, 2+len(members)) 1307 args[0] = "srem" 1308 args[1] = key 1309 args = appendArgs(args, members) 1310 cmd := NewIntCmd(args...) 1311 _ = c(cmd) 1312 return cmd 1313} 1314 1315func (c cmdable) SUnion(keys ...string) *StringSliceCmd { 1316 args := make([]interface{}, 1+len(keys)) 1317 args[0] = "sunion" 1318 for i, key := range keys { 1319 args[1+i] = key 1320 } 1321 cmd := NewStringSliceCmd(args...) 1322 _ = c(cmd) 1323 return cmd 1324} 1325 1326func (c cmdable) SUnionStore(destination string, keys ...string) *IntCmd { 1327 args := make([]interface{}, 2+len(keys)) 1328 args[0] = "sunionstore" 1329 args[1] = destination 1330 for i, key := range keys { 1331 args[2+i] = key 1332 } 1333 cmd := NewIntCmd(args...) 1334 _ = c(cmd) 1335 return cmd 1336} 1337 1338//------------------------------------------------------------------------------ 1339 1340type XAddArgs struct { 1341 Stream string 1342 MaxLen int64 // MAXLEN N 1343 MaxLenApprox int64 // MAXLEN ~ N 1344 ID string 1345 Values map[string]interface{} 1346} 1347 1348func (c cmdable) XAdd(a *XAddArgs) *StringCmd { 1349 args := make([]interface{}, 0, 6+len(a.Values)*2) 1350 args = append(args, "xadd") 1351 args = append(args, a.Stream) 1352 if a.MaxLen > 0 { 1353 args = append(args, "maxlen", a.MaxLen) 1354 } else if a.MaxLenApprox > 0 { 1355 args = append(args, "maxlen", "~", a.MaxLenApprox) 1356 } 1357 if a.ID != "" { 1358 args = append(args, a.ID) 1359 } else { 1360 args = append(args, "*") 1361 } 1362 for k, v := range a.Values { 1363 args = append(args, k) 1364 args = append(args, v) 1365 } 1366 1367 cmd := NewStringCmd(args...) 1368 _ = c(cmd) 1369 return cmd 1370} 1371 1372func (c cmdable) XDel(stream string, ids ...string) *IntCmd { 1373 args := []interface{}{"xdel", stream} 1374 for _, id := range ids { 1375 args = append(args, id) 1376 } 1377 cmd := NewIntCmd(args...) 1378 _ = c(cmd) 1379 return cmd 1380} 1381 1382func (c cmdable) XLen(stream string) *IntCmd { 1383 cmd := NewIntCmd("xlen", stream) 1384 _ = c(cmd) 1385 return cmd 1386} 1387 1388func (c cmdable) XRange(stream, start, stop string) *XMessageSliceCmd { 1389 cmd := NewXMessageSliceCmd("xrange", stream, start, stop) 1390 _ = c(cmd) 1391 return cmd 1392} 1393 1394func (c cmdable) XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { 1395 cmd := NewXMessageSliceCmd("xrange", stream, start, stop, "count", count) 1396 _ = c(cmd) 1397 return cmd 1398} 1399 1400func (c cmdable) XRevRange(stream, start, stop string) *XMessageSliceCmd { 1401 cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop) 1402 _ = c(cmd) 1403 return cmd 1404} 1405 1406func (c cmdable) XRevRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { 1407 cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop, "count", count) 1408 _ = c(cmd) 1409 return cmd 1410} 1411 1412type XReadArgs struct { 1413 Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2 1414 Count int64 1415 Block time.Duration 1416} 1417 1418func (c cmdable) XRead(a *XReadArgs) *XStreamSliceCmd { 1419 args := make([]interface{}, 0, 5+len(a.Streams)) 1420 args = append(args, "xread") 1421 if a.Count > 0 { 1422 args = append(args, "count") 1423 args = append(args, a.Count) 1424 } 1425 if a.Block >= 0 { 1426 args = append(args, "block") 1427 args = append(args, int64(a.Block/time.Millisecond)) 1428 } 1429 1430 args = append(args, "streams") 1431 for _, s := range a.Streams { 1432 args = append(args, s) 1433 } 1434 1435 cmd := NewXStreamSliceCmd(args...) 1436 if a.Block >= 0 { 1437 cmd.setReadTimeout(a.Block) 1438 } 1439 _ = c(cmd) 1440 return cmd 1441} 1442 1443func (c cmdable) XReadStreams(streams ...string) *XStreamSliceCmd { 1444 return c.XRead(&XReadArgs{ 1445 Streams: streams, 1446 Block: -1, 1447 }) 1448} 1449 1450func (c cmdable) XGroupCreate(stream, group, start string) *StatusCmd { 1451 cmd := NewStatusCmd("xgroup", "create", stream, group, start) 1452 _ = c(cmd) 1453 return cmd 1454} 1455 1456func (c cmdable) XGroupCreateMkStream(stream, group, start string) *StatusCmd { 1457 cmd := NewStatusCmd("xgroup", "create", stream, group, start, "mkstream") 1458 _ = c(cmd) 1459 return cmd 1460} 1461 1462func (c cmdable) XGroupSetID(stream, group, start string) *StatusCmd { 1463 cmd := NewStatusCmd("xgroup", "setid", stream, group, start) 1464 _ = c(cmd) 1465 return cmd 1466} 1467 1468func (c cmdable) XGroupDestroy(stream, group string) *IntCmd { 1469 cmd := NewIntCmd("xgroup", "destroy", stream, group) 1470 _ = c(cmd) 1471 return cmd 1472} 1473 1474func (c cmdable) XGroupDelConsumer(stream, group, consumer string) *IntCmd { 1475 cmd := NewIntCmd("xgroup", "delconsumer", stream, group, consumer) 1476 _ = c(cmd) 1477 return cmd 1478} 1479 1480type XReadGroupArgs struct { 1481 Group string 1482 Consumer string 1483 Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2 1484 Count int64 1485 Block time.Duration 1486 NoAck bool 1487} 1488 1489func (c cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd { 1490 args := make([]interface{}, 0, 8+len(a.Streams)) 1491 args = append(args, "xreadgroup", "group", a.Group, a.Consumer) 1492 if a.Count > 0 { 1493 args = append(args, "count", a.Count) 1494 } 1495 if a.Block >= 0 { 1496 args = append(args, "block", int64(a.Block/time.Millisecond)) 1497 } 1498 if a.NoAck { 1499 args = append(args, "noack") 1500 } 1501 args = append(args, "streams") 1502 for _, s := range a.Streams { 1503 args = append(args, s) 1504 } 1505 1506 cmd := NewXStreamSliceCmd(args...) 1507 if a.Block >= 0 { 1508 cmd.setReadTimeout(a.Block) 1509 } 1510 _ = c(cmd) 1511 return cmd 1512} 1513 1514func (c cmdable) XAck(stream, group string, ids ...string) *IntCmd { 1515 args := []interface{}{"xack", stream, group} 1516 for _, id := range ids { 1517 args = append(args, id) 1518 } 1519 cmd := NewIntCmd(args...) 1520 _ = c(cmd) 1521 return cmd 1522} 1523 1524func (c cmdable) XPending(stream, group string) *XPendingCmd { 1525 cmd := NewXPendingCmd("xpending", stream, group) 1526 _ = c(cmd) 1527 return cmd 1528} 1529 1530type XPendingExtArgs struct { 1531 Stream string 1532 Group string 1533 Start string 1534 End string 1535 Count int64 1536 Consumer string 1537} 1538 1539func (c cmdable) XPendingExt(a *XPendingExtArgs) *XPendingExtCmd { 1540 args := make([]interface{}, 0, 7) 1541 args = append(args, "xpending", a.Stream, a.Group, a.Start, a.End, a.Count) 1542 if a.Consumer != "" { 1543 args = append(args, a.Consumer) 1544 } 1545 cmd := NewXPendingExtCmd(args...) 1546 _ = c(cmd) 1547 return cmd 1548} 1549 1550type XClaimArgs struct { 1551 Stream string 1552 Group string 1553 Consumer string 1554 MinIdle time.Duration 1555 Messages []string 1556} 1557 1558func (c cmdable) XClaim(a *XClaimArgs) *XMessageSliceCmd { 1559 args := xClaimArgs(a) 1560 cmd := NewXMessageSliceCmd(args...) 1561 _ = c(cmd) 1562 return cmd 1563} 1564 1565func (c cmdable) XClaimJustID(a *XClaimArgs) *StringSliceCmd { 1566 args := xClaimArgs(a) 1567 args = append(args, "justid") 1568 cmd := NewStringSliceCmd(args...) 1569 _ = c(cmd) 1570 return cmd 1571} 1572 1573func xClaimArgs(a *XClaimArgs) []interface{} { 1574 args := make([]interface{}, 0, 4+len(a.Messages)) 1575 args = append(args, 1576 "xclaim", 1577 a.Stream, 1578 a.Group, a.Consumer, 1579 int64(a.MinIdle/time.Millisecond)) 1580 for _, id := range a.Messages { 1581 args = append(args, id) 1582 } 1583 return args 1584} 1585 1586func (c cmdable) XTrim(key string, maxLen int64) *IntCmd { 1587 cmd := NewIntCmd("xtrim", key, "maxlen", maxLen) 1588 _ = c(cmd) 1589 return cmd 1590} 1591 1592func (c cmdable) XTrimApprox(key string, maxLen int64) *IntCmd { 1593 cmd := NewIntCmd("xtrim", key, "maxlen", "~", maxLen) 1594 _ = c(cmd) 1595 return cmd 1596} 1597 1598func (c cmdable) XInfoGroups(key string) *XInfoGroupsCmd { 1599 cmd := NewXInfoGroupsCmd(key) 1600 _ = c(cmd) 1601 return cmd 1602} 1603 1604//------------------------------------------------------------------------------ 1605 1606// Z represents sorted set member. 1607type Z struct { 1608 Score float64 1609 Member interface{} 1610} 1611 1612// ZWithKey represents sorted set member including the name of the key where it was popped. 1613type ZWithKey struct { 1614 Z 1615 Key string 1616} 1617 1618// ZStore is used as an arg to ZInterStore and ZUnionStore. 1619type ZStore struct { 1620 Keys []string 1621 Weights []float64 1622 // Can be SUM, MIN or MAX. 1623 Aggregate string 1624} 1625 1626// Redis `BZPOPMAX key [key ...] timeout` command. 1627func (c cmdable) BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd { 1628 args := make([]interface{}, 1+len(keys)+1) 1629 args[0] = "bzpopmax" 1630 for i, key := range keys { 1631 args[1+i] = key 1632 } 1633 args[len(args)-1] = formatSec(timeout) 1634 cmd := NewZWithKeyCmd(args...) 1635 cmd.setReadTimeout(timeout) 1636 _ = c(cmd) 1637 return cmd 1638} 1639 1640// Redis `BZPOPMIN key [key ...] timeout` command. 1641func (c cmdable) BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd { 1642 args := make([]interface{}, 1+len(keys)+1) 1643 args[0] = "bzpopmin" 1644 for i, key := range keys { 1645 args[1+i] = key 1646 } 1647 args[len(args)-1] = formatSec(timeout) 1648 cmd := NewZWithKeyCmd(args...) 1649 cmd.setReadTimeout(timeout) 1650 _ = c(cmd) 1651 return cmd 1652} 1653 1654func (c cmdable) zAdd(a []interface{}, n int, members ...*Z) *IntCmd { 1655 for i, m := range members { 1656 a[n+2*i] = m.Score 1657 a[n+2*i+1] = m.Member 1658 } 1659 cmd := NewIntCmd(a...) 1660 _ = c(cmd) 1661 return cmd 1662} 1663 1664// Redis `ZADD key score member [score member ...]` command. 1665func (c cmdable) ZAdd(key string, members ...*Z) *IntCmd { 1666 const n = 2 1667 a := make([]interface{}, n+2*len(members)) 1668 a[0], a[1] = "zadd", key 1669 return c.zAdd(a, n, members...) 1670} 1671 1672// Redis `ZADD key NX score member [score member ...]` command. 1673func (c cmdable) ZAddNX(key string, members ...*Z) *IntCmd { 1674 const n = 3 1675 a := make([]interface{}, n+2*len(members)) 1676 a[0], a[1], a[2] = "zadd", key, "nx" 1677 return c.zAdd(a, n, members...) 1678} 1679 1680// Redis `ZADD key XX score member [score member ...]` command. 1681func (c cmdable) ZAddXX(key string, members ...*Z) *IntCmd { 1682 const n = 3 1683 a := make([]interface{}, n+2*len(members)) 1684 a[0], a[1], a[2] = "zadd", key, "xx" 1685 return c.zAdd(a, n, members...) 1686} 1687 1688// Redis `ZADD key CH score member [score member ...]` command. 1689func (c cmdable) ZAddCh(key string, members ...*Z) *IntCmd { 1690 const n = 3 1691 a := make([]interface{}, n+2*len(members)) 1692 a[0], a[1], a[2] = "zadd", key, "ch" 1693 return c.zAdd(a, n, members...) 1694} 1695 1696// Redis `ZADD key NX CH score member [score member ...]` command. 1697func (c cmdable) ZAddNXCh(key string, members ...*Z) *IntCmd { 1698 const n = 4 1699 a := make([]interface{}, n+2*len(members)) 1700 a[0], a[1], a[2], a[3] = "zadd", key, "nx", "ch" 1701 return c.zAdd(a, n, members...) 1702} 1703 1704// Redis `ZADD key XX CH score member [score member ...]` command. 1705func (c cmdable) ZAddXXCh(key string, members ...*Z) *IntCmd { 1706 const n = 4 1707 a := make([]interface{}, n+2*len(members)) 1708 a[0], a[1], a[2], a[3] = "zadd", key, "xx", "ch" 1709 return c.zAdd(a, n, members...) 1710} 1711 1712func (c cmdable) zIncr(a []interface{}, n int, members ...*Z) *FloatCmd { 1713 for i, m := range members { 1714 a[n+2*i] = m.Score 1715 a[n+2*i+1] = m.Member 1716 } 1717 cmd := NewFloatCmd(a...) 1718 _ = c(cmd) 1719 return cmd 1720} 1721 1722// Redis `ZADD key INCR score member` command. 1723func (c cmdable) ZIncr(key string, member *Z) *FloatCmd { 1724 const n = 3 1725 a := make([]interface{}, n+2) 1726 a[0], a[1], a[2] = "zadd", key, "incr" 1727 return c.zIncr(a, n, member) 1728} 1729 1730// Redis `ZADD key NX INCR score member` command. 1731func (c cmdable) ZIncrNX(key string, member *Z) *FloatCmd { 1732 const n = 4 1733 a := make([]interface{}, n+2) 1734 a[0], a[1], a[2], a[3] = "zadd", key, "incr", "nx" 1735 return c.zIncr(a, n, member) 1736} 1737 1738// Redis `ZADD key XX INCR score member` command. 1739func (c cmdable) ZIncrXX(key string, member *Z) *FloatCmd { 1740 const n = 4 1741 a := make([]interface{}, n+2) 1742 a[0], a[1], a[2], a[3] = "zadd", key, "incr", "xx" 1743 return c.zIncr(a, n, member) 1744} 1745 1746func (c cmdable) ZCard(key string) *IntCmd { 1747 cmd := NewIntCmd("zcard", key) 1748 _ = c(cmd) 1749 return cmd 1750} 1751 1752func (c cmdable) ZCount(key, min, max string) *IntCmd { 1753 cmd := NewIntCmd("zcount", key, min, max) 1754 _ = c(cmd) 1755 return cmd 1756} 1757 1758func (c cmdable) ZLexCount(key, min, max string) *IntCmd { 1759 cmd := NewIntCmd("zlexcount", key, min, max) 1760 _ = c(cmd) 1761 return cmd 1762} 1763 1764func (c cmdable) ZIncrBy(key string, increment float64, member string) *FloatCmd { 1765 cmd := NewFloatCmd("zincrby", key, increment, member) 1766 _ = c(cmd) 1767 return cmd 1768} 1769 1770func (c cmdable) ZInterStore(destination string, store *ZStore) *IntCmd { 1771 args := make([]interface{}, 3+len(store.Keys)) 1772 args[0] = "zinterstore" 1773 args[1] = destination 1774 args[2] = len(store.Keys) 1775 for i, key := range store.Keys { 1776 args[3+i] = key 1777 } 1778 if len(store.Weights) > 0 { 1779 args = append(args, "weights") 1780 for _, weight := range store.Weights { 1781 args = append(args, weight) 1782 } 1783 } 1784 if store.Aggregate != "" { 1785 args = append(args, "aggregate", store.Aggregate) 1786 } 1787 cmd := NewIntCmd(args...) 1788 _ = c(cmd) 1789 return cmd 1790} 1791 1792func (c cmdable) ZPopMax(key string, count ...int64) *ZSliceCmd { 1793 args := []interface{}{ 1794 "zpopmax", 1795 key, 1796 } 1797 1798 switch len(count) { 1799 case 0: 1800 break 1801 case 1: 1802 args = append(args, count[0]) 1803 default: 1804 panic("too many arguments") 1805 } 1806 1807 cmd := NewZSliceCmd(args...) 1808 _ = c(cmd) 1809 return cmd 1810} 1811 1812func (c cmdable) ZPopMin(key string, count ...int64) *ZSliceCmd { 1813 args := []interface{}{ 1814 "zpopmin", 1815 key, 1816 } 1817 1818 switch len(count) { 1819 case 0: 1820 break 1821 case 1: 1822 args = append(args, count[0]) 1823 default: 1824 panic("too many arguments") 1825 } 1826 1827 cmd := NewZSliceCmd(args...) 1828 _ = c(cmd) 1829 return cmd 1830} 1831 1832func (c cmdable) zRange(key string, start, stop int64, withScores bool) *StringSliceCmd { 1833 args := []interface{}{ 1834 "zrange", 1835 key, 1836 start, 1837 stop, 1838 } 1839 if withScores { 1840 args = append(args, "withscores") 1841 } 1842 cmd := NewStringSliceCmd(args...) 1843 _ = c(cmd) 1844 return cmd 1845} 1846 1847func (c cmdable) ZRange(key string, start, stop int64) *StringSliceCmd { 1848 return c.zRange(key, start, stop, false) 1849} 1850 1851func (c cmdable) ZRangeWithScores(key string, start, stop int64) *ZSliceCmd { 1852 cmd := NewZSliceCmd("zrange", key, start, stop, "withscores") 1853 _ = c(cmd) 1854 return cmd 1855} 1856 1857type ZRangeBy struct { 1858 Min, Max string 1859 Offset, Count int64 1860} 1861 1862func (c cmdable) zRangeBy(zcmd, key string, opt *ZRangeBy, withScores bool) *StringSliceCmd { 1863 args := []interface{}{zcmd, key, opt.Min, opt.Max} 1864 if withScores { 1865 args = append(args, "withscores") 1866 } 1867 if opt.Offset != 0 || opt.Count != 0 { 1868 args = append( 1869 args, 1870 "limit", 1871 opt.Offset, 1872 opt.Count, 1873 ) 1874 } 1875 cmd := NewStringSliceCmd(args...) 1876 _ = c(cmd) 1877 return cmd 1878} 1879 1880func (c cmdable) ZRangeByScore(key string, opt *ZRangeBy) *StringSliceCmd { 1881 return c.zRangeBy("zrangebyscore", key, opt, false) 1882} 1883 1884func (c cmdable) ZRangeByLex(key string, opt *ZRangeBy) *StringSliceCmd { 1885 return c.zRangeBy("zrangebylex", key, opt, false) 1886} 1887 1888func (c cmdable) ZRangeByScoreWithScores(key string, opt *ZRangeBy) *ZSliceCmd { 1889 args := []interface{}{"zrangebyscore", key, opt.Min, opt.Max, "withscores"} 1890 if opt.Offset != 0 || opt.Count != 0 { 1891 args = append( 1892 args, 1893 "limit", 1894 opt.Offset, 1895 opt.Count, 1896 ) 1897 } 1898 cmd := NewZSliceCmd(args...) 1899 _ = c(cmd) 1900 return cmd 1901} 1902 1903func (c cmdable) ZRank(key, member string) *IntCmd { 1904 cmd := NewIntCmd("zrank", key, member) 1905 _ = c(cmd) 1906 return cmd 1907} 1908 1909func (c cmdable) ZRem(key string, members ...interface{}) *IntCmd { 1910 args := make([]interface{}, 2, 2+len(members)) 1911 args[0] = "zrem" 1912 args[1] = key 1913 args = appendArgs(args, members) 1914 cmd := NewIntCmd(args...) 1915 _ = c(cmd) 1916 return cmd 1917} 1918 1919func (c cmdable) ZRemRangeByRank(key string, start, stop int64) *IntCmd { 1920 cmd := NewIntCmd( 1921 "zremrangebyrank", 1922 key, 1923 start, 1924 stop, 1925 ) 1926 _ = c(cmd) 1927 return cmd 1928} 1929 1930func (c cmdable) ZRemRangeByScore(key, min, max string) *IntCmd { 1931 cmd := NewIntCmd("zremrangebyscore", key, min, max) 1932 _ = c(cmd) 1933 return cmd 1934} 1935 1936func (c cmdable) ZRemRangeByLex(key, min, max string) *IntCmd { 1937 cmd := NewIntCmd("zremrangebylex", key, min, max) 1938 _ = c(cmd) 1939 return cmd 1940} 1941 1942func (c cmdable) ZRevRange(key string, start, stop int64) *StringSliceCmd { 1943 cmd := NewStringSliceCmd("zrevrange", key, start, stop) 1944 _ = c(cmd) 1945 return cmd 1946} 1947 1948func (c cmdable) ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd { 1949 cmd := NewZSliceCmd("zrevrange", key, start, stop, "withscores") 1950 _ = c(cmd) 1951 return cmd 1952} 1953 1954func (c cmdable) zRevRangeBy(zcmd, key string, opt *ZRangeBy) *StringSliceCmd { 1955 args := []interface{}{zcmd, key, opt.Max, opt.Min} 1956 if opt.Offset != 0 || opt.Count != 0 { 1957 args = append( 1958 args, 1959 "limit", 1960 opt.Offset, 1961 opt.Count, 1962 ) 1963 } 1964 cmd := NewStringSliceCmd(args...) 1965 _ = c(cmd) 1966 return cmd 1967} 1968 1969func (c cmdable) ZRevRangeByScore(key string, opt *ZRangeBy) *StringSliceCmd { 1970 return c.zRevRangeBy("zrevrangebyscore", key, opt) 1971} 1972 1973func (c cmdable) ZRevRangeByLex(key string, opt *ZRangeBy) *StringSliceCmd { 1974 return c.zRevRangeBy("zrevrangebylex", key, opt) 1975} 1976 1977func (c cmdable) ZRevRangeByScoreWithScores(key string, opt *ZRangeBy) *ZSliceCmd { 1978 args := []interface{}{"zrevrangebyscore", key, opt.Max, opt.Min, "withscores"} 1979 if opt.Offset != 0 || opt.Count != 0 { 1980 args = append( 1981 args, 1982 "limit", 1983 opt.Offset, 1984 opt.Count, 1985 ) 1986 } 1987 cmd := NewZSliceCmd(args...) 1988 _ = c(cmd) 1989 return cmd 1990} 1991 1992func (c cmdable) ZRevRank(key, member string) *IntCmd { 1993 cmd := NewIntCmd("zrevrank", key, member) 1994 _ = c(cmd) 1995 return cmd 1996} 1997 1998func (c cmdable) ZScore(key, member string) *FloatCmd { 1999 cmd := NewFloatCmd("zscore", key, member) 2000 _ = c(cmd) 2001 return cmd 2002} 2003 2004func (c cmdable) ZUnionStore(dest string, store *ZStore) *IntCmd { 2005 args := make([]interface{}, 3+len(store.Keys)) 2006 args[0] = "zunionstore" 2007 args[1] = dest 2008 args[2] = len(store.Keys) 2009 for i, key := range store.Keys { 2010 args[3+i] = key 2011 } 2012 if len(store.Weights) > 0 { 2013 args = append(args, "weights") 2014 for _, weight := range store.Weights { 2015 args = append(args, weight) 2016 } 2017 } 2018 if store.Aggregate != "" { 2019 args = append(args, "aggregate", store.Aggregate) 2020 } 2021 cmd := NewIntCmd(args...) 2022 _ = c(cmd) 2023 return cmd 2024} 2025 2026//------------------------------------------------------------------------------ 2027 2028func (c cmdable) PFAdd(key string, els ...interface{}) *IntCmd { 2029 args := make([]interface{}, 2, 2+len(els)) 2030 args[0] = "pfadd" 2031 args[1] = key 2032 args = appendArgs(args, els) 2033 cmd := NewIntCmd(args...) 2034 _ = c(cmd) 2035 return cmd 2036} 2037 2038func (c cmdable) PFCount(keys ...string) *IntCmd { 2039 args := make([]interface{}, 1+len(keys)) 2040 args[0] = "pfcount" 2041 for i, key := range keys { 2042 args[1+i] = key 2043 } 2044 cmd := NewIntCmd(args...) 2045 _ = c(cmd) 2046 return cmd 2047} 2048 2049func (c cmdable) PFMerge(dest string, keys ...string) *StatusCmd { 2050 args := make([]interface{}, 2+len(keys)) 2051 args[0] = "pfmerge" 2052 args[1] = dest 2053 for i, key := range keys { 2054 args[2+i] = key 2055 } 2056 cmd := NewStatusCmd(args...) 2057 _ = c(cmd) 2058 return cmd 2059} 2060 2061//------------------------------------------------------------------------------ 2062 2063func (c cmdable) BgRewriteAOF() *StatusCmd { 2064 cmd := NewStatusCmd("bgrewriteaof") 2065 _ = c(cmd) 2066 return cmd 2067} 2068 2069func (c cmdable) BgSave() *StatusCmd { 2070 cmd := NewStatusCmd("bgsave") 2071 _ = c(cmd) 2072 return cmd 2073} 2074 2075func (c cmdable) ClientKill(ipPort string) *StatusCmd { 2076 cmd := NewStatusCmd("client", "kill", ipPort) 2077 _ = c(cmd) 2078 return cmd 2079} 2080 2081// ClientKillByFilter is new style synx, while the ClientKill is old 2082// CLIENT KILL <option> [value] ... <option> [value] 2083func (c cmdable) ClientKillByFilter(keys ...string) *IntCmd { 2084 args := make([]interface{}, 2+len(keys)) 2085 args[0] = "client" 2086 args[1] = "kill" 2087 for i, key := range keys { 2088 args[2+i] = key 2089 } 2090 cmd := NewIntCmd(args...) 2091 _ = c(cmd) 2092 return cmd 2093} 2094 2095func (c cmdable) ClientList() *StringCmd { 2096 cmd := NewStringCmd("client", "list") 2097 _ = c(cmd) 2098 return cmd 2099} 2100 2101func (c cmdable) ClientPause(dur time.Duration) *BoolCmd { 2102 cmd := NewBoolCmd("client", "pause", formatMs(dur)) 2103 _ = c(cmd) 2104 return cmd 2105} 2106 2107func (c cmdable) ClientID() *IntCmd { 2108 cmd := NewIntCmd("client", "id") 2109 _ = c(cmd) 2110 return cmd 2111} 2112 2113func (c cmdable) ClientUnblock(id int64) *IntCmd { 2114 cmd := NewIntCmd("client", "unblock", id) 2115 _ = c(cmd) 2116 return cmd 2117} 2118 2119func (c cmdable) ClientUnblockWithError(id int64) *IntCmd { 2120 cmd := NewIntCmd("client", "unblock", id, "error") 2121 _ = c(cmd) 2122 return cmd 2123} 2124 2125// ClientSetName assigns a name to the connection. 2126func (c statefulCmdable) ClientSetName(name string) *BoolCmd { 2127 cmd := NewBoolCmd("client", "setname", name) 2128 _ = c(cmd) 2129 return cmd 2130} 2131 2132// ClientGetName returns the name of the connection. 2133func (c cmdable) ClientGetName() *StringCmd { 2134 cmd := NewStringCmd("client", "getname") 2135 _ = c(cmd) 2136 return cmd 2137} 2138 2139func (c cmdable) ConfigGet(parameter string) *SliceCmd { 2140 cmd := NewSliceCmd("config", "get", parameter) 2141 _ = c(cmd) 2142 return cmd 2143} 2144 2145func (c cmdable) ConfigResetStat() *StatusCmd { 2146 cmd := NewStatusCmd("config", "resetstat") 2147 _ = c(cmd) 2148 return cmd 2149} 2150 2151func (c cmdable) ConfigSet(parameter, value string) *StatusCmd { 2152 cmd := NewStatusCmd("config", "set", parameter, value) 2153 _ = c(cmd) 2154 return cmd 2155} 2156 2157func (c cmdable) ConfigRewrite() *StatusCmd { 2158 cmd := NewStatusCmd("config", "rewrite") 2159 _ = c(cmd) 2160 return cmd 2161} 2162 2163// Deperecated. Use DBSize instead. 2164func (c cmdable) DbSize() *IntCmd { 2165 return c.DBSize() 2166} 2167 2168func (c cmdable) DBSize() *IntCmd { 2169 cmd := NewIntCmd("dbsize") 2170 _ = c(cmd) 2171 return cmd 2172} 2173 2174func (c cmdable) FlushAll() *StatusCmd { 2175 cmd := NewStatusCmd("flushall") 2176 _ = c(cmd) 2177 return cmd 2178} 2179 2180func (c cmdable) FlushAllAsync() *StatusCmd { 2181 cmd := NewStatusCmd("flushall", "async") 2182 _ = c(cmd) 2183 return cmd 2184} 2185 2186func (c cmdable) FlushDB() *StatusCmd { 2187 cmd := NewStatusCmd("flushdb") 2188 _ = c(cmd) 2189 return cmd 2190} 2191 2192func (c cmdable) FlushDBAsync() *StatusCmd { 2193 cmd := NewStatusCmd("flushdb", "async") 2194 _ = c(cmd) 2195 return cmd 2196} 2197 2198func (c cmdable) Info(section ...string) *StringCmd { 2199 args := []interface{}{"info"} 2200 if len(section) > 0 { 2201 args = append(args, section[0]) 2202 } 2203 cmd := NewStringCmd(args...) 2204 _ = c(cmd) 2205 return cmd 2206} 2207 2208func (c cmdable) LastSave() *IntCmd { 2209 cmd := NewIntCmd("lastsave") 2210 _ = c(cmd) 2211 return cmd 2212} 2213 2214func (c cmdable) Save() *StatusCmd { 2215 cmd := NewStatusCmd("save") 2216 _ = c(cmd) 2217 return cmd 2218} 2219 2220func (c cmdable) shutdown(modifier string) *StatusCmd { 2221 var args []interface{} 2222 if modifier == "" { 2223 args = []interface{}{"shutdown"} 2224 } else { 2225 args = []interface{}{"shutdown", modifier} 2226 } 2227 cmd := NewStatusCmd(args...) 2228 _ = c(cmd) 2229 if err := cmd.Err(); err != nil { 2230 if err == io.EOF { 2231 // Server quit as expected. 2232 cmd.err = nil 2233 } 2234 } else { 2235 // Server did not quit. String reply contains the reason. 2236 cmd.err = errors.New(cmd.val) 2237 cmd.val = "" 2238 } 2239 return cmd 2240} 2241 2242func (c cmdable) Shutdown() *StatusCmd { 2243 return c.shutdown("") 2244} 2245 2246func (c cmdable) ShutdownSave() *StatusCmd { 2247 return c.shutdown("save") 2248} 2249 2250func (c cmdable) ShutdownNoSave() *StatusCmd { 2251 return c.shutdown("nosave") 2252} 2253 2254func (c cmdable) SlaveOf(host, port string) *StatusCmd { 2255 cmd := NewStatusCmd("slaveof", host, port) 2256 _ = c(cmd) 2257 return cmd 2258} 2259 2260func (c cmdable) SlowLog() { 2261 panic("not implemented") 2262} 2263 2264func (c cmdable) Sync() { 2265 panic("not implemented") 2266} 2267 2268func (c cmdable) Time() *TimeCmd { 2269 cmd := NewTimeCmd("time") 2270 _ = c(cmd) 2271 return cmd 2272} 2273 2274//------------------------------------------------------------------------------ 2275 2276func (c cmdable) Eval(script string, keys []string, args ...interface{}) *Cmd { 2277 cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) 2278 cmdArgs[0] = "eval" 2279 cmdArgs[1] = script 2280 cmdArgs[2] = len(keys) 2281 for i, key := range keys { 2282 cmdArgs[3+i] = key 2283 } 2284 cmdArgs = appendArgs(cmdArgs, args) 2285 cmd := NewCmd(cmdArgs...) 2286 _ = c(cmd) 2287 return cmd 2288} 2289 2290func (c cmdable) EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd { 2291 cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) 2292 cmdArgs[0] = "evalsha" 2293 cmdArgs[1] = sha1 2294 cmdArgs[2] = len(keys) 2295 for i, key := range keys { 2296 cmdArgs[3+i] = key 2297 } 2298 cmdArgs = appendArgs(cmdArgs, args) 2299 cmd := NewCmd(cmdArgs...) 2300 _ = c(cmd) 2301 return cmd 2302} 2303 2304func (c cmdable) ScriptExists(hashes ...string) *BoolSliceCmd { 2305 args := make([]interface{}, 2+len(hashes)) 2306 args[0] = "script" 2307 args[1] = "exists" 2308 for i, hash := range hashes { 2309 args[2+i] = hash 2310 } 2311 cmd := NewBoolSliceCmd(args...) 2312 _ = c(cmd) 2313 return cmd 2314} 2315 2316func (c cmdable) ScriptFlush() *StatusCmd { 2317 cmd := NewStatusCmd("script", "flush") 2318 _ = c(cmd) 2319 return cmd 2320} 2321 2322func (c cmdable) ScriptKill() *StatusCmd { 2323 cmd := NewStatusCmd("script", "kill") 2324 _ = c(cmd) 2325 return cmd 2326} 2327 2328func (c cmdable) ScriptLoad(script string) *StringCmd { 2329 cmd := NewStringCmd("script", "load", script) 2330 _ = c(cmd) 2331 return cmd 2332} 2333 2334//------------------------------------------------------------------------------ 2335 2336func (c cmdable) DebugObject(key string) *StringCmd { 2337 cmd := NewStringCmd("debug", "object", key) 2338 _ = c(cmd) 2339 return cmd 2340} 2341 2342//------------------------------------------------------------------------------ 2343 2344// Publish posts the message to the channel. 2345func (c cmdable) Publish(channel string, message interface{}) *IntCmd { 2346 cmd := NewIntCmd("publish", channel, message) 2347 _ = c(cmd) 2348 return cmd 2349} 2350 2351func (c cmdable) PubSubChannels(pattern string) *StringSliceCmd { 2352 args := []interface{}{"pubsub", "channels"} 2353 if pattern != "*" { 2354 args = append(args, pattern) 2355 } 2356 cmd := NewStringSliceCmd(args...) 2357 _ = c(cmd) 2358 return cmd 2359} 2360 2361func (c cmdable) PubSubNumSub(channels ...string) *StringIntMapCmd { 2362 args := make([]interface{}, 2+len(channels)) 2363 args[0] = "pubsub" 2364 args[1] = "numsub" 2365 for i, channel := range channels { 2366 args[2+i] = channel 2367 } 2368 cmd := NewStringIntMapCmd(args...) 2369 _ = c(cmd) 2370 return cmd 2371} 2372 2373func (c cmdable) PubSubNumPat() *IntCmd { 2374 cmd := NewIntCmd("pubsub", "numpat") 2375 _ = c(cmd) 2376 return cmd 2377} 2378 2379//------------------------------------------------------------------------------ 2380 2381func (c cmdable) ClusterSlots() *ClusterSlotsCmd { 2382 cmd := NewClusterSlotsCmd("cluster", "slots") 2383 _ = c(cmd) 2384 return cmd 2385} 2386 2387func (c cmdable) ClusterNodes() *StringCmd { 2388 cmd := NewStringCmd("cluster", "nodes") 2389 _ = c(cmd) 2390 return cmd 2391} 2392 2393func (c cmdable) ClusterMeet(host, port string) *StatusCmd { 2394 cmd := NewStatusCmd("cluster", "meet", host, port) 2395 _ = c(cmd) 2396 return cmd 2397} 2398 2399func (c cmdable) ClusterForget(nodeID string) *StatusCmd { 2400 cmd := NewStatusCmd("cluster", "forget", nodeID) 2401 _ = c(cmd) 2402 return cmd 2403} 2404 2405func (c cmdable) ClusterReplicate(nodeID string) *StatusCmd { 2406 cmd := NewStatusCmd("cluster", "replicate", nodeID) 2407 _ = c(cmd) 2408 return cmd 2409} 2410 2411func (c cmdable) ClusterResetSoft() *StatusCmd { 2412 cmd := NewStatusCmd("cluster", "reset", "soft") 2413 _ = c(cmd) 2414 return cmd 2415} 2416 2417func (c cmdable) ClusterResetHard() *StatusCmd { 2418 cmd := NewStatusCmd("cluster", "reset", "hard") 2419 _ = c(cmd) 2420 return cmd 2421} 2422 2423func (c cmdable) ClusterInfo() *StringCmd { 2424 cmd := NewStringCmd("cluster", "info") 2425 _ = c(cmd) 2426 return cmd 2427} 2428 2429func (c cmdable) ClusterKeySlot(key string) *IntCmd { 2430 cmd := NewIntCmd("cluster", "keyslot", key) 2431 _ = c(cmd) 2432 return cmd 2433} 2434 2435func (c cmdable) ClusterGetKeysInSlot(slot int, count int) *StringSliceCmd { 2436 cmd := NewStringSliceCmd("cluster", "getkeysinslot", slot, count) 2437 _ = c(cmd) 2438 return cmd 2439} 2440 2441func (c cmdable) ClusterCountFailureReports(nodeID string) *IntCmd { 2442 cmd := NewIntCmd("cluster", "count-failure-reports", nodeID) 2443 _ = c(cmd) 2444 return cmd 2445} 2446 2447func (c cmdable) ClusterCountKeysInSlot(slot int) *IntCmd { 2448 cmd := NewIntCmd("cluster", "countkeysinslot", slot) 2449 _ = c(cmd) 2450 return cmd 2451} 2452 2453func (c cmdable) ClusterDelSlots(slots ...int) *StatusCmd { 2454 args := make([]interface{}, 2+len(slots)) 2455 args[0] = "cluster" 2456 args[1] = "delslots" 2457 for i, slot := range slots { 2458 args[2+i] = slot 2459 } 2460 cmd := NewStatusCmd(args...) 2461 _ = c(cmd) 2462 return cmd 2463} 2464 2465func (c cmdable) ClusterDelSlotsRange(min, max int) *StatusCmd { 2466 size := max - min + 1 2467 slots := make([]int, size) 2468 for i := 0; i < size; i++ { 2469 slots[i] = min + i 2470 } 2471 return c.ClusterDelSlots(slots...) 2472} 2473 2474func (c cmdable) ClusterSaveConfig() *StatusCmd { 2475 cmd := NewStatusCmd("cluster", "saveconfig") 2476 _ = c(cmd) 2477 return cmd 2478} 2479 2480func (c cmdable) ClusterSlaves(nodeID string) *StringSliceCmd { 2481 cmd := NewStringSliceCmd("cluster", "slaves", nodeID) 2482 _ = c(cmd) 2483 return cmd 2484} 2485 2486func (c cmdable) ReadOnly() *StatusCmd { 2487 cmd := NewStatusCmd("readonly") 2488 _ = c(cmd) 2489 return cmd 2490} 2491 2492func (c cmdable) ReadWrite() *StatusCmd { 2493 cmd := NewStatusCmd("readwrite") 2494 _ = c(cmd) 2495 return cmd 2496} 2497 2498func (c cmdable) ClusterFailover() *StatusCmd { 2499 cmd := NewStatusCmd("cluster", "failover") 2500 _ = c(cmd) 2501 return cmd 2502} 2503 2504func (c cmdable) ClusterAddSlots(slots ...int) *StatusCmd { 2505 args := make([]interface{}, 2+len(slots)) 2506 args[0] = "cluster" 2507 args[1] = "addslots" 2508 for i, num := range slots { 2509 args[2+i] = num 2510 } 2511 cmd := NewStatusCmd(args...) 2512 _ = c(cmd) 2513 return cmd 2514} 2515 2516func (c cmdable) ClusterAddSlotsRange(min, max int) *StatusCmd { 2517 size := max - min + 1 2518 slots := make([]int, size) 2519 for i := 0; i < size; i++ { 2520 slots[i] = min + i 2521 } 2522 return c.ClusterAddSlots(slots...) 2523} 2524 2525//------------------------------------------------------------------------------ 2526 2527func (c cmdable) GeoAdd(key string, geoLocation ...*GeoLocation) *IntCmd { 2528 args := make([]interface{}, 2+3*len(geoLocation)) 2529 args[0] = "geoadd" 2530 args[1] = key 2531 for i, eachLoc := range geoLocation { 2532 args[2+3*i] = eachLoc.Longitude 2533 args[2+3*i+1] = eachLoc.Latitude 2534 args[2+3*i+2] = eachLoc.Name 2535 } 2536 cmd := NewIntCmd(args...) 2537 _ = c(cmd) 2538 return cmd 2539} 2540 2541// GeoRadius is a read-only GEORADIUS_RO command. 2542func (c cmdable) GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd { 2543 cmd := NewGeoLocationCmd(query, "georadius_ro", key, longitude, latitude) 2544 if query.Store != "" || query.StoreDist != "" { 2545 cmd.SetErr(errors.New("GeoRadius does not support Store or StoreDist")) 2546 return cmd 2547 } 2548 _ = c(cmd) 2549 return cmd 2550} 2551 2552// GeoRadiusStore is a writing GEORADIUS command. 2553func (c cmdable) GeoRadiusStore(key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd { 2554 args := geoLocationArgs(query, "georadius", key, longitude, latitude) 2555 cmd := NewIntCmd(args...) 2556 if query.Store == "" && query.StoreDist == "" { 2557 cmd.SetErr(errors.New("GeoRadiusStore requires Store or StoreDist")) 2558 return cmd 2559 } 2560 _ = c(cmd) 2561 return cmd 2562} 2563 2564// GeoRadius is a read-only GEORADIUSBYMEMBER_RO command. 2565func (c cmdable) GeoRadiusByMember(key, member string, query *GeoRadiusQuery) *GeoLocationCmd { 2566 cmd := NewGeoLocationCmd(query, "georadiusbymember_ro", key, member) 2567 if query.Store != "" || query.StoreDist != "" { 2568 cmd.SetErr(errors.New("GeoRadiusByMember does not support Store or StoreDist")) 2569 return cmd 2570 } 2571 _ = c(cmd) 2572 return cmd 2573} 2574 2575// GeoRadiusByMemberStore is a writing GEORADIUSBYMEMBER command. 2576func (c cmdable) GeoRadiusByMemberStore(key, member string, query *GeoRadiusQuery) *IntCmd { 2577 args := geoLocationArgs(query, "georadiusbymember", key, member) 2578 cmd := NewIntCmd(args...) 2579 if query.Store == "" && query.StoreDist == "" { 2580 cmd.SetErr(errors.New("GeoRadiusByMemberStore requires Store or StoreDist")) 2581 return cmd 2582 } 2583 _ = c(cmd) 2584 return cmd 2585} 2586 2587func (c cmdable) GeoDist(key string, member1, member2, unit string) *FloatCmd { 2588 if unit == "" { 2589 unit = "km" 2590 } 2591 cmd := NewFloatCmd("geodist", key, member1, member2, unit) 2592 _ = c(cmd) 2593 return cmd 2594} 2595 2596func (c cmdable) GeoHash(key string, members ...string) *StringSliceCmd { 2597 args := make([]interface{}, 2+len(members)) 2598 args[0] = "geohash" 2599 args[1] = key 2600 for i, member := range members { 2601 args[2+i] = member 2602 } 2603 cmd := NewStringSliceCmd(args...) 2604 _ = c(cmd) 2605 return cmd 2606} 2607 2608func (c cmdable) GeoPos(key string, members ...string) *GeoPosCmd { 2609 args := make([]interface{}, 2+len(members)) 2610 args[0] = "geopos" 2611 args[1] = key 2612 for i, member := range members { 2613 args[2+i] = member 2614 } 2615 cmd := NewGeoPosCmd(args...) 2616 _ = c(cmd) 2617 return cmd 2618} 2619 2620//------------------------------------------------------------------------------ 2621 2622func (c cmdable) MemoryUsage(key string, samples ...int) *IntCmd { 2623 args := []interface{}{"memory", "usage", key} 2624 if len(samples) > 0 { 2625 if len(samples) != 1 { 2626 panic("MemoryUsage expects single sample count") 2627 } 2628 args = append(args, "SAMPLES", samples[0]) 2629 } 2630 cmd := NewIntCmd(args...) 2631 _ = c(cmd) 2632 return cmd 2633} 2634