1 package redis
2
3 import (
4 "bufio"
5 "context"
6 "fmt"
7 "net"
8 "regexp"
9 "strconv"
10 "strings"
11 "sync"
12 "time"
13
14 "github.com/redis/go-redis/v9/internal"
15 "github.com/redis/go-redis/v9/internal/hscan"
16 "github.com/redis/go-redis/v9/internal/proto"
17 "github.com/redis/go-redis/v9/internal/util"
18 )
19
20
21
22 var keylessCommands = map[string]struct{}{
23 "acl": {},
24 "asking": {},
25 "auth": {},
26 "bgrewriteaof": {},
27 "bgsave": {},
28 "client": {},
29 "cluster": {},
30 "config": {},
31 "debug": {},
32 "discard": {},
33 "echo": {},
34 "exec": {},
35 "failover": {},
36 "function": {},
37 "hello": {},
38 "latency": {},
39 "lolwut": {},
40 "module": {},
41 "monitor": {},
42 "multi": {},
43 "pfselftest": {},
44 "ping": {},
45 "psubscribe": {},
46 "psync": {},
47 "publish": {},
48 "pubsub": {},
49 "punsubscribe": {},
50 "quit": {},
51 "readonly": {},
52 "readwrite": {},
53 "replconf": {},
54 "replicaof": {},
55 "role": {},
56 "save": {},
57 "script": {},
58 "select": {},
59 "shutdown": {},
60 "slaveof": {},
61 "slowlog": {},
62 "subscribe": {},
63 "swapdb": {},
64 "sync": {},
65 "unsubscribe": {},
66 "unwatch": {},
67 }
68
69 type Cmder interface {
70
71
72 Name() string
73
74
75
76 FullName() string
77
78
79
80 Args() []interface{}
81
82
83
84 String() string
85
86 stringArg(int) string
87 firstKeyPos() int8
88 SetFirstKeyPos(int8)
89
90 readTimeout() *time.Duration
91 readReply(rd *proto.Reader) error
92 readRawReply(rd *proto.Reader) error
93 SetErr(error)
94 Err() error
95 }
96
97 func setCmdsErr(cmds []Cmder, e error) {
98 for _, cmd := range cmds {
99 if cmd.Err() == nil {
100 cmd.SetErr(e)
101 }
102 }
103 }
104
105 func cmdsFirstErr(cmds []Cmder) error {
106 for _, cmd := range cmds {
107 if err := cmd.Err(); err != nil {
108 return err
109 }
110 }
111 return nil
112 }
113
114 func writeCmds(wr *proto.Writer, cmds []Cmder) error {
115 for _, cmd := range cmds {
116 if err := writeCmd(wr, cmd); err != nil {
117 return err
118 }
119 }
120 return nil
121 }
122
123 func writeCmd(wr *proto.Writer, cmd Cmder) error {
124 return wr.WriteArgs(cmd.Args())
125 }
126
127
128
129
130 func cmdFirstKeyPos(cmd Cmder) int {
131 if pos := cmd.firstKeyPos(); pos != 0 {
132 return int(pos)
133 }
134
135 name := cmd.Name()
136
137
138 if _, ok := keylessCommands[name]; ok {
139 return 0
140 }
141
142 switch name {
143 case "eval", "evalsha", "eval_ro", "evalsha_ro":
144 if cmd.stringArg(2) != "0" {
145 return 3
146 }
147
148 return 0
149 case "publish":
150 return 1
151 case "memory":
152
153 if cmd.stringArg(1) == "usage" {
154 return 2
155 }
156 }
157 return 1
158 }
159
160 func cmdString(cmd Cmder, val interface{}) string {
161 b := make([]byte, 0, 64)
162
163 for i, arg := range cmd.Args() {
164 if i > 0 {
165 b = append(b, ' ')
166 }
167 b = internal.AppendArg(b, arg)
168 }
169
170 if err := cmd.Err(); err != nil {
171 b = append(b, ": "...)
172 b = append(b, err.Error()...)
173 } else if val != nil {
174 b = append(b, ": "...)
175 b = internal.AppendArg(b, val)
176 }
177
178 return util.BytesToString(b)
179 }
180
181
182
183 type baseCmd struct {
184 ctx context.Context
185 args []interface{}
186 err error
187 keyPos int8
188 rawVal interface{}
189 _readTimeout *time.Duration
190 }
191
192 var _ Cmder = (*Cmd)(nil)
193
194 func (cmd *baseCmd) Name() string {
195 if len(cmd.args) == 0 {
196 return ""
197 }
198
199 return internal.ToLower(cmd.stringArg(0))
200 }
201
202 func (cmd *baseCmd) FullName() string {
203 switch name := cmd.Name(); name {
204 case "cluster", "command":
205 if len(cmd.args) == 1 {
206 return name
207 }
208 if s2, ok := cmd.args[1].(string); ok {
209 return name + " " + s2
210 }
211 return name
212 default:
213 return name
214 }
215 }
216
217 func (cmd *baseCmd) Args() []interface{} {
218 return cmd.args
219 }
220
221 func (cmd *baseCmd) stringArg(pos int) string {
222 if pos < 0 || pos >= len(cmd.args) {
223 return ""
224 }
225 arg := cmd.args[pos]
226 switch v := arg.(type) {
227 case string:
228 return v
229 case []byte:
230 return string(v)
231 default:
232
233 return fmt.Sprint(v)
234 }
235 }
236
237 func (cmd *baseCmd) firstKeyPos() int8 {
238 return cmd.keyPos
239 }
240
241 func (cmd *baseCmd) SetFirstKeyPos(keyPos int8) {
242 cmd.keyPos = keyPos
243 }
244
245 func (cmd *baseCmd) SetErr(e error) {
246 cmd.err = e
247 }
248
249 func (cmd *baseCmd) Err() error {
250 return cmd.err
251 }
252
253 func (cmd *baseCmd) readTimeout() *time.Duration {
254 return cmd._readTimeout
255 }
256
257 func (cmd *baseCmd) setReadTimeout(d time.Duration) {
258 cmd._readTimeout = &d
259 }
260
261 func (cmd *baseCmd) readRawReply(rd *proto.Reader) (err error) {
262 cmd.rawVal, err = rd.ReadReply()
263 return err
264 }
265
266
267
268 type Cmd struct {
269 baseCmd
270
271 val interface{}
272 }
273
274 func NewCmd(ctx context.Context, args ...interface{}) *Cmd {
275 return &Cmd{
276 baseCmd: baseCmd{
277 ctx: ctx,
278 args: args,
279 },
280 }
281 }
282
283 func (cmd *Cmd) String() string {
284 return cmdString(cmd, cmd.val)
285 }
286
287 func (cmd *Cmd) SetVal(val interface{}) {
288 cmd.val = val
289 }
290
291 func (cmd *Cmd) Val() interface{} {
292 return cmd.val
293 }
294
295 func (cmd *Cmd) Result() (interface{}, error) {
296 return cmd.val, cmd.err
297 }
298
299 func (cmd *Cmd) Text() (string, error) {
300 if cmd.err != nil {
301 return "", cmd.err
302 }
303 return toString(cmd.val)
304 }
305
306 func toString(val interface{}) (string, error) {
307 switch val := val.(type) {
308 case string:
309 return val, nil
310 default:
311 err := fmt.Errorf("redis: unexpected type=%T for String", val)
312 return "", err
313 }
314 }
315
316 func (cmd *Cmd) Int() (int, error) {
317 if cmd.err != nil {
318 return 0, cmd.err
319 }
320 switch val := cmd.val.(type) {
321 case int64:
322 return int(val), nil
323 case string:
324 return strconv.Atoi(val)
325 default:
326 err := fmt.Errorf("redis: unexpected type=%T for Int", val)
327 return 0, err
328 }
329 }
330
331 func (cmd *Cmd) Int64() (int64, error) {
332 if cmd.err != nil {
333 return 0, cmd.err
334 }
335 return toInt64(cmd.val)
336 }
337
338 func toInt64(val interface{}) (int64, error) {
339 switch val := val.(type) {
340 case int64:
341 return val, nil
342 case string:
343 return strconv.ParseInt(val, 10, 64)
344 default:
345 err := fmt.Errorf("redis: unexpected type=%T for Int64", val)
346 return 0, err
347 }
348 }
349
350 func (cmd *Cmd) Uint64() (uint64, error) {
351 if cmd.err != nil {
352 return 0, cmd.err
353 }
354 return toUint64(cmd.val)
355 }
356
357 func toUint64(val interface{}) (uint64, error) {
358 switch val := val.(type) {
359 case int64:
360 return uint64(val), nil
361 case string:
362 return strconv.ParseUint(val, 10, 64)
363 default:
364 err := fmt.Errorf("redis: unexpected type=%T for Uint64", val)
365 return 0, err
366 }
367 }
368
369 func (cmd *Cmd) Float32() (float32, error) {
370 if cmd.err != nil {
371 return 0, cmd.err
372 }
373 return toFloat32(cmd.val)
374 }
375
376 func toFloat32(val interface{}) (float32, error) {
377 switch val := val.(type) {
378 case int64:
379 return float32(val), nil
380 case string:
381 f, err := strconv.ParseFloat(val, 32)
382 if err != nil {
383 return 0, err
384 }
385 return float32(f), nil
386 default:
387 err := fmt.Errorf("redis: unexpected type=%T for Float32", val)
388 return 0, err
389 }
390 }
391
392 func (cmd *Cmd) Float64() (float64, error) {
393 if cmd.err != nil {
394 return 0, cmd.err
395 }
396 return toFloat64(cmd.val)
397 }
398
399 func toFloat64(val interface{}) (float64, error) {
400 switch val := val.(type) {
401 case int64:
402 return float64(val), nil
403 case string:
404 return strconv.ParseFloat(val, 64)
405 default:
406 err := fmt.Errorf("redis: unexpected type=%T for Float64", val)
407 return 0, err
408 }
409 }
410
411 func (cmd *Cmd) Bool() (bool, error) {
412 if cmd.err != nil {
413 return false, cmd.err
414 }
415 return toBool(cmd.val)
416 }
417
418 func toBool(val interface{}) (bool, error) {
419 switch val := val.(type) {
420 case bool:
421 return val, nil
422 case int64:
423 return val != 0, nil
424 case string:
425 return strconv.ParseBool(val)
426 default:
427 err := fmt.Errorf("redis: unexpected type=%T for Bool", val)
428 return false, err
429 }
430 }
431
432 func (cmd *Cmd) Slice() ([]interface{}, error) {
433 if cmd.err != nil {
434 return nil, cmd.err
435 }
436 switch val := cmd.val.(type) {
437 case []interface{}:
438 return val, nil
439 default:
440 return nil, fmt.Errorf("redis: unexpected type=%T for Slice", val)
441 }
442 }
443
444 func (cmd *Cmd) StringSlice() ([]string, error) {
445 slice, err := cmd.Slice()
446 if err != nil {
447 return nil, err
448 }
449
450 ss := make([]string, len(slice))
451 for i, iface := range slice {
452 val, err := toString(iface)
453 if err != nil {
454 return nil, err
455 }
456 ss[i] = val
457 }
458 return ss, nil
459 }
460
461 func (cmd *Cmd) Int64Slice() ([]int64, error) {
462 slice, err := cmd.Slice()
463 if err != nil {
464 return nil, err
465 }
466
467 nums := make([]int64, len(slice))
468 for i, iface := range slice {
469 val, err := toInt64(iface)
470 if err != nil {
471 return nil, err
472 }
473 nums[i] = val
474 }
475 return nums, nil
476 }
477
478 func (cmd *Cmd) Uint64Slice() ([]uint64, error) {
479 slice, err := cmd.Slice()
480 if err != nil {
481 return nil, err
482 }
483
484 nums := make([]uint64, len(slice))
485 for i, iface := range slice {
486 val, err := toUint64(iface)
487 if err != nil {
488 return nil, err
489 }
490 nums[i] = val
491 }
492 return nums, nil
493 }
494
495 func (cmd *Cmd) Float32Slice() ([]float32, error) {
496 slice, err := cmd.Slice()
497 if err != nil {
498 return nil, err
499 }
500
501 floats := make([]float32, len(slice))
502 for i, iface := range slice {
503 val, err := toFloat32(iface)
504 if err != nil {
505 return nil, err
506 }
507 floats[i] = val
508 }
509 return floats, nil
510 }
511
512 func (cmd *Cmd) Float64Slice() ([]float64, error) {
513 slice, err := cmd.Slice()
514 if err != nil {
515 return nil, err
516 }
517
518 floats := make([]float64, len(slice))
519 for i, iface := range slice {
520 val, err := toFloat64(iface)
521 if err != nil {
522 return nil, err
523 }
524 floats[i] = val
525 }
526 return floats, nil
527 }
528
529 func (cmd *Cmd) BoolSlice() ([]bool, error) {
530 slice, err := cmd.Slice()
531 if err != nil {
532 return nil, err
533 }
534
535 bools := make([]bool, len(slice))
536 for i, iface := range slice {
537 val, err := toBool(iface)
538 if err != nil {
539 return nil, err
540 }
541 bools[i] = val
542 }
543 return bools, nil
544 }
545
546 func (cmd *Cmd) readReply(rd *proto.Reader) (err error) {
547 cmd.val, err = rd.ReadReply()
548 return err
549 }
550
551
552
553 type SliceCmd struct {
554 baseCmd
555
556 val []interface{}
557 }
558
559 var _ Cmder = (*SliceCmd)(nil)
560
561 func NewSliceCmd(ctx context.Context, args ...interface{}) *SliceCmd {
562 return &SliceCmd{
563 baseCmd: baseCmd{
564 ctx: ctx,
565 args: args,
566 },
567 }
568 }
569
570 func (cmd *SliceCmd) SetVal(val []interface{}) {
571 cmd.val = val
572 }
573
574 func (cmd *SliceCmd) Val() []interface{} {
575 return cmd.val
576 }
577
578 func (cmd *SliceCmd) Result() ([]interface{}, error) {
579 return cmd.val, cmd.err
580 }
581
582 func (cmd *SliceCmd) String() string {
583 return cmdString(cmd, cmd.val)
584 }
585
586
587
588 func (cmd *SliceCmd) Scan(dst interface{}) error {
589 if cmd.err != nil {
590 return cmd.err
591 }
592
593
594
595 var args []interface{}
596 if cmd.args[0] == "hmget" {
597 args = cmd.args[2:]
598 } else {
599
600 args = cmd.args[1:]
601 }
602
603 return hscan.Scan(dst, args, cmd.val)
604 }
605
606 func (cmd *SliceCmd) readReply(rd *proto.Reader) (err error) {
607 cmd.val, err = rd.ReadSlice()
608 return err
609 }
610
611
612
613 type StatusCmd struct {
614 baseCmd
615
616 val string
617 }
618
619 var _ Cmder = (*StatusCmd)(nil)
620
621 func NewStatusCmd(ctx context.Context, args ...interface{}) *StatusCmd {
622 return &StatusCmd{
623 baseCmd: baseCmd{
624 ctx: ctx,
625 args: args,
626 },
627 }
628 }
629
630 func (cmd *StatusCmd) SetVal(val string) {
631 cmd.val = val
632 }
633
634 func (cmd *StatusCmd) Val() string {
635 return cmd.val
636 }
637
638 func (cmd *StatusCmd) Result() (string, error) {
639 return cmd.val, cmd.err
640 }
641
642 func (cmd *StatusCmd) Bytes() ([]byte, error) {
643 return util.StringToBytes(cmd.val), cmd.err
644 }
645
646 func (cmd *StatusCmd) String() string {
647 return cmdString(cmd, cmd.val)
648 }
649
650 func (cmd *StatusCmd) readReply(rd *proto.Reader) (err error) {
651 cmd.val, err = rd.ReadString()
652 return err
653 }
654
655
656
657 type IntCmd struct {
658 baseCmd
659
660 val int64
661 }
662
663 var _ Cmder = (*IntCmd)(nil)
664
665 func NewIntCmd(ctx context.Context, args ...interface{}) *IntCmd {
666 return &IntCmd{
667 baseCmd: baseCmd{
668 ctx: ctx,
669 args: args,
670 },
671 }
672 }
673
674 func (cmd *IntCmd) SetVal(val int64) {
675 cmd.val = val
676 }
677
678 func (cmd *IntCmd) Val() int64 {
679 return cmd.val
680 }
681
682 func (cmd *IntCmd) Result() (int64, error) {
683 return cmd.val, cmd.err
684 }
685
686 func (cmd *IntCmd) Uint64() (uint64, error) {
687 return uint64(cmd.val), cmd.err
688 }
689
690 func (cmd *IntCmd) String() string {
691 return cmdString(cmd, cmd.val)
692 }
693
694 func (cmd *IntCmd) readReply(rd *proto.Reader) (err error) {
695 cmd.val, err = rd.ReadInt()
696 return err
697 }
698
699
700
701 type IntSliceCmd struct {
702 baseCmd
703
704 val []int64
705 }
706
707 var _ Cmder = (*IntSliceCmd)(nil)
708
709 func NewIntSliceCmd(ctx context.Context, args ...interface{}) *IntSliceCmd {
710 return &IntSliceCmd{
711 baseCmd: baseCmd{
712 ctx: ctx,
713 args: args,
714 },
715 }
716 }
717
718 func (cmd *IntSliceCmd) SetVal(val []int64) {
719 cmd.val = val
720 }
721
722 func (cmd *IntSliceCmd) Val() []int64 {
723 return cmd.val
724 }
725
726 func (cmd *IntSliceCmd) Result() ([]int64, error) {
727 return cmd.val, cmd.err
728 }
729
730 func (cmd *IntSliceCmd) String() string {
731 return cmdString(cmd, cmd.val)
732 }
733
734 func (cmd *IntSliceCmd) readReply(rd *proto.Reader) error {
735 n, err := rd.ReadArrayLen()
736 if err != nil {
737 return err
738 }
739 cmd.val = make([]int64, n)
740 for i := 0; i < len(cmd.val); i++ {
741 if cmd.val[i], err = rd.ReadInt(); err != nil {
742 return err
743 }
744 }
745 return nil
746 }
747
748
749
750 type DurationCmd struct {
751 baseCmd
752
753 val time.Duration
754 precision time.Duration
755 }
756
757 var _ Cmder = (*DurationCmd)(nil)
758
759 func NewDurationCmd(ctx context.Context, precision time.Duration, args ...interface{}) *DurationCmd {
760 return &DurationCmd{
761 baseCmd: baseCmd{
762 ctx: ctx,
763 args: args,
764 },
765 precision: precision,
766 }
767 }
768
769 func (cmd *DurationCmd) SetVal(val time.Duration) {
770 cmd.val = val
771 }
772
773 func (cmd *DurationCmd) Val() time.Duration {
774 return cmd.val
775 }
776
777 func (cmd *DurationCmd) Result() (time.Duration, error) {
778 return cmd.val, cmd.err
779 }
780
781 func (cmd *DurationCmd) String() string {
782 return cmdString(cmd, cmd.val)
783 }
784
785 func (cmd *DurationCmd) readReply(rd *proto.Reader) error {
786 n, err := rd.ReadInt()
787 if err != nil {
788 return err
789 }
790 switch n {
791
792
793 case -2, -1:
794 cmd.val = time.Duration(n)
795 default:
796 cmd.val = time.Duration(n) * cmd.precision
797 }
798 return nil
799 }
800
801
802
803 type TimeCmd struct {
804 baseCmd
805
806 val time.Time
807 }
808
809 var _ Cmder = (*TimeCmd)(nil)
810
811 func NewTimeCmd(ctx context.Context, args ...interface{}) *TimeCmd {
812 return &TimeCmd{
813 baseCmd: baseCmd{
814 ctx: ctx,
815 args: args,
816 },
817 }
818 }
819
820 func (cmd *TimeCmd) SetVal(val time.Time) {
821 cmd.val = val
822 }
823
824 func (cmd *TimeCmd) Val() time.Time {
825 return cmd.val
826 }
827
828 func (cmd *TimeCmd) Result() (time.Time, error) {
829 return cmd.val, cmd.err
830 }
831
832 func (cmd *TimeCmd) String() string {
833 return cmdString(cmd, cmd.val)
834 }
835
836 func (cmd *TimeCmd) readReply(rd *proto.Reader) error {
837 if err := rd.ReadFixedArrayLen(2); err != nil {
838 return err
839 }
840 second, err := rd.ReadInt()
841 if err != nil {
842 return err
843 }
844 microsecond, err := rd.ReadInt()
845 if err != nil {
846 return err
847 }
848 cmd.val = time.Unix(second, microsecond*1000)
849 return nil
850 }
851
852
853
854 type BoolCmd struct {
855 baseCmd
856
857 val bool
858 }
859
860 var _ Cmder = (*BoolCmd)(nil)
861
862 func NewBoolCmd(ctx context.Context, args ...interface{}) *BoolCmd {
863 return &BoolCmd{
864 baseCmd: baseCmd{
865 ctx: ctx,
866 args: args,
867 },
868 }
869 }
870
871 func (cmd *BoolCmd) SetVal(val bool) {
872 cmd.val = val
873 }
874
875 func (cmd *BoolCmd) Val() bool {
876 return cmd.val
877 }
878
879 func (cmd *BoolCmd) Result() (bool, error) {
880 return cmd.val, cmd.err
881 }
882
883 func (cmd *BoolCmd) String() string {
884 return cmdString(cmd, cmd.val)
885 }
886
887 func (cmd *BoolCmd) readReply(rd *proto.Reader) (err error) {
888 cmd.val, err = rd.ReadBool()
889
890
891
892 if err == Nil {
893 cmd.val = false
894 err = nil
895 }
896 return err
897 }
898
899
900
901 type StringCmd struct {
902 baseCmd
903
904 val string
905 }
906
907 var _ Cmder = (*StringCmd)(nil)
908
909 func NewStringCmd(ctx context.Context, args ...interface{}) *StringCmd {
910 return &StringCmd{
911 baseCmd: baseCmd{
912 ctx: ctx,
913 args: args,
914 },
915 }
916 }
917
918 func (cmd *StringCmd) SetVal(val string) {
919 cmd.val = val
920 }
921
922 func (cmd *StringCmd) Val() string {
923 return cmd.val
924 }
925
926 func (cmd *StringCmd) Result() (string, error) {
927 return cmd.val, cmd.err
928 }
929
930 func (cmd *StringCmd) Bytes() ([]byte, error) {
931 return util.StringToBytes(cmd.val), cmd.err
932 }
933
934 func (cmd *StringCmd) Bool() (bool, error) {
935 if cmd.err != nil {
936 return false, cmd.err
937 }
938 return strconv.ParseBool(cmd.val)
939 }
940
941 func (cmd *StringCmd) Int() (int, error) {
942 if cmd.err != nil {
943 return 0, cmd.err
944 }
945 return strconv.Atoi(cmd.Val())
946 }
947
948 func (cmd *StringCmd) Int64() (int64, error) {
949 if cmd.err != nil {
950 return 0, cmd.err
951 }
952 return strconv.ParseInt(cmd.Val(), 10, 64)
953 }
954
955 func (cmd *StringCmd) Uint64() (uint64, error) {
956 if cmd.err != nil {
957 return 0, cmd.err
958 }
959 return strconv.ParseUint(cmd.Val(), 10, 64)
960 }
961
962 func (cmd *StringCmd) Float32() (float32, error) {
963 if cmd.err != nil {
964 return 0, cmd.err
965 }
966 f, err := strconv.ParseFloat(cmd.Val(), 32)
967 if err != nil {
968 return 0, err
969 }
970 return float32(f), nil
971 }
972
973 func (cmd *StringCmd) Float64() (float64, error) {
974 if cmd.err != nil {
975 return 0, cmd.err
976 }
977 return strconv.ParseFloat(cmd.Val(), 64)
978 }
979
980 func (cmd *StringCmd) Time() (time.Time, error) {
981 if cmd.err != nil {
982 return time.Time{}, cmd.err
983 }
984 return time.Parse(time.RFC3339Nano, cmd.Val())
985 }
986
987 func (cmd *StringCmd) Scan(val interface{}) error {
988 if cmd.err != nil {
989 return cmd.err
990 }
991 return proto.Scan([]byte(cmd.val), val)
992 }
993
994 func (cmd *StringCmd) String() string {
995 return cmdString(cmd, cmd.val)
996 }
997
998 func (cmd *StringCmd) readReply(rd *proto.Reader) (err error) {
999 cmd.val, err = rd.ReadString()
1000 return err
1001 }
1002
1003
1004
1005 type FloatCmd struct {
1006 baseCmd
1007
1008 val float64
1009 }
1010
1011 var _ Cmder = (*FloatCmd)(nil)
1012
1013 func NewFloatCmd(ctx context.Context, args ...interface{}) *FloatCmd {
1014 return &FloatCmd{
1015 baseCmd: baseCmd{
1016 ctx: ctx,
1017 args: args,
1018 },
1019 }
1020 }
1021
1022 func (cmd *FloatCmd) SetVal(val float64) {
1023 cmd.val = val
1024 }
1025
1026 func (cmd *FloatCmd) Val() float64 {
1027 return cmd.val
1028 }
1029
1030 func (cmd *FloatCmd) Result() (float64, error) {
1031 return cmd.val, cmd.err
1032 }
1033
1034 func (cmd *FloatCmd) String() string {
1035 return cmdString(cmd, cmd.val)
1036 }
1037
1038 func (cmd *FloatCmd) readReply(rd *proto.Reader) (err error) {
1039 cmd.val, err = rd.ReadFloat()
1040 return err
1041 }
1042
1043
1044
1045 type FloatSliceCmd struct {
1046 baseCmd
1047
1048 val []float64
1049 }
1050
1051 var _ Cmder = (*FloatSliceCmd)(nil)
1052
1053 func NewFloatSliceCmd(ctx context.Context, args ...interface{}) *FloatSliceCmd {
1054 return &FloatSliceCmd{
1055 baseCmd: baseCmd{
1056 ctx: ctx,
1057 args: args,
1058 },
1059 }
1060 }
1061
1062 func (cmd *FloatSliceCmd) SetVal(val []float64) {
1063 cmd.val = val
1064 }
1065
1066 func (cmd *FloatSliceCmd) Val() []float64 {
1067 return cmd.val
1068 }
1069
1070 func (cmd *FloatSliceCmd) Result() ([]float64, error) {
1071 return cmd.val, cmd.err
1072 }
1073
1074 func (cmd *FloatSliceCmd) String() string {
1075 return cmdString(cmd, cmd.val)
1076 }
1077
1078 func (cmd *FloatSliceCmd) readReply(rd *proto.Reader) error {
1079 n, err := rd.ReadArrayLen()
1080 if err != nil {
1081 return err
1082 }
1083
1084 cmd.val = make([]float64, n)
1085 for i := 0; i < len(cmd.val); i++ {
1086 switch num, err := rd.ReadFloat(); {
1087 case err == Nil:
1088 cmd.val[i] = 0
1089 case err != nil:
1090 return err
1091 default:
1092 cmd.val[i] = num
1093 }
1094 }
1095 return nil
1096 }
1097
1098
1099
1100 type StringSliceCmd struct {
1101 baseCmd
1102
1103 val []string
1104 }
1105
1106 var _ Cmder = (*StringSliceCmd)(nil)
1107
1108 func NewStringSliceCmd(ctx context.Context, args ...interface{}) *StringSliceCmd {
1109 return &StringSliceCmd{
1110 baseCmd: baseCmd{
1111 ctx: ctx,
1112 args: args,
1113 },
1114 }
1115 }
1116
1117 func (cmd *StringSliceCmd) SetVal(val []string) {
1118 cmd.val = val
1119 }
1120
1121 func (cmd *StringSliceCmd) Val() []string {
1122 return cmd.val
1123 }
1124
1125 func (cmd *StringSliceCmd) Result() ([]string, error) {
1126 return cmd.val, cmd.err
1127 }
1128
1129 func (cmd *StringSliceCmd) String() string {
1130 return cmdString(cmd, cmd.val)
1131 }
1132
1133 func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
1134 return proto.ScanSlice(cmd.Val(), container)
1135 }
1136
1137 func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error {
1138 n, err := rd.ReadArrayLen()
1139 if err != nil {
1140 return err
1141 }
1142 cmd.val = make([]string, n)
1143 for i := 0; i < len(cmd.val); i++ {
1144 switch s, err := rd.ReadString(); {
1145 case err == Nil:
1146 cmd.val[i] = ""
1147 case err != nil:
1148 return err
1149 default:
1150 cmd.val[i] = s
1151 }
1152 }
1153 return nil
1154 }
1155
1156
1157
1158 type KeyValue struct {
1159 Key string
1160 Value string
1161 }
1162
1163 type KeyValueSliceCmd struct {
1164 baseCmd
1165
1166 val []KeyValue
1167 }
1168
1169 var _ Cmder = (*KeyValueSliceCmd)(nil)
1170
1171 func NewKeyValueSliceCmd(ctx context.Context, args ...interface{}) *KeyValueSliceCmd {
1172 return &KeyValueSliceCmd{
1173 baseCmd: baseCmd{
1174 ctx: ctx,
1175 args: args,
1176 },
1177 }
1178 }
1179
1180 func (cmd *KeyValueSliceCmd) SetVal(val []KeyValue) {
1181 cmd.val = val
1182 }
1183
1184 func (cmd *KeyValueSliceCmd) Val() []KeyValue {
1185 return cmd.val
1186 }
1187
1188 func (cmd *KeyValueSliceCmd) Result() ([]KeyValue, error) {
1189 return cmd.val, cmd.err
1190 }
1191
1192 func (cmd *KeyValueSliceCmd) String() string {
1193 return cmdString(cmd, cmd.val)
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207 func (cmd *KeyValueSliceCmd) readReply(rd *proto.Reader) error {
1208 n, err := rd.ReadArrayLen()
1209 if err != nil {
1210 return err
1211 }
1212
1213
1214 if n == 0 {
1215 cmd.val = make([]KeyValue, 0)
1216 return nil
1217 }
1218
1219 typ, err := rd.PeekReplyType()
1220 if err != nil {
1221 return err
1222 }
1223 array := typ == proto.RespArray
1224
1225 if array {
1226 cmd.val = make([]KeyValue, n)
1227 } else {
1228 cmd.val = make([]KeyValue, n/2)
1229 }
1230
1231 for i := 0; i < len(cmd.val); i++ {
1232 if array {
1233 if err = rd.ReadFixedArrayLen(2); err != nil {
1234 return err
1235 }
1236 }
1237
1238 if cmd.val[i].Key, err = rd.ReadString(); err != nil {
1239 return err
1240 }
1241
1242 if cmd.val[i].Value, err = rd.ReadString(); err != nil {
1243 return err
1244 }
1245 }
1246
1247 return nil
1248 }
1249
1250
1251
1252 type BoolSliceCmd struct {
1253 baseCmd
1254
1255 val []bool
1256 }
1257
1258 var _ Cmder = (*BoolSliceCmd)(nil)
1259
1260 func NewBoolSliceCmd(ctx context.Context, args ...interface{}) *BoolSliceCmd {
1261 return &BoolSliceCmd{
1262 baseCmd: baseCmd{
1263 ctx: ctx,
1264 args: args,
1265 },
1266 }
1267 }
1268
1269 func (cmd *BoolSliceCmd) SetVal(val []bool) {
1270 cmd.val = val
1271 }
1272
1273 func (cmd *BoolSliceCmd) Val() []bool {
1274 return cmd.val
1275 }
1276
1277 func (cmd *BoolSliceCmd) Result() ([]bool, error) {
1278 return cmd.val, cmd.err
1279 }
1280
1281 func (cmd *BoolSliceCmd) String() string {
1282 return cmdString(cmd, cmd.val)
1283 }
1284
1285 func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error {
1286 n, err := rd.ReadArrayLen()
1287 if err != nil {
1288 return err
1289 }
1290 cmd.val = make([]bool, n)
1291 for i := 0; i < len(cmd.val); i++ {
1292 if cmd.val[i], err = rd.ReadBool(); err != nil {
1293 return err
1294 }
1295 }
1296 return nil
1297 }
1298
1299
1300
1301 type MapStringStringCmd struct {
1302 baseCmd
1303
1304 val map[string]string
1305 }
1306
1307 var _ Cmder = (*MapStringStringCmd)(nil)
1308
1309 func NewMapStringStringCmd(ctx context.Context, args ...interface{}) *MapStringStringCmd {
1310 return &MapStringStringCmd{
1311 baseCmd: baseCmd{
1312 ctx: ctx,
1313 args: args,
1314 },
1315 }
1316 }
1317
1318 func (cmd *MapStringStringCmd) Val() map[string]string {
1319 return cmd.val
1320 }
1321
1322 func (cmd *MapStringStringCmd) SetVal(val map[string]string) {
1323 cmd.val = val
1324 }
1325
1326 func (cmd *MapStringStringCmd) Result() (map[string]string, error) {
1327 return cmd.val, cmd.err
1328 }
1329
1330 func (cmd *MapStringStringCmd) String() string {
1331 return cmdString(cmd, cmd.val)
1332 }
1333
1334
1335
1336 func (cmd *MapStringStringCmd) Scan(dest interface{}) error {
1337 if cmd.err != nil {
1338 return cmd.err
1339 }
1340
1341 strct, err := hscan.Struct(dest)
1342 if err != nil {
1343 return err
1344 }
1345
1346 for k, v := range cmd.val {
1347 if err := strct.Scan(k, v); err != nil {
1348 return err
1349 }
1350 }
1351
1352 return nil
1353 }
1354
1355 func (cmd *MapStringStringCmd) readReply(rd *proto.Reader) error {
1356 n, err := rd.ReadMapLen()
1357 if err != nil {
1358 return err
1359 }
1360
1361 cmd.val = make(map[string]string, n)
1362 for i := 0; i < n; i++ {
1363 key, err := rd.ReadString()
1364 if err != nil {
1365 return err
1366 }
1367
1368 value, err := rd.ReadString()
1369 if err != nil {
1370 return err
1371 }
1372
1373 cmd.val[key] = value
1374 }
1375 return nil
1376 }
1377
1378
1379
1380 type MapStringIntCmd struct {
1381 baseCmd
1382
1383 val map[string]int64
1384 }
1385
1386 var _ Cmder = (*MapStringIntCmd)(nil)
1387
1388 func NewMapStringIntCmd(ctx context.Context, args ...interface{}) *MapStringIntCmd {
1389 return &MapStringIntCmd{
1390 baseCmd: baseCmd{
1391 ctx: ctx,
1392 args: args,
1393 },
1394 }
1395 }
1396
1397 func (cmd *MapStringIntCmd) SetVal(val map[string]int64) {
1398 cmd.val = val
1399 }
1400
1401 func (cmd *MapStringIntCmd) Val() map[string]int64 {
1402 return cmd.val
1403 }
1404
1405 func (cmd *MapStringIntCmd) Result() (map[string]int64, error) {
1406 return cmd.val, cmd.err
1407 }
1408
1409 func (cmd *MapStringIntCmd) String() string {
1410 return cmdString(cmd, cmd.val)
1411 }
1412
1413 func (cmd *MapStringIntCmd) readReply(rd *proto.Reader) error {
1414 n, err := rd.ReadMapLen()
1415 if err != nil {
1416 return err
1417 }
1418
1419 cmd.val = make(map[string]int64, n)
1420 for i := 0; i < n; i++ {
1421 key, err := rd.ReadString()
1422 if err != nil {
1423 return err
1424 }
1425
1426 nn, err := rd.ReadInt()
1427 if err != nil {
1428 return err
1429 }
1430 cmd.val[key] = nn
1431 }
1432 return nil
1433 }
1434
1435
1436 type MapStringSliceInterfaceCmd struct {
1437 baseCmd
1438 val map[string][]interface{}
1439 }
1440
1441 func NewMapStringSliceInterfaceCmd(ctx context.Context, args ...interface{}) *MapStringSliceInterfaceCmd {
1442 return &MapStringSliceInterfaceCmd{
1443 baseCmd: baseCmd{
1444 ctx: ctx,
1445 args: args,
1446 },
1447 }
1448 }
1449
1450 func (cmd *MapStringSliceInterfaceCmd) String() string {
1451 return cmdString(cmd, cmd.val)
1452 }
1453
1454 func (cmd *MapStringSliceInterfaceCmd) SetVal(val map[string][]interface{}) {
1455 cmd.val = val
1456 }
1457
1458 func (cmd *MapStringSliceInterfaceCmd) Result() (map[string][]interface{}, error) {
1459 return cmd.val, cmd.err
1460 }
1461
1462 func (cmd *MapStringSliceInterfaceCmd) Val() map[string][]interface{} {
1463 return cmd.val
1464 }
1465
1466 func (cmd *MapStringSliceInterfaceCmd) readReply(rd *proto.Reader) (err error) {
1467 readType, err := rd.PeekReplyType()
1468 if err != nil {
1469 return err
1470 }
1471
1472 cmd.val = make(map[string][]interface{})
1473
1474 switch readType {
1475 case proto.RespMap:
1476 n, err := rd.ReadMapLen()
1477 if err != nil {
1478 return err
1479 }
1480 for i := 0; i < n; i++ {
1481 k, err := rd.ReadString()
1482 if err != nil {
1483 return err
1484 }
1485 nn, err := rd.ReadArrayLen()
1486 if err != nil {
1487 return err
1488 }
1489 cmd.val[k] = make([]interface{}, nn)
1490 for j := 0; j < nn; j++ {
1491 value, err := rd.ReadReply()
1492 if err != nil {
1493 return err
1494 }
1495 cmd.val[k][j] = value
1496 }
1497 }
1498 case proto.RespArray:
1499
1500 n, err := rd.ReadArrayLen()
1501 if err != nil {
1502 return err
1503 }
1504
1505 for i := 0; i < n; i++ {
1506
1507 itemLen, err := rd.ReadArrayLen()
1508 if err != nil {
1509 return err
1510 }
1511
1512 key, err := rd.ReadString()
1513 if err != nil {
1514 return err
1515 }
1516 cmd.val[key] = make([]interface{}, 0, itemLen-1)
1517 for j := 1; j < itemLen; j++ {
1518
1519 data, err := rd.ReadReply()
1520 if err != nil {
1521 return err
1522 }
1523 cmd.val[key] = append(cmd.val[key], data)
1524 }
1525 }
1526 }
1527
1528 return nil
1529 }
1530
1531
1532
1533 type StringStructMapCmd struct {
1534 baseCmd
1535
1536 val map[string]struct{}
1537 }
1538
1539 var _ Cmder = (*StringStructMapCmd)(nil)
1540
1541 func NewStringStructMapCmd(ctx context.Context, args ...interface{}) *StringStructMapCmd {
1542 return &StringStructMapCmd{
1543 baseCmd: baseCmd{
1544 ctx: ctx,
1545 args: args,
1546 },
1547 }
1548 }
1549
1550 func (cmd *StringStructMapCmd) SetVal(val map[string]struct{}) {
1551 cmd.val = val
1552 }
1553
1554 func (cmd *StringStructMapCmd) Val() map[string]struct{} {
1555 return cmd.val
1556 }
1557
1558 func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
1559 return cmd.val, cmd.err
1560 }
1561
1562 func (cmd *StringStructMapCmd) String() string {
1563 return cmdString(cmd, cmd.val)
1564 }
1565
1566 func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error {
1567 n, err := rd.ReadArrayLen()
1568 if err != nil {
1569 return err
1570 }
1571
1572 cmd.val = make(map[string]struct{}, n)
1573 for i := 0; i < n; i++ {
1574 key, err := rd.ReadString()
1575 if err != nil {
1576 return err
1577 }
1578 cmd.val[key] = struct{}{}
1579 }
1580 return nil
1581 }
1582
1583
1584
1585 type XMessage struct {
1586 ID string
1587 Values map[string]interface{}
1588 }
1589
1590 type XMessageSliceCmd struct {
1591 baseCmd
1592
1593 val []XMessage
1594 }
1595
1596 var _ Cmder = (*XMessageSliceCmd)(nil)
1597
1598 func NewXMessageSliceCmd(ctx context.Context, args ...interface{}) *XMessageSliceCmd {
1599 return &XMessageSliceCmd{
1600 baseCmd: baseCmd{
1601 ctx: ctx,
1602 args: args,
1603 },
1604 }
1605 }
1606
1607 func (cmd *XMessageSliceCmd) SetVal(val []XMessage) {
1608 cmd.val = val
1609 }
1610
1611 func (cmd *XMessageSliceCmd) Val() []XMessage {
1612 return cmd.val
1613 }
1614
1615 func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) {
1616 return cmd.val, cmd.err
1617 }
1618
1619 func (cmd *XMessageSliceCmd) String() string {
1620 return cmdString(cmd, cmd.val)
1621 }
1622
1623 func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) (err error) {
1624 cmd.val, err = readXMessageSlice(rd)
1625 return err
1626 }
1627
1628 func readXMessageSlice(rd *proto.Reader) ([]XMessage, error) {
1629 n, err := rd.ReadArrayLen()
1630 if err != nil {
1631 return nil, err
1632 }
1633
1634 msgs := make([]XMessage, n)
1635 for i := 0; i < len(msgs); i++ {
1636 if msgs[i], err = readXMessage(rd); err != nil {
1637 return nil, err
1638 }
1639 }
1640 return msgs, nil
1641 }
1642
1643 func readXMessage(rd *proto.Reader) (XMessage, error) {
1644 if err := rd.ReadFixedArrayLen(2); err != nil {
1645 return XMessage{}, err
1646 }
1647
1648 id, err := rd.ReadString()
1649 if err != nil {
1650 return XMessage{}, err
1651 }
1652
1653 v, err := stringInterfaceMapParser(rd)
1654 if err != nil {
1655 if err != proto.Nil {
1656 return XMessage{}, err
1657 }
1658 }
1659
1660 return XMessage{
1661 ID: id,
1662 Values: v,
1663 }, nil
1664 }
1665
1666 func stringInterfaceMapParser(rd *proto.Reader) (map[string]interface{}, error) {
1667 n, err := rd.ReadMapLen()
1668 if err != nil {
1669 return nil, err
1670 }
1671
1672 m := make(map[string]interface{}, n)
1673 for i := 0; i < n; i++ {
1674 key, err := rd.ReadString()
1675 if err != nil {
1676 return nil, err
1677 }
1678
1679 value, err := rd.ReadString()
1680 if err != nil {
1681 return nil, err
1682 }
1683
1684 m[key] = value
1685 }
1686 return m, nil
1687 }
1688
1689
1690
1691 type XStream struct {
1692 Stream string
1693 Messages []XMessage
1694 }
1695
1696 type XStreamSliceCmd struct {
1697 baseCmd
1698
1699 val []XStream
1700 }
1701
1702 var _ Cmder = (*XStreamSliceCmd)(nil)
1703
1704 func NewXStreamSliceCmd(ctx context.Context, args ...interface{}) *XStreamSliceCmd {
1705 return &XStreamSliceCmd{
1706 baseCmd: baseCmd{
1707 ctx: ctx,
1708 args: args,
1709 },
1710 }
1711 }
1712
1713 func (cmd *XStreamSliceCmd) SetVal(val []XStream) {
1714 cmd.val = val
1715 }
1716
1717 func (cmd *XStreamSliceCmd) Val() []XStream {
1718 return cmd.val
1719 }
1720
1721 func (cmd *XStreamSliceCmd) Result() ([]XStream, error) {
1722 return cmd.val, cmd.err
1723 }
1724
1725 func (cmd *XStreamSliceCmd) String() string {
1726 return cmdString(cmd, cmd.val)
1727 }
1728
1729 func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error {
1730 typ, err := rd.PeekReplyType()
1731 if err != nil {
1732 return err
1733 }
1734
1735 var n int
1736 if typ == proto.RespMap {
1737 n, err = rd.ReadMapLen()
1738 } else {
1739 n, err = rd.ReadArrayLen()
1740 }
1741 if err != nil {
1742 return err
1743 }
1744 cmd.val = make([]XStream, n)
1745 for i := 0; i < len(cmd.val); i++ {
1746 if typ != proto.RespMap {
1747 if err = rd.ReadFixedArrayLen(2); err != nil {
1748 return err
1749 }
1750 }
1751 if cmd.val[i].Stream, err = rd.ReadString(); err != nil {
1752 return err
1753 }
1754 if cmd.val[i].Messages, err = readXMessageSlice(rd); err != nil {
1755 return err
1756 }
1757 }
1758 return nil
1759 }
1760
1761
1762
1763 type XPending struct {
1764 Count int64
1765 Lower string
1766 Higher string
1767 Consumers map[string]int64
1768 }
1769
1770 type XPendingCmd struct {
1771 baseCmd
1772 val *XPending
1773 }
1774
1775 var _ Cmder = (*XPendingCmd)(nil)
1776
1777 func NewXPendingCmd(ctx context.Context, args ...interface{}) *XPendingCmd {
1778 return &XPendingCmd{
1779 baseCmd: baseCmd{
1780 ctx: ctx,
1781 args: args,
1782 },
1783 }
1784 }
1785
1786 func (cmd *XPendingCmd) SetVal(val *XPending) {
1787 cmd.val = val
1788 }
1789
1790 func (cmd *XPendingCmd) Val() *XPending {
1791 return cmd.val
1792 }
1793
1794 func (cmd *XPendingCmd) Result() (*XPending, error) {
1795 return cmd.val, cmd.err
1796 }
1797
1798 func (cmd *XPendingCmd) String() string {
1799 return cmdString(cmd, cmd.val)
1800 }
1801
1802 func (cmd *XPendingCmd) readReply(rd *proto.Reader) error {
1803 var err error
1804 if err = rd.ReadFixedArrayLen(4); err != nil {
1805 return err
1806 }
1807 cmd.val = &XPending{}
1808
1809 if cmd.val.Count, err = rd.ReadInt(); err != nil {
1810 return err
1811 }
1812
1813 if cmd.val.Lower, err = rd.ReadString(); err != nil && err != Nil {
1814 return err
1815 }
1816
1817 if cmd.val.Higher, err = rd.ReadString(); err != nil && err != Nil {
1818 return err
1819 }
1820
1821 n, err := rd.ReadArrayLen()
1822 if err != nil && err != Nil {
1823 return err
1824 }
1825 cmd.val.Consumers = make(map[string]int64, n)
1826 for i := 0; i < n; i++ {
1827 if err = rd.ReadFixedArrayLen(2); err != nil {
1828 return err
1829 }
1830
1831 consumerName, err := rd.ReadString()
1832 if err != nil {
1833 return err
1834 }
1835 consumerPending, err := rd.ReadInt()
1836 if err != nil {
1837 return err
1838 }
1839 cmd.val.Consumers[consumerName] = consumerPending
1840 }
1841 return nil
1842 }
1843
1844
1845
1846 type XPendingExt struct {
1847 ID string
1848 Consumer string
1849 Idle time.Duration
1850 RetryCount int64
1851 }
1852
1853 type XPendingExtCmd struct {
1854 baseCmd
1855 val []XPendingExt
1856 }
1857
1858 var _ Cmder = (*XPendingExtCmd)(nil)
1859
1860 func NewXPendingExtCmd(ctx context.Context, args ...interface{}) *XPendingExtCmd {
1861 return &XPendingExtCmd{
1862 baseCmd: baseCmd{
1863 ctx: ctx,
1864 args: args,
1865 },
1866 }
1867 }
1868
1869 func (cmd *XPendingExtCmd) SetVal(val []XPendingExt) {
1870 cmd.val = val
1871 }
1872
1873 func (cmd *XPendingExtCmd) Val() []XPendingExt {
1874 return cmd.val
1875 }
1876
1877 func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) {
1878 return cmd.val, cmd.err
1879 }
1880
1881 func (cmd *XPendingExtCmd) String() string {
1882 return cmdString(cmd, cmd.val)
1883 }
1884
1885 func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error {
1886 n, err := rd.ReadArrayLen()
1887 if err != nil {
1888 return err
1889 }
1890 cmd.val = make([]XPendingExt, n)
1891
1892 for i := 0; i < len(cmd.val); i++ {
1893 if err = rd.ReadFixedArrayLen(4); err != nil {
1894 return err
1895 }
1896
1897 if cmd.val[i].ID, err = rd.ReadString(); err != nil {
1898 return err
1899 }
1900
1901 if cmd.val[i].Consumer, err = rd.ReadString(); err != nil && err != Nil {
1902 return err
1903 }
1904
1905 idle, err := rd.ReadInt()
1906 if err != nil && err != Nil {
1907 return err
1908 }
1909 cmd.val[i].Idle = time.Duration(idle) * time.Millisecond
1910
1911 if cmd.val[i].RetryCount, err = rd.ReadInt(); err != nil && err != Nil {
1912 return err
1913 }
1914 }
1915
1916 return nil
1917 }
1918
1919
1920
1921 type XAutoClaimCmd struct {
1922 baseCmd
1923
1924 start string
1925 val []XMessage
1926 }
1927
1928 var _ Cmder = (*XAutoClaimCmd)(nil)
1929
1930 func NewXAutoClaimCmd(ctx context.Context, args ...interface{}) *XAutoClaimCmd {
1931 return &XAutoClaimCmd{
1932 baseCmd: baseCmd{
1933 ctx: ctx,
1934 args: args,
1935 },
1936 }
1937 }
1938
1939 func (cmd *XAutoClaimCmd) SetVal(val []XMessage, start string) {
1940 cmd.val = val
1941 cmd.start = start
1942 }
1943
1944 func (cmd *XAutoClaimCmd) Val() (messages []XMessage, start string) {
1945 return cmd.val, cmd.start
1946 }
1947
1948 func (cmd *XAutoClaimCmd) Result() (messages []XMessage, start string, err error) {
1949 return cmd.val, cmd.start, cmd.err
1950 }
1951
1952 func (cmd *XAutoClaimCmd) String() string {
1953 return cmdString(cmd, cmd.val)
1954 }
1955
1956 func (cmd *XAutoClaimCmd) readReply(rd *proto.Reader) error {
1957 n, err := rd.ReadArrayLen()
1958 if err != nil {
1959 return err
1960 }
1961
1962 switch n {
1963 case 2,
1964 3:
1965
1966 default:
1967 return fmt.Errorf("redis: got %d elements in XAutoClaim reply, wanted 2/3", n)
1968 }
1969
1970 cmd.start, err = rd.ReadString()
1971 if err != nil {
1972 return err
1973 }
1974
1975 cmd.val, err = readXMessageSlice(rd)
1976 if err != nil {
1977 return err
1978 }
1979
1980 if n >= 3 {
1981 if err := rd.DiscardNext(); err != nil {
1982 return err
1983 }
1984 }
1985
1986 return nil
1987 }
1988
1989
1990
1991 type XAutoClaimJustIDCmd struct {
1992 baseCmd
1993
1994 start string
1995 val []string
1996 }
1997
1998 var _ Cmder = (*XAutoClaimJustIDCmd)(nil)
1999
2000 func NewXAutoClaimJustIDCmd(ctx context.Context, args ...interface{}) *XAutoClaimJustIDCmd {
2001 return &XAutoClaimJustIDCmd{
2002 baseCmd: baseCmd{
2003 ctx: ctx,
2004 args: args,
2005 },
2006 }
2007 }
2008
2009 func (cmd *XAutoClaimJustIDCmd) SetVal(val []string, start string) {
2010 cmd.val = val
2011 cmd.start = start
2012 }
2013
2014 func (cmd *XAutoClaimJustIDCmd) Val() (ids []string, start string) {
2015 return cmd.val, cmd.start
2016 }
2017
2018 func (cmd *XAutoClaimJustIDCmd) Result() (ids []string, start string, err error) {
2019 return cmd.val, cmd.start, cmd.err
2020 }
2021
2022 func (cmd *XAutoClaimJustIDCmd) String() string {
2023 return cmdString(cmd, cmd.val)
2024 }
2025
2026 func (cmd *XAutoClaimJustIDCmd) readReply(rd *proto.Reader) error {
2027 n, err := rd.ReadArrayLen()
2028 if err != nil {
2029 return err
2030 }
2031
2032 switch n {
2033 case 2,
2034 3:
2035
2036 default:
2037 return fmt.Errorf("redis: got %d elements in XAutoClaimJustID reply, wanted 2/3", n)
2038 }
2039
2040 cmd.start, err = rd.ReadString()
2041 if err != nil {
2042 return err
2043 }
2044
2045 nn, err := rd.ReadArrayLen()
2046 if err != nil {
2047 return err
2048 }
2049
2050 cmd.val = make([]string, nn)
2051 for i := 0; i < nn; i++ {
2052 cmd.val[i], err = rd.ReadString()
2053 if err != nil {
2054 return err
2055 }
2056 }
2057
2058 if n >= 3 {
2059 if err := rd.DiscardNext(); err != nil {
2060 return err
2061 }
2062 }
2063
2064 return nil
2065 }
2066
2067
2068
2069 type XInfoConsumersCmd struct {
2070 baseCmd
2071 val []XInfoConsumer
2072 }
2073
2074 type XInfoConsumer struct {
2075 Name string
2076 Pending int64
2077 Idle time.Duration
2078 Inactive time.Duration
2079 }
2080
2081 var _ Cmder = (*XInfoConsumersCmd)(nil)
2082
2083 func NewXInfoConsumersCmd(ctx context.Context, stream string, group string) *XInfoConsumersCmd {
2084 return &XInfoConsumersCmd{
2085 baseCmd: baseCmd{
2086 ctx: ctx,
2087 args: []interface{}{"xinfo", "consumers", stream, group},
2088 },
2089 }
2090 }
2091
2092 func (cmd *XInfoConsumersCmd) SetVal(val []XInfoConsumer) {
2093 cmd.val = val
2094 }
2095
2096 func (cmd *XInfoConsumersCmd) Val() []XInfoConsumer {
2097 return cmd.val
2098 }
2099
2100 func (cmd *XInfoConsumersCmd) Result() ([]XInfoConsumer, error) {
2101 return cmd.val, cmd.err
2102 }
2103
2104 func (cmd *XInfoConsumersCmd) String() string {
2105 return cmdString(cmd, cmd.val)
2106 }
2107
2108 func (cmd *XInfoConsumersCmd) readReply(rd *proto.Reader) error {
2109 n, err := rd.ReadArrayLen()
2110 if err != nil {
2111 return err
2112 }
2113 cmd.val = make([]XInfoConsumer, n)
2114
2115 for i := 0; i < len(cmd.val); i++ {
2116 nn, err := rd.ReadMapLen()
2117 if err != nil {
2118 return err
2119 }
2120
2121 var key string
2122 for f := 0; f < nn; f++ {
2123 key, err = rd.ReadString()
2124 if err != nil {
2125 return err
2126 }
2127
2128 switch key {
2129 case "name":
2130 cmd.val[i].Name, err = rd.ReadString()
2131 case "pending":
2132 cmd.val[i].Pending, err = rd.ReadInt()
2133 case "idle":
2134 var idle int64
2135 idle, err = rd.ReadInt()
2136 cmd.val[i].Idle = time.Duration(idle) * time.Millisecond
2137 case "inactive":
2138 var inactive int64
2139 inactive, err = rd.ReadInt()
2140 cmd.val[i].Inactive = time.Duration(inactive) * time.Millisecond
2141 default:
2142 return fmt.Errorf("redis: unexpected content %s in XINFO CONSUMERS reply", key)
2143 }
2144 if err != nil {
2145 return err
2146 }
2147 }
2148 }
2149
2150 return nil
2151 }
2152
2153
2154
2155 type XInfoGroupsCmd struct {
2156 baseCmd
2157 val []XInfoGroup
2158 }
2159
2160 type XInfoGroup struct {
2161 Name string
2162 Consumers int64
2163 Pending int64
2164 LastDeliveredID string
2165 EntriesRead int64
2166
2167
2168 Lag int64
2169 }
2170
2171 var _ Cmder = (*XInfoGroupsCmd)(nil)
2172
2173 func NewXInfoGroupsCmd(ctx context.Context, stream string) *XInfoGroupsCmd {
2174 return &XInfoGroupsCmd{
2175 baseCmd: baseCmd{
2176 ctx: ctx,
2177 args: []interface{}{"xinfo", "groups", stream},
2178 },
2179 }
2180 }
2181
2182 func (cmd *XInfoGroupsCmd) SetVal(val []XInfoGroup) {
2183 cmd.val = val
2184 }
2185
2186 func (cmd *XInfoGroupsCmd) Val() []XInfoGroup {
2187 return cmd.val
2188 }
2189
2190 func (cmd *XInfoGroupsCmd) Result() ([]XInfoGroup, error) {
2191 return cmd.val, cmd.err
2192 }
2193
2194 func (cmd *XInfoGroupsCmd) String() string {
2195 return cmdString(cmd, cmd.val)
2196 }
2197
2198 func (cmd *XInfoGroupsCmd) readReply(rd *proto.Reader) error {
2199 n, err := rd.ReadArrayLen()
2200 if err != nil {
2201 return err
2202 }
2203 cmd.val = make([]XInfoGroup, n)
2204
2205 for i := 0; i < len(cmd.val); i++ {
2206 group := &cmd.val[i]
2207
2208 nn, err := rd.ReadMapLen()
2209 if err != nil {
2210 return err
2211 }
2212
2213 var key string
2214 for j := 0; j < nn; j++ {
2215 key, err = rd.ReadString()
2216 if err != nil {
2217 return err
2218 }
2219
2220 switch key {
2221 case "name":
2222 group.Name, err = rd.ReadString()
2223 if err != nil {
2224 return err
2225 }
2226 case "consumers":
2227 group.Consumers, err = rd.ReadInt()
2228 if err != nil {
2229 return err
2230 }
2231 case "pending":
2232 group.Pending, err = rd.ReadInt()
2233 if err != nil {
2234 return err
2235 }
2236 case "last-delivered-id":
2237 group.LastDeliveredID, err = rd.ReadString()
2238 if err != nil {
2239 return err
2240 }
2241 case "entries-read":
2242 group.EntriesRead, err = rd.ReadInt()
2243 if err != nil && err != Nil {
2244 return err
2245 }
2246 case "lag":
2247 group.Lag, err = rd.ReadInt()
2248
2249
2250
2251
2252 if err != nil && err != Nil {
2253 return err
2254 } else if err == Nil {
2255 group.Lag = -1
2256 }
2257 default:
2258 return fmt.Errorf("redis: unexpected key %q in XINFO GROUPS reply", key)
2259 }
2260 }
2261 }
2262
2263 return nil
2264 }
2265
2266
2267
2268 type XInfoStreamCmd struct {
2269 baseCmd
2270 val *XInfoStream
2271 }
2272
2273 type XInfoStream struct {
2274 Length int64
2275 RadixTreeKeys int64
2276 RadixTreeNodes int64
2277 Groups int64
2278 LastGeneratedID string
2279 MaxDeletedEntryID string
2280 EntriesAdded int64
2281 FirstEntry XMessage
2282 LastEntry XMessage
2283 RecordedFirstEntryID string
2284 }
2285
2286 var _ Cmder = (*XInfoStreamCmd)(nil)
2287
2288 func NewXInfoStreamCmd(ctx context.Context, stream string) *XInfoStreamCmd {
2289 return &XInfoStreamCmd{
2290 baseCmd: baseCmd{
2291 ctx: ctx,
2292 args: []interface{}{"xinfo", "stream", stream},
2293 },
2294 }
2295 }
2296
2297 func (cmd *XInfoStreamCmd) SetVal(val *XInfoStream) {
2298 cmd.val = val
2299 }
2300
2301 func (cmd *XInfoStreamCmd) Val() *XInfoStream {
2302 return cmd.val
2303 }
2304
2305 func (cmd *XInfoStreamCmd) Result() (*XInfoStream, error) {
2306 return cmd.val, cmd.err
2307 }
2308
2309 func (cmd *XInfoStreamCmd) String() string {
2310 return cmdString(cmd, cmd.val)
2311 }
2312
2313 func (cmd *XInfoStreamCmd) readReply(rd *proto.Reader) error {
2314 n, err := rd.ReadMapLen()
2315 if err != nil {
2316 return err
2317 }
2318 cmd.val = &XInfoStream{}
2319
2320 for i := 0; i < n; i++ {
2321 key, err := rd.ReadString()
2322 if err != nil {
2323 return err
2324 }
2325 switch key {
2326 case "length":
2327 cmd.val.Length, err = rd.ReadInt()
2328 if err != nil {
2329 return err
2330 }
2331 case "radix-tree-keys":
2332 cmd.val.RadixTreeKeys, err = rd.ReadInt()
2333 if err != nil {
2334 return err
2335 }
2336 case "radix-tree-nodes":
2337 cmd.val.RadixTreeNodes, err = rd.ReadInt()
2338 if err != nil {
2339 return err
2340 }
2341 case "groups":
2342 cmd.val.Groups, err = rd.ReadInt()
2343 if err != nil {
2344 return err
2345 }
2346 case "last-generated-id":
2347 cmd.val.LastGeneratedID, err = rd.ReadString()
2348 if err != nil {
2349 return err
2350 }
2351 case "max-deleted-entry-id":
2352 cmd.val.MaxDeletedEntryID, err = rd.ReadString()
2353 if err != nil {
2354 return err
2355 }
2356 case "entries-added":
2357 cmd.val.EntriesAdded, err = rd.ReadInt()
2358 if err != nil {
2359 return err
2360 }
2361 case "first-entry":
2362 cmd.val.FirstEntry, err = readXMessage(rd)
2363 if err != nil && err != Nil {
2364 return err
2365 }
2366 case "last-entry":
2367 cmd.val.LastEntry, err = readXMessage(rd)
2368 if err != nil && err != Nil {
2369 return err
2370 }
2371 case "recorded-first-entry-id":
2372 cmd.val.RecordedFirstEntryID, err = rd.ReadString()
2373 if err != nil {
2374 return err
2375 }
2376 default:
2377 return fmt.Errorf("redis: unexpected key %q in XINFO STREAM reply", key)
2378 }
2379 }
2380 return nil
2381 }
2382
2383
2384
2385 type XInfoStreamFullCmd struct {
2386 baseCmd
2387 val *XInfoStreamFull
2388 }
2389
2390 type XInfoStreamFull struct {
2391 Length int64
2392 RadixTreeKeys int64
2393 RadixTreeNodes int64
2394 LastGeneratedID string
2395 MaxDeletedEntryID string
2396 EntriesAdded int64
2397 Entries []XMessage
2398 Groups []XInfoStreamGroup
2399 RecordedFirstEntryID string
2400 }
2401
2402 type XInfoStreamGroup struct {
2403 Name string
2404 LastDeliveredID string
2405 EntriesRead int64
2406 Lag int64
2407 PelCount int64
2408 Pending []XInfoStreamGroupPending
2409 Consumers []XInfoStreamConsumer
2410 }
2411
2412 type XInfoStreamGroupPending struct {
2413 ID string
2414 Consumer string
2415 DeliveryTime time.Time
2416 DeliveryCount int64
2417 }
2418
2419 type XInfoStreamConsumer struct {
2420 Name string
2421 SeenTime time.Time
2422 ActiveTime time.Time
2423 PelCount int64
2424 Pending []XInfoStreamConsumerPending
2425 }
2426
2427 type XInfoStreamConsumerPending struct {
2428 ID string
2429 DeliveryTime time.Time
2430 DeliveryCount int64
2431 }
2432
2433 var _ Cmder = (*XInfoStreamFullCmd)(nil)
2434
2435 func NewXInfoStreamFullCmd(ctx context.Context, args ...interface{}) *XInfoStreamFullCmd {
2436 return &XInfoStreamFullCmd{
2437 baseCmd: baseCmd{
2438 ctx: ctx,
2439 args: args,
2440 },
2441 }
2442 }
2443
2444 func (cmd *XInfoStreamFullCmd) SetVal(val *XInfoStreamFull) {
2445 cmd.val = val
2446 }
2447
2448 func (cmd *XInfoStreamFullCmd) Val() *XInfoStreamFull {
2449 return cmd.val
2450 }
2451
2452 func (cmd *XInfoStreamFullCmd) Result() (*XInfoStreamFull, error) {
2453 return cmd.val, cmd.err
2454 }
2455
2456 func (cmd *XInfoStreamFullCmd) String() string {
2457 return cmdString(cmd, cmd.val)
2458 }
2459
2460 func (cmd *XInfoStreamFullCmd) readReply(rd *proto.Reader) error {
2461 n, err := rd.ReadMapLen()
2462 if err != nil {
2463 return err
2464 }
2465
2466 cmd.val = &XInfoStreamFull{}
2467
2468 for i := 0; i < n; i++ {
2469 key, err := rd.ReadString()
2470 if err != nil {
2471 return err
2472 }
2473
2474 switch key {
2475 case "length":
2476 cmd.val.Length, err = rd.ReadInt()
2477 if err != nil {
2478 return err
2479 }
2480 case "radix-tree-keys":
2481 cmd.val.RadixTreeKeys, err = rd.ReadInt()
2482 if err != nil {
2483 return err
2484 }
2485 case "radix-tree-nodes":
2486 cmd.val.RadixTreeNodes, err = rd.ReadInt()
2487 if err != nil {
2488 return err
2489 }
2490 case "last-generated-id":
2491 cmd.val.LastGeneratedID, err = rd.ReadString()
2492 if err != nil {
2493 return err
2494 }
2495 case "entries-added":
2496 cmd.val.EntriesAdded, err = rd.ReadInt()
2497 if err != nil {
2498 return err
2499 }
2500 case "entries":
2501 cmd.val.Entries, err = readXMessageSlice(rd)
2502 if err != nil {
2503 return err
2504 }
2505 case "groups":
2506 cmd.val.Groups, err = readStreamGroups(rd)
2507 if err != nil {
2508 return err
2509 }
2510 case "max-deleted-entry-id":
2511 cmd.val.MaxDeletedEntryID, err = rd.ReadString()
2512 if err != nil {
2513 return err
2514 }
2515 case "recorded-first-entry-id":
2516 cmd.val.RecordedFirstEntryID, err = rd.ReadString()
2517 if err != nil {
2518 return err
2519 }
2520 default:
2521 return fmt.Errorf("redis: unexpected key %q in XINFO STREAM FULL reply", key)
2522 }
2523 }
2524 return nil
2525 }
2526
2527 func readStreamGroups(rd *proto.Reader) ([]XInfoStreamGroup, error) {
2528 n, err := rd.ReadArrayLen()
2529 if err != nil {
2530 return nil, err
2531 }
2532 groups := make([]XInfoStreamGroup, 0, n)
2533 for i := 0; i < n; i++ {
2534 nn, err := rd.ReadMapLen()
2535 if err != nil {
2536 return nil, err
2537 }
2538
2539 group := XInfoStreamGroup{}
2540
2541 for j := 0; j < nn; j++ {
2542 key, err := rd.ReadString()
2543 if err != nil {
2544 return nil, err
2545 }
2546
2547 switch key {
2548 case "name":
2549 group.Name, err = rd.ReadString()
2550 if err != nil {
2551 return nil, err
2552 }
2553 case "last-delivered-id":
2554 group.LastDeliveredID, err = rd.ReadString()
2555 if err != nil {
2556 return nil, err
2557 }
2558 case "entries-read":
2559 group.EntriesRead, err = rd.ReadInt()
2560 if err != nil && err != Nil {
2561 return nil, err
2562 }
2563 case "lag":
2564
2565
2566 group.Lag, err = rd.ReadInt()
2567 if err != nil && err != Nil {
2568 return nil, err
2569 }
2570 case "pel-count":
2571 group.PelCount, err = rd.ReadInt()
2572 if err != nil {
2573 return nil, err
2574 }
2575 case "pending":
2576 group.Pending, err = readXInfoStreamGroupPending(rd)
2577 if err != nil {
2578 return nil, err
2579 }
2580 case "consumers":
2581 group.Consumers, err = readXInfoStreamConsumers(rd)
2582 if err != nil {
2583 return nil, err
2584 }
2585 default:
2586 return nil, fmt.Errorf("redis: unexpected key %q in XINFO STREAM FULL reply", key)
2587 }
2588 }
2589
2590 groups = append(groups, group)
2591 }
2592
2593 return groups, nil
2594 }
2595
2596 func readXInfoStreamGroupPending(rd *proto.Reader) ([]XInfoStreamGroupPending, error) {
2597 n, err := rd.ReadArrayLen()
2598 if err != nil {
2599 return nil, err
2600 }
2601
2602 pending := make([]XInfoStreamGroupPending, 0, n)
2603
2604 for i := 0; i < n; i++ {
2605 if err = rd.ReadFixedArrayLen(4); err != nil {
2606 return nil, err
2607 }
2608
2609 p := XInfoStreamGroupPending{}
2610
2611 p.ID, err = rd.ReadString()
2612 if err != nil {
2613 return nil, err
2614 }
2615
2616 p.Consumer, err = rd.ReadString()
2617 if err != nil {
2618 return nil, err
2619 }
2620
2621 delivery, err := rd.ReadInt()
2622 if err != nil {
2623 return nil, err
2624 }
2625 p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
2626
2627 p.DeliveryCount, err = rd.ReadInt()
2628 if err != nil {
2629 return nil, err
2630 }
2631
2632 pending = append(pending, p)
2633 }
2634
2635 return pending, nil
2636 }
2637
2638 func readXInfoStreamConsumers(rd *proto.Reader) ([]XInfoStreamConsumer, error) {
2639 n, err := rd.ReadArrayLen()
2640 if err != nil {
2641 return nil, err
2642 }
2643
2644 consumers := make([]XInfoStreamConsumer, 0, n)
2645
2646 for i := 0; i < n; i++ {
2647 nn, err := rd.ReadMapLen()
2648 if err != nil {
2649 return nil, err
2650 }
2651
2652 c := XInfoStreamConsumer{}
2653
2654 for f := 0; f < nn; f++ {
2655 cKey, err := rd.ReadString()
2656 if err != nil {
2657 return nil, err
2658 }
2659
2660 switch cKey {
2661 case "name":
2662 c.Name, err = rd.ReadString()
2663 case "seen-time":
2664 seen, err := rd.ReadInt()
2665 if err != nil {
2666 return nil, err
2667 }
2668 c.SeenTime = time.UnixMilli(seen)
2669 case "active-time":
2670 active, err := rd.ReadInt()
2671 if err != nil {
2672 return nil, err
2673 }
2674 c.ActiveTime = time.UnixMilli(active)
2675 case "pel-count":
2676 c.PelCount, err = rd.ReadInt()
2677 case "pending":
2678 pendingNumber, err := rd.ReadArrayLen()
2679 if err != nil {
2680 return nil, err
2681 }
2682
2683 c.Pending = make([]XInfoStreamConsumerPending, 0, pendingNumber)
2684
2685 for pn := 0; pn < pendingNumber; pn++ {
2686 if err = rd.ReadFixedArrayLen(3); err != nil {
2687 return nil, err
2688 }
2689
2690 p := XInfoStreamConsumerPending{}
2691
2692 p.ID, err = rd.ReadString()
2693 if err != nil {
2694 return nil, err
2695 }
2696
2697 delivery, err := rd.ReadInt()
2698 if err != nil {
2699 return nil, err
2700 }
2701 p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
2702
2703 p.DeliveryCount, err = rd.ReadInt()
2704 if err != nil {
2705 return nil, err
2706 }
2707
2708 c.Pending = append(c.Pending, p)
2709 }
2710 default:
2711 return nil, fmt.Errorf("redis: unexpected content %s "+
2712 "in XINFO STREAM FULL reply", cKey)
2713 }
2714 if err != nil {
2715 return nil, err
2716 }
2717 }
2718 consumers = append(consumers, c)
2719 }
2720
2721 return consumers, nil
2722 }
2723
2724
2725
2726 type ZSliceCmd struct {
2727 baseCmd
2728
2729 val []Z
2730 }
2731
2732 var _ Cmder = (*ZSliceCmd)(nil)
2733
2734 func NewZSliceCmd(ctx context.Context, args ...interface{}) *ZSliceCmd {
2735 return &ZSliceCmd{
2736 baseCmd: baseCmd{
2737 ctx: ctx,
2738 args: args,
2739 },
2740 }
2741 }
2742
2743 func (cmd *ZSliceCmd) SetVal(val []Z) {
2744 cmd.val = val
2745 }
2746
2747 func (cmd *ZSliceCmd) Val() []Z {
2748 return cmd.val
2749 }
2750
2751 func (cmd *ZSliceCmd) Result() ([]Z, error) {
2752 return cmd.val, cmd.err
2753 }
2754
2755 func (cmd *ZSliceCmd) String() string {
2756 return cmdString(cmd, cmd.val)
2757 }
2758
2759 func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error {
2760 n, err := rd.ReadArrayLen()
2761 if err != nil {
2762 return err
2763 }
2764
2765
2766 if n == 0 {
2767 cmd.val = make([]Z, 0)
2768 return nil
2769 }
2770
2771 typ, err := rd.PeekReplyType()
2772 if err != nil {
2773 return err
2774 }
2775 array := typ == proto.RespArray
2776
2777 if array {
2778 cmd.val = make([]Z, n)
2779 } else {
2780 cmd.val = make([]Z, n/2)
2781 }
2782
2783 for i := 0; i < len(cmd.val); i++ {
2784 if array {
2785 if err = rd.ReadFixedArrayLen(2); err != nil {
2786 return err
2787 }
2788 }
2789
2790 if cmd.val[i].Member, err = rd.ReadString(); err != nil {
2791 return err
2792 }
2793
2794 if cmd.val[i].Score, err = rd.ReadFloat(); err != nil {
2795 return err
2796 }
2797 }
2798
2799 return nil
2800 }
2801
2802
2803
2804 type ZWithKeyCmd struct {
2805 baseCmd
2806
2807 val *ZWithKey
2808 }
2809
2810 var _ Cmder = (*ZWithKeyCmd)(nil)
2811
2812 func NewZWithKeyCmd(ctx context.Context, args ...interface{}) *ZWithKeyCmd {
2813 return &ZWithKeyCmd{
2814 baseCmd: baseCmd{
2815 ctx: ctx,
2816 args: args,
2817 },
2818 }
2819 }
2820
2821 func (cmd *ZWithKeyCmd) SetVal(val *ZWithKey) {
2822 cmd.val = val
2823 }
2824
2825 func (cmd *ZWithKeyCmd) Val() *ZWithKey {
2826 return cmd.val
2827 }
2828
2829 func (cmd *ZWithKeyCmd) Result() (*ZWithKey, error) {
2830 return cmd.val, cmd.err
2831 }
2832
2833 func (cmd *ZWithKeyCmd) String() string {
2834 return cmdString(cmd, cmd.val)
2835 }
2836
2837 func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) (err error) {
2838 if err = rd.ReadFixedArrayLen(3); err != nil {
2839 return err
2840 }
2841 cmd.val = &ZWithKey{}
2842
2843 if cmd.val.Key, err = rd.ReadString(); err != nil {
2844 return err
2845 }
2846 if cmd.val.Member, err = rd.ReadString(); err != nil {
2847 return err
2848 }
2849 if cmd.val.Score, err = rd.ReadFloat(); err != nil {
2850 return err
2851 }
2852
2853 return nil
2854 }
2855
2856
2857
2858 type ScanCmd struct {
2859 baseCmd
2860
2861 page []string
2862 cursor uint64
2863
2864 process cmdable
2865 }
2866
2867 var _ Cmder = (*ScanCmd)(nil)
2868
2869 func NewScanCmd(ctx context.Context, process cmdable, args ...interface{}) *ScanCmd {
2870 return &ScanCmd{
2871 baseCmd: baseCmd{
2872 ctx: ctx,
2873 args: args,
2874 },
2875 process: process,
2876 }
2877 }
2878
2879 func (cmd *ScanCmd) SetVal(page []string, cursor uint64) {
2880 cmd.page = page
2881 cmd.cursor = cursor
2882 }
2883
2884 func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
2885 return cmd.page, cmd.cursor
2886 }
2887
2888 func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
2889 return cmd.page, cmd.cursor, cmd.err
2890 }
2891
2892 func (cmd *ScanCmd) String() string {
2893 return cmdString(cmd, cmd.page)
2894 }
2895
2896 func (cmd *ScanCmd) readReply(rd *proto.Reader) error {
2897 if err := rd.ReadFixedArrayLen(2); err != nil {
2898 return err
2899 }
2900
2901 cursor, err := rd.ReadUint()
2902 if err != nil {
2903 return err
2904 }
2905 cmd.cursor = cursor
2906
2907 n, err := rd.ReadArrayLen()
2908 if err != nil {
2909 return err
2910 }
2911 cmd.page = make([]string, n)
2912
2913 for i := 0; i < len(cmd.page); i++ {
2914 if cmd.page[i], err = rd.ReadString(); err != nil {
2915 return err
2916 }
2917 }
2918 return nil
2919 }
2920
2921
2922 func (cmd *ScanCmd) Iterator() *ScanIterator {
2923 return &ScanIterator{
2924 cmd: cmd,
2925 }
2926 }
2927
2928
2929
2930 type ClusterNode struct {
2931 ID string
2932 Addr string
2933 NetworkingMetadata map[string]string
2934 }
2935
2936 type ClusterSlot struct {
2937 Start int
2938 End int
2939 Nodes []ClusterNode
2940 }
2941
2942 type ClusterSlotsCmd struct {
2943 baseCmd
2944
2945 val []ClusterSlot
2946 }
2947
2948 var _ Cmder = (*ClusterSlotsCmd)(nil)
2949
2950 func NewClusterSlotsCmd(ctx context.Context, args ...interface{}) *ClusterSlotsCmd {
2951 return &ClusterSlotsCmd{
2952 baseCmd: baseCmd{
2953 ctx: ctx,
2954 args: args,
2955 },
2956 }
2957 }
2958
2959 func (cmd *ClusterSlotsCmd) SetVal(val []ClusterSlot) {
2960 cmd.val = val
2961 }
2962
2963 func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
2964 return cmd.val
2965 }
2966
2967 func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
2968 return cmd.val, cmd.err
2969 }
2970
2971 func (cmd *ClusterSlotsCmd) String() string {
2972 return cmdString(cmd, cmd.val)
2973 }
2974
2975 func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error {
2976 n, err := rd.ReadArrayLen()
2977 if err != nil {
2978 return err
2979 }
2980 cmd.val = make([]ClusterSlot, n)
2981
2982 for i := 0; i < len(cmd.val); i++ {
2983 n, err = rd.ReadArrayLen()
2984 if err != nil {
2985 return err
2986 }
2987 if n < 2 {
2988 return fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n)
2989 }
2990
2991 start, err := rd.ReadInt()
2992 if err != nil {
2993 return err
2994 }
2995
2996 end, err := rd.ReadInt()
2997 if err != nil {
2998 return err
2999 }
3000
3001
3002 nodes := make([]ClusterNode, n-2)
3003
3004 for j := 0; j < len(nodes); j++ {
3005 nn, err := rd.ReadArrayLen()
3006 if err != nil {
3007 return err
3008 }
3009 if nn < 2 || nn > 4 {
3010 return fmt.Errorf("got %d elements in cluster info address, expected 2, 3, or 4", n)
3011 }
3012
3013 ip, err := rd.ReadString()
3014 if err != nil {
3015 return err
3016 }
3017
3018 port, err := rd.ReadString()
3019 if err != nil {
3020 return err
3021 }
3022
3023 nodes[j].Addr = net.JoinHostPort(ip, port)
3024
3025 if nn >= 3 {
3026 id, err := rd.ReadString()
3027 if err != nil {
3028 return err
3029 }
3030 nodes[j].ID = id
3031 }
3032
3033 if nn >= 4 {
3034 metadataLength, err := rd.ReadMapLen()
3035 if err != nil {
3036 return err
3037 }
3038
3039 networkingMetadata := make(map[string]string, metadataLength)
3040
3041 for i := 0; i < metadataLength; i++ {
3042 key, err := rd.ReadString()
3043 if err != nil {
3044 return err
3045 }
3046 value, err := rd.ReadString()
3047 if err != nil {
3048 return err
3049 }
3050 networkingMetadata[key] = value
3051 }
3052
3053 nodes[j].NetworkingMetadata = networkingMetadata
3054 }
3055 }
3056
3057 cmd.val[i] = ClusterSlot{
3058 Start: int(start),
3059 End: int(end),
3060 Nodes: nodes,
3061 }
3062 }
3063
3064 return nil
3065 }
3066
3067
3068
3069
3070 type GeoLocation struct {
3071 Name string
3072 Longitude, Latitude, Dist float64
3073 GeoHash int64
3074 }
3075
3076
3077 type GeoRadiusQuery struct {
3078 Radius float64
3079
3080 Unit string
3081 WithCoord bool
3082 WithDist bool
3083 WithGeoHash bool
3084 Count int
3085
3086 Sort string
3087 Store string
3088 StoreDist string
3089
3090
3091 withLen int
3092 }
3093
3094 type GeoLocationCmd struct {
3095 baseCmd
3096
3097 q *GeoRadiusQuery
3098 locations []GeoLocation
3099 }
3100
3101 var _ Cmder = (*GeoLocationCmd)(nil)
3102
3103 func NewGeoLocationCmd(ctx context.Context, q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
3104 return &GeoLocationCmd{
3105 baseCmd: baseCmd{
3106 ctx: ctx,
3107 args: geoLocationArgs(q, args...),
3108 },
3109 q: q,
3110 }
3111 }
3112
3113 func geoLocationArgs(q *GeoRadiusQuery, args ...interface{}) []interface{} {
3114 args = append(args, q.Radius)
3115 if q.Unit != "" {
3116 args = append(args, q.Unit)
3117 } else {
3118 args = append(args, "km")
3119 }
3120 if q.WithCoord {
3121 args = append(args, "withcoord")
3122 q.withLen++
3123 }
3124 if q.WithDist {
3125 args = append(args, "withdist")
3126 q.withLen++
3127 }
3128 if q.WithGeoHash {
3129 args = append(args, "withhash")
3130 q.withLen++
3131 }
3132 if q.Count > 0 {
3133 args = append(args, "count", q.Count)
3134 }
3135 if q.Sort != "" {
3136 args = append(args, q.Sort)
3137 }
3138 if q.Store != "" {
3139 args = append(args, "store")
3140 args = append(args, q.Store)
3141 }
3142 if q.StoreDist != "" {
3143 args = append(args, "storedist")
3144 args = append(args, q.StoreDist)
3145 }
3146 return args
3147 }
3148
3149 func (cmd *GeoLocationCmd) SetVal(locations []GeoLocation) {
3150 cmd.locations = locations
3151 }
3152
3153 func (cmd *GeoLocationCmd) Val() []GeoLocation {
3154 return cmd.locations
3155 }
3156
3157 func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
3158 return cmd.locations, cmd.err
3159 }
3160
3161 func (cmd *GeoLocationCmd) String() string {
3162 return cmdString(cmd, cmd.locations)
3163 }
3164
3165 func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error {
3166 n, err := rd.ReadArrayLen()
3167 if err != nil {
3168 return err
3169 }
3170 cmd.locations = make([]GeoLocation, n)
3171
3172 for i := 0; i < len(cmd.locations); i++ {
3173
3174 if cmd.q.withLen == 0 {
3175 if cmd.locations[i].Name, err = rd.ReadString(); err != nil {
3176 return err
3177 }
3178 continue
3179 }
3180
3181
3182 if err = rd.ReadFixedArrayLen(cmd.q.withLen + 1); err != nil {
3183 return err
3184 }
3185
3186 if cmd.locations[i].Name, err = rd.ReadString(); err != nil {
3187 return err
3188 }
3189 if cmd.q.WithDist {
3190 if cmd.locations[i].Dist, err = rd.ReadFloat(); err != nil {
3191 return err
3192 }
3193 }
3194 if cmd.q.WithGeoHash {
3195 if cmd.locations[i].GeoHash, err = rd.ReadInt(); err != nil {
3196 return err
3197 }
3198 }
3199 if cmd.q.WithCoord {
3200 if err = rd.ReadFixedArrayLen(2); err != nil {
3201 return err
3202 }
3203 if cmd.locations[i].Longitude, err = rd.ReadFloat(); err != nil {
3204 return err
3205 }
3206 if cmd.locations[i].Latitude, err = rd.ReadFloat(); err != nil {
3207 return err
3208 }
3209 }
3210 }
3211
3212 return nil
3213 }
3214
3215
3216
3217
3218 type GeoSearchQuery struct {
3219 Member string
3220
3221
3222 Longitude float64
3223 Latitude float64
3224
3225
3226
3227 Radius float64
3228 RadiusUnit string
3229
3230
3231
3232 BoxWidth float64
3233 BoxHeight float64
3234 BoxUnit string
3235
3236
3237 Sort string
3238 Count int
3239 CountAny bool
3240 }
3241
3242 type GeoSearchLocationQuery struct {
3243 GeoSearchQuery
3244
3245 WithCoord bool
3246 WithDist bool
3247 WithHash bool
3248 }
3249
3250 type GeoSearchStoreQuery struct {
3251 GeoSearchQuery
3252
3253
3254
3255
3256 StoreDist bool
3257 }
3258
3259 func geoSearchLocationArgs(q *GeoSearchLocationQuery, args []interface{}) []interface{} {
3260 args = geoSearchArgs(&q.GeoSearchQuery, args)
3261
3262 if q.WithCoord {
3263 args = append(args, "withcoord")
3264 }
3265 if q.WithDist {
3266 args = append(args, "withdist")
3267 }
3268 if q.WithHash {
3269 args = append(args, "withhash")
3270 }
3271
3272 return args
3273 }
3274
3275 func geoSearchArgs(q *GeoSearchQuery, args []interface{}) []interface{} {
3276 if q.Member != "" {
3277 args = append(args, "frommember", q.Member)
3278 } else {
3279 args = append(args, "fromlonlat", q.Longitude, q.Latitude)
3280 }
3281
3282 if q.Radius > 0 {
3283 if q.RadiusUnit == "" {
3284 q.RadiusUnit = "km"
3285 }
3286 args = append(args, "byradius", q.Radius, q.RadiusUnit)
3287 } else {
3288 if q.BoxUnit == "" {
3289 q.BoxUnit = "km"
3290 }
3291 args = append(args, "bybox", q.BoxWidth, q.BoxHeight, q.BoxUnit)
3292 }
3293
3294 if q.Sort != "" {
3295 args = append(args, q.Sort)
3296 }
3297
3298 if q.Count > 0 {
3299 args = append(args, "count", q.Count)
3300 if q.CountAny {
3301 args = append(args, "any")
3302 }
3303 }
3304
3305 return args
3306 }
3307
3308 type GeoSearchLocationCmd struct {
3309 baseCmd
3310
3311 opt *GeoSearchLocationQuery
3312 val []GeoLocation
3313 }
3314
3315 var _ Cmder = (*GeoSearchLocationCmd)(nil)
3316
3317 func NewGeoSearchLocationCmd(
3318 ctx context.Context, opt *GeoSearchLocationQuery, args ...interface{},
3319 ) *GeoSearchLocationCmd {
3320 return &GeoSearchLocationCmd{
3321 baseCmd: baseCmd{
3322 ctx: ctx,
3323 args: args,
3324 },
3325 opt: opt,
3326 }
3327 }
3328
3329 func (cmd *GeoSearchLocationCmd) SetVal(val []GeoLocation) {
3330 cmd.val = val
3331 }
3332
3333 func (cmd *GeoSearchLocationCmd) Val() []GeoLocation {
3334 return cmd.val
3335 }
3336
3337 func (cmd *GeoSearchLocationCmd) Result() ([]GeoLocation, error) {
3338 return cmd.val, cmd.err
3339 }
3340
3341 func (cmd *GeoSearchLocationCmd) String() string {
3342 return cmdString(cmd, cmd.val)
3343 }
3344
3345 func (cmd *GeoSearchLocationCmd) readReply(rd *proto.Reader) error {
3346 n, err := rd.ReadArrayLen()
3347 if err != nil {
3348 return err
3349 }
3350
3351 cmd.val = make([]GeoLocation, n)
3352 for i := 0; i < n; i++ {
3353 _, err = rd.ReadArrayLen()
3354 if err != nil {
3355 return err
3356 }
3357
3358 var loc GeoLocation
3359
3360 loc.Name, err = rd.ReadString()
3361 if err != nil {
3362 return err
3363 }
3364 if cmd.opt.WithDist {
3365 loc.Dist, err = rd.ReadFloat()
3366 if err != nil {
3367 return err
3368 }
3369 }
3370 if cmd.opt.WithHash {
3371 loc.GeoHash, err = rd.ReadInt()
3372 if err != nil {
3373 return err
3374 }
3375 }
3376 if cmd.opt.WithCoord {
3377 if err = rd.ReadFixedArrayLen(2); err != nil {
3378 return err
3379 }
3380 loc.Longitude, err = rd.ReadFloat()
3381 if err != nil {
3382 return err
3383 }
3384 loc.Latitude, err = rd.ReadFloat()
3385 if err != nil {
3386 return err
3387 }
3388 }
3389
3390 cmd.val[i] = loc
3391 }
3392
3393 return nil
3394 }
3395
3396
3397
3398 type GeoPos struct {
3399 Longitude, Latitude float64
3400 }
3401
3402 type GeoPosCmd struct {
3403 baseCmd
3404
3405 val []*GeoPos
3406 }
3407
3408 var _ Cmder = (*GeoPosCmd)(nil)
3409
3410 func NewGeoPosCmd(ctx context.Context, args ...interface{}) *GeoPosCmd {
3411 return &GeoPosCmd{
3412 baseCmd: baseCmd{
3413 ctx: ctx,
3414 args: args,
3415 },
3416 }
3417 }
3418
3419 func (cmd *GeoPosCmd) SetVal(val []*GeoPos) {
3420 cmd.val = val
3421 }
3422
3423 func (cmd *GeoPosCmd) Val() []*GeoPos {
3424 return cmd.val
3425 }
3426
3427 func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
3428 return cmd.val, cmd.err
3429 }
3430
3431 func (cmd *GeoPosCmd) String() string {
3432 return cmdString(cmd, cmd.val)
3433 }
3434
3435 func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error {
3436 n, err := rd.ReadArrayLen()
3437 if err != nil {
3438 return err
3439 }
3440 cmd.val = make([]*GeoPos, n)
3441
3442 for i := 0; i < len(cmd.val); i++ {
3443 err = rd.ReadFixedArrayLen(2)
3444 if err != nil {
3445 if err == Nil {
3446 cmd.val[i] = nil
3447 continue
3448 }
3449 return err
3450 }
3451
3452 longitude, err := rd.ReadFloat()
3453 if err != nil {
3454 return err
3455 }
3456 latitude, err := rd.ReadFloat()
3457 if err != nil {
3458 return err
3459 }
3460
3461 cmd.val[i] = &GeoPos{
3462 Longitude: longitude,
3463 Latitude: latitude,
3464 }
3465 }
3466
3467 return nil
3468 }
3469
3470
3471
3472 type CommandInfo struct {
3473 Name string
3474 Arity int8
3475 Flags []string
3476 ACLFlags []string
3477 FirstKeyPos int8
3478 LastKeyPos int8
3479 StepCount int8
3480 ReadOnly bool
3481 }
3482
3483 type CommandsInfoCmd struct {
3484 baseCmd
3485
3486 val map[string]*CommandInfo
3487 }
3488
3489 var _ Cmder = (*CommandsInfoCmd)(nil)
3490
3491 func NewCommandsInfoCmd(ctx context.Context, args ...interface{}) *CommandsInfoCmd {
3492 return &CommandsInfoCmd{
3493 baseCmd: baseCmd{
3494 ctx: ctx,
3495 args: args,
3496 },
3497 }
3498 }
3499
3500 func (cmd *CommandsInfoCmd) SetVal(val map[string]*CommandInfo) {
3501 cmd.val = val
3502 }
3503
3504 func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
3505 return cmd.val
3506 }
3507
3508 func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
3509 return cmd.val, cmd.err
3510 }
3511
3512 func (cmd *CommandsInfoCmd) String() string {
3513 return cmdString(cmd, cmd.val)
3514 }
3515
3516 func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
3517 const numArgRedis5 = 6
3518 const numArgRedis6 = 7
3519 const numArgRedis7 = 10
3520
3521 n, err := rd.ReadArrayLen()
3522 if err != nil {
3523 return err
3524 }
3525 cmd.val = make(map[string]*CommandInfo, n)
3526
3527 for i := 0; i < n; i++ {
3528 nn, err := rd.ReadArrayLen()
3529 if err != nil {
3530 return err
3531 }
3532
3533 switch nn {
3534 case numArgRedis5, numArgRedis6, numArgRedis7:
3535
3536 default:
3537 return fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6/7/10", nn)
3538 }
3539
3540 cmdInfo := &CommandInfo{}
3541 if cmdInfo.Name, err = rd.ReadString(); err != nil {
3542 return err
3543 }
3544
3545 arity, err := rd.ReadInt()
3546 if err != nil {
3547 return err
3548 }
3549 cmdInfo.Arity = int8(arity)
3550
3551 flagLen, err := rd.ReadArrayLen()
3552 if err != nil {
3553 return err
3554 }
3555 cmdInfo.Flags = make([]string, flagLen)
3556 for f := 0; f < len(cmdInfo.Flags); f++ {
3557 switch s, err := rd.ReadString(); {
3558 case err == Nil:
3559 cmdInfo.Flags[f] = ""
3560 case err != nil:
3561 return err
3562 default:
3563 if !cmdInfo.ReadOnly && s == "readonly" {
3564 cmdInfo.ReadOnly = true
3565 }
3566 cmdInfo.Flags[f] = s
3567 }
3568 }
3569
3570 firstKeyPos, err := rd.ReadInt()
3571 if err != nil {
3572 return err
3573 }
3574 cmdInfo.FirstKeyPos = int8(firstKeyPos)
3575
3576 lastKeyPos, err := rd.ReadInt()
3577 if err != nil {
3578 return err
3579 }
3580 cmdInfo.LastKeyPos = int8(lastKeyPos)
3581
3582 stepCount, err := rd.ReadInt()
3583 if err != nil {
3584 return err
3585 }
3586 cmdInfo.StepCount = int8(stepCount)
3587
3588 if nn >= numArgRedis6 {
3589 aclFlagLen, err := rd.ReadArrayLen()
3590 if err != nil {
3591 return err
3592 }
3593 cmdInfo.ACLFlags = make([]string, aclFlagLen)
3594 for f := 0; f < len(cmdInfo.ACLFlags); f++ {
3595 switch s, err := rd.ReadString(); {
3596 case err == Nil:
3597 cmdInfo.ACLFlags[f] = ""
3598 case err != nil:
3599 return err
3600 default:
3601 cmdInfo.ACLFlags[f] = s
3602 }
3603 }
3604 }
3605
3606 if nn >= numArgRedis7 {
3607 if err := rd.DiscardNext(); err != nil {
3608 return err
3609 }
3610 if err := rd.DiscardNext(); err != nil {
3611 return err
3612 }
3613 if err := rd.DiscardNext(); err != nil {
3614 return err
3615 }
3616 }
3617
3618 cmd.val[cmdInfo.Name] = cmdInfo
3619 }
3620
3621 return nil
3622 }
3623
3624
3625
3626 type cmdsInfoCache struct {
3627 fn func(ctx context.Context) (map[string]*CommandInfo, error)
3628
3629 once internal.Once
3630 cmds map[string]*CommandInfo
3631 }
3632
3633 func newCmdsInfoCache(fn func(ctx context.Context) (map[string]*CommandInfo, error)) *cmdsInfoCache {
3634 return &cmdsInfoCache{
3635 fn: fn,
3636 }
3637 }
3638
3639 func (c *cmdsInfoCache) Get(ctx context.Context) (map[string]*CommandInfo, error) {
3640 err := c.once.Do(func() error {
3641 cmds, err := c.fn(ctx)
3642 if err != nil {
3643 return err
3644 }
3645
3646 lowerCmds := make(map[string]*CommandInfo, len(cmds))
3647
3648
3649 for k, v := range cmds {
3650 lowerCmds[internal.ToLower(k)] = v
3651 }
3652
3653 c.cmds = lowerCmds
3654 return nil
3655 })
3656 return c.cmds, err
3657 }
3658
3659
3660
3661 type SlowLog struct {
3662 ID int64
3663 Time time.Time
3664 Duration time.Duration
3665 Args []string
3666
3667
3668 ClientAddr string
3669 ClientName string
3670 }
3671
3672 type SlowLogCmd struct {
3673 baseCmd
3674
3675 val []SlowLog
3676 }
3677
3678 var _ Cmder = (*SlowLogCmd)(nil)
3679
3680 func NewSlowLogCmd(ctx context.Context, args ...interface{}) *SlowLogCmd {
3681 return &SlowLogCmd{
3682 baseCmd: baseCmd{
3683 ctx: ctx,
3684 args: args,
3685 },
3686 }
3687 }
3688
3689 func (cmd *SlowLogCmd) SetVal(val []SlowLog) {
3690 cmd.val = val
3691 }
3692
3693 func (cmd *SlowLogCmd) Val() []SlowLog {
3694 return cmd.val
3695 }
3696
3697 func (cmd *SlowLogCmd) Result() ([]SlowLog, error) {
3698 return cmd.val, cmd.err
3699 }
3700
3701 func (cmd *SlowLogCmd) String() string {
3702 return cmdString(cmd, cmd.val)
3703 }
3704
3705 func (cmd *SlowLogCmd) readReply(rd *proto.Reader) error {
3706 n, err := rd.ReadArrayLen()
3707 if err != nil {
3708 return err
3709 }
3710 cmd.val = make([]SlowLog, n)
3711
3712 for i := 0; i < len(cmd.val); i++ {
3713 nn, err := rd.ReadArrayLen()
3714 if err != nil {
3715 return err
3716 }
3717 if nn < 4 {
3718 return fmt.Errorf("redis: got %d elements in slowlog get, expected at least 4", nn)
3719 }
3720
3721 if cmd.val[i].ID, err = rd.ReadInt(); err != nil {
3722 return err
3723 }
3724
3725 createdAt, err := rd.ReadInt()
3726 if err != nil {
3727 return err
3728 }
3729 cmd.val[i].Time = time.Unix(createdAt, 0)
3730
3731 costs, err := rd.ReadInt()
3732 if err != nil {
3733 return err
3734 }
3735 cmd.val[i].Duration = time.Duration(costs) * time.Microsecond
3736
3737 cmdLen, err := rd.ReadArrayLen()
3738 if err != nil {
3739 return err
3740 }
3741 if cmdLen < 1 {
3742 return fmt.Errorf("redis: got %d elements commands reply in slowlog get, expected at least 1", cmdLen)
3743 }
3744
3745 cmd.val[i].Args = make([]string, cmdLen)
3746 for f := 0; f < len(cmd.val[i].Args); f++ {
3747 cmd.val[i].Args[f], err = rd.ReadString()
3748 if err != nil {
3749 return err
3750 }
3751 }
3752
3753 if nn >= 5 {
3754 if cmd.val[i].ClientAddr, err = rd.ReadString(); err != nil {
3755 return err
3756 }
3757 }
3758
3759 if nn >= 6 {
3760 if cmd.val[i].ClientName, err = rd.ReadString(); err != nil {
3761 return err
3762 }
3763 }
3764 }
3765
3766 return nil
3767 }
3768
3769
3770
3771 type MapStringInterfaceCmd struct {
3772 baseCmd
3773
3774 val map[string]interface{}
3775 }
3776
3777 var _ Cmder = (*MapStringInterfaceCmd)(nil)
3778
3779 func NewMapStringInterfaceCmd(ctx context.Context, args ...interface{}) *MapStringInterfaceCmd {
3780 return &MapStringInterfaceCmd{
3781 baseCmd: baseCmd{
3782 ctx: ctx,
3783 args: args,
3784 },
3785 }
3786 }
3787
3788 func (cmd *MapStringInterfaceCmd) SetVal(val map[string]interface{}) {
3789 cmd.val = val
3790 }
3791
3792 func (cmd *MapStringInterfaceCmd) Val() map[string]interface{} {
3793 return cmd.val
3794 }
3795
3796 func (cmd *MapStringInterfaceCmd) Result() (map[string]interface{}, error) {
3797 return cmd.val, cmd.err
3798 }
3799
3800 func (cmd *MapStringInterfaceCmd) String() string {
3801 return cmdString(cmd, cmd.val)
3802 }
3803
3804 func (cmd *MapStringInterfaceCmd) readReply(rd *proto.Reader) error {
3805 n, err := rd.ReadMapLen()
3806 if err != nil {
3807 return err
3808 }
3809
3810 cmd.val = make(map[string]interface{}, n)
3811 for i := 0; i < n; i++ {
3812 k, err := rd.ReadString()
3813 if err != nil {
3814 return err
3815 }
3816 v, err := rd.ReadReply()
3817 if err != nil {
3818 if err == Nil {
3819 cmd.val[k] = Nil
3820 continue
3821 }
3822 if err, ok := err.(proto.RedisError); ok {
3823 cmd.val[k] = err
3824 continue
3825 }
3826 return err
3827 }
3828 cmd.val[k] = v
3829 }
3830 return nil
3831 }
3832
3833
3834
3835 type MapStringStringSliceCmd struct {
3836 baseCmd
3837
3838 val []map[string]string
3839 }
3840
3841 var _ Cmder = (*MapStringStringSliceCmd)(nil)
3842
3843 func NewMapStringStringSliceCmd(ctx context.Context, args ...interface{}) *MapStringStringSliceCmd {
3844 return &MapStringStringSliceCmd{
3845 baseCmd: baseCmd{
3846 ctx: ctx,
3847 args: args,
3848 },
3849 }
3850 }
3851
3852 func (cmd *MapStringStringSliceCmd) SetVal(val []map[string]string) {
3853 cmd.val = val
3854 }
3855
3856 func (cmd *MapStringStringSliceCmd) Val() []map[string]string {
3857 return cmd.val
3858 }
3859
3860 func (cmd *MapStringStringSliceCmd) Result() ([]map[string]string, error) {
3861 return cmd.val, cmd.err
3862 }
3863
3864 func (cmd *MapStringStringSliceCmd) String() string {
3865 return cmdString(cmd, cmd.val)
3866 }
3867
3868 func (cmd *MapStringStringSliceCmd) readReply(rd *proto.Reader) error {
3869 n, err := rd.ReadArrayLen()
3870 if err != nil {
3871 return err
3872 }
3873
3874 cmd.val = make([]map[string]string, n)
3875 for i := 0; i < n; i++ {
3876 nn, err := rd.ReadMapLen()
3877 if err != nil {
3878 return err
3879 }
3880 cmd.val[i] = make(map[string]string, nn)
3881 for f := 0; f < nn; f++ {
3882 k, err := rd.ReadString()
3883 if err != nil {
3884 return err
3885 }
3886
3887 v, err := rd.ReadString()
3888 if err != nil {
3889 return err
3890 }
3891 cmd.val[i][k] = v
3892 }
3893 }
3894 return nil
3895 }
3896
3897
3898
3899
3900 type MapMapStringInterfaceCmd struct {
3901 baseCmd
3902 val map[string]interface{}
3903 }
3904
3905 func NewMapMapStringInterfaceCmd(ctx context.Context, args ...interface{}) *MapMapStringInterfaceCmd {
3906 return &MapMapStringInterfaceCmd{
3907 baseCmd: baseCmd{
3908 ctx: ctx,
3909 args: args,
3910 },
3911 }
3912 }
3913
3914 func (cmd *MapMapStringInterfaceCmd) String() string {
3915 return cmdString(cmd, cmd.val)
3916 }
3917
3918 func (cmd *MapMapStringInterfaceCmd) SetVal(val map[string]interface{}) {
3919 cmd.val = val
3920 }
3921
3922 func (cmd *MapMapStringInterfaceCmd) Result() (map[string]interface{}, error) {
3923 return cmd.val, cmd.err
3924 }
3925
3926 func (cmd *MapMapStringInterfaceCmd) Val() map[string]interface{} {
3927 return cmd.val
3928 }
3929
3930
3931 func (cmd *MapMapStringInterfaceCmd) readReply(rd *proto.Reader) (err error) {
3932 data, err := rd.ReadReply()
3933 if err != nil {
3934 return err
3935 }
3936 resultMap := map[string]interface{}{}
3937
3938 switch midResponse := data.(type) {
3939 case map[interface{}]interface{}:
3940 for k, v := range midResponse {
3941 stringKey, ok := k.(string)
3942 if !ok {
3943 return fmt.Errorf("redis: invalid map key %#v", k)
3944 }
3945 resultMap[stringKey] = v
3946 }
3947 case []interface{}:
3948 n := len(midResponse)
3949 for i := 0; i < n; i++ {
3950 finalArr, ok := midResponse[i].([]interface{})
3951 if !ok {
3952 return fmt.Errorf("redis: unexpected response %#v", data)
3953 }
3954 m := len(finalArr)
3955 if m%2 != 0 {
3956 return fmt.Errorf("redis: unexpected response %#v", data)
3957 }
3958
3959 for j := 0; j < m; j += 2 {
3960 stringKey, ok := finalArr[j].(string)
3961 if !ok {
3962 return fmt.Errorf("redis: invalid map key %#v", finalArr[i])
3963 }
3964 resultMap[stringKey] = finalArr[j+1]
3965 }
3966 }
3967 default:
3968 return fmt.Errorf("redis: unexpected response %#v", data)
3969 }
3970
3971 cmd.val = resultMap
3972 return nil
3973 }
3974
3975
3976
3977 type MapStringInterfaceSliceCmd struct {
3978 baseCmd
3979
3980 val []map[string]interface{}
3981 }
3982
3983 var _ Cmder = (*MapStringInterfaceSliceCmd)(nil)
3984
3985 func NewMapStringInterfaceSliceCmd(ctx context.Context, args ...interface{}) *MapStringInterfaceSliceCmd {
3986 return &MapStringInterfaceSliceCmd{
3987 baseCmd: baseCmd{
3988 ctx: ctx,
3989 args: args,
3990 },
3991 }
3992 }
3993
3994 func (cmd *MapStringInterfaceSliceCmd) SetVal(val []map[string]interface{}) {
3995 cmd.val = val
3996 }
3997
3998 func (cmd *MapStringInterfaceSliceCmd) Val() []map[string]interface{} {
3999 return cmd.val
4000 }
4001
4002 func (cmd *MapStringInterfaceSliceCmd) Result() ([]map[string]interface{}, error) {
4003 return cmd.val, cmd.err
4004 }
4005
4006 func (cmd *MapStringInterfaceSliceCmd) String() string {
4007 return cmdString(cmd, cmd.val)
4008 }
4009
4010 func (cmd *MapStringInterfaceSliceCmd) readReply(rd *proto.Reader) error {
4011 n, err := rd.ReadArrayLen()
4012 if err != nil {
4013 return err
4014 }
4015
4016 cmd.val = make([]map[string]interface{}, n)
4017 for i := 0; i < n; i++ {
4018 nn, err := rd.ReadMapLen()
4019 if err != nil {
4020 return err
4021 }
4022 cmd.val[i] = make(map[string]interface{}, nn)
4023 for f := 0; f < nn; f++ {
4024 k, err := rd.ReadString()
4025 if err != nil {
4026 return err
4027 }
4028 v, err := rd.ReadReply()
4029 if err != nil {
4030 if err != Nil {
4031 return err
4032 }
4033 }
4034 cmd.val[i][k] = v
4035 }
4036 }
4037 return nil
4038 }
4039
4040
4041
4042 type KeyValuesCmd struct {
4043 baseCmd
4044
4045 key string
4046 val []string
4047 }
4048
4049 var _ Cmder = (*KeyValuesCmd)(nil)
4050
4051 func NewKeyValuesCmd(ctx context.Context, args ...interface{}) *KeyValuesCmd {
4052 return &KeyValuesCmd{
4053 baseCmd: baseCmd{
4054 ctx: ctx,
4055 args: args,
4056 },
4057 }
4058 }
4059
4060 func (cmd *KeyValuesCmd) SetVal(key string, val []string) {
4061 cmd.key = key
4062 cmd.val = val
4063 }
4064
4065 func (cmd *KeyValuesCmd) Val() (string, []string) {
4066 return cmd.key, cmd.val
4067 }
4068
4069 func (cmd *KeyValuesCmd) Result() (string, []string, error) {
4070 return cmd.key, cmd.val, cmd.err
4071 }
4072
4073 func (cmd *KeyValuesCmd) String() string {
4074 return cmdString(cmd, cmd.val)
4075 }
4076
4077 func (cmd *KeyValuesCmd) readReply(rd *proto.Reader) (err error) {
4078 if err = rd.ReadFixedArrayLen(2); err != nil {
4079 return err
4080 }
4081
4082 cmd.key, err = rd.ReadString()
4083 if err != nil {
4084 return err
4085 }
4086
4087 n, err := rd.ReadArrayLen()
4088 if err != nil {
4089 return err
4090 }
4091 cmd.val = make([]string, n)
4092 for i := 0; i < n; i++ {
4093 cmd.val[i], err = rd.ReadString()
4094 if err != nil {
4095 return err
4096 }
4097 }
4098
4099 return nil
4100 }
4101
4102
4103
4104 type ZSliceWithKeyCmd struct {
4105 baseCmd
4106
4107 key string
4108 val []Z
4109 }
4110
4111 var _ Cmder = (*ZSliceWithKeyCmd)(nil)
4112
4113 func NewZSliceWithKeyCmd(ctx context.Context, args ...interface{}) *ZSliceWithKeyCmd {
4114 return &ZSliceWithKeyCmd{
4115 baseCmd: baseCmd{
4116 ctx: ctx,
4117 args: args,
4118 },
4119 }
4120 }
4121
4122 func (cmd *ZSliceWithKeyCmd) SetVal(key string, val []Z) {
4123 cmd.key = key
4124 cmd.val = val
4125 }
4126
4127 func (cmd *ZSliceWithKeyCmd) Val() (string, []Z) {
4128 return cmd.key, cmd.val
4129 }
4130
4131 func (cmd *ZSliceWithKeyCmd) Result() (string, []Z, error) {
4132 return cmd.key, cmd.val, cmd.err
4133 }
4134
4135 func (cmd *ZSliceWithKeyCmd) String() string {
4136 return cmdString(cmd, cmd.val)
4137 }
4138
4139 func (cmd *ZSliceWithKeyCmd) readReply(rd *proto.Reader) (err error) {
4140 if err = rd.ReadFixedArrayLen(2); err != nil {
4141 return err
4142 }
4143
4144 cmd.key, err = rd.ReadString()
4145 if err != nil {
4146 return err
4147 }
4148
4149 n, err := rd.ReadArrayLen()
4150 if err != nil {
4151 return err
4152 }
4153
4154 typ, err := rd.PeekReplyType()
4155 if err != nil {
4156 return err
4157 }
4158 array := typ == proto.RespArray
4159
4160 if array {
4161 cmd.val = make([]Z, n)
4162 } else {
4163 cmd.val = make([]Z, n/2)
4164 }
4165
4166 for i := 0; i < len(cmd.val); i++ {
4167 if array {
4168 if err = rd.ReadFixedArrayLen(2); err != nil {
4169 return err
4170 }
4171 }
4172
4173 if cmd.val[i].Member, err = rd.ReadString(); err != nil {
4174 return err
4175 }
4176
4177 if cmd.val[i].Score, err = rd.ReadFloat(); err != nil {
4178 return err
4179 }
4180 }
4181
4182 return nil
4183 }
4184
4185 type Function struct {
4186 Name string
4187 Description string
4188 Flags []string
4189 }
4190
4191 type Library struct {
4192 Name string
4193 Engine string
4194 Functions []Function
4195 Code string
4196 }
4197
4198 type FunctionListCmd struct {
4199 baseCmd
4200
4201 val []Library
4202 }
4203
4204 var _ Cmder = (*FunctionListCmd)(nil)
4205
4206 func NewFunctionListCmd(ctx context.Context, args ...interface{}) *FunctionListCmd {
4207 return &FunctionListCmd{
4208 baseCmd: baseCmd{
4209 ctx: ctx,
4210 args: args,
4211 },
4212 }
4213 }
4214
4215 func (cmd *FunctionListCmd) SetVal(val []Library) {
4216 cmd.val = val
4217 }
4218
4219 func (cmd *FunctionListCmd) String() string {
4220 return cmdString(cmd, cmd.val)
4221 }
4222
4223 func (cmd *FunctionListCmd) Val() []Library {
4224 return cmd.val
4225 }
4226
4227 func (cmd *FunctionListCmd) Result() ([]Library, error) {
4228 return cmd.val, cmd.err
4229 }
4230
4231 func (cmd *FunctionListCmd) First() (*Library, error) {
4232 if cmd.err != nil {
4233 return nil, cmd.err
4234 }
4235 if len(cmd.val) > 0 {
4236 return &cmd.val[0], nil
4237 }
4238 return nil, Nil
4239 }
4240
4241 func (cmd *FunctionListCmd) readReply(rd *proto.Reader) (err error) {
4242 n, err := rd.ReadArrayLen()
4243 if err != nil {
4244 return err
4245 }
4246
4247 libraries := make([]Library, n)
4248 for i := 0; i < n; i++ {
4249 nn, err := rd.ReadMapLen()
4250 if err != nil {
4251 return err
4252 }
4253
4254 library := Library{}
4255 for f := 0; f < nn; f++ {
4256 key, err := rd.ReadString()
4257 if err != nil {
4258 return err
4259 }
4260
4261 switch key {
4262 case "library_name":
4263 library.Name, err = rd.ReadString()
4264 case "engine":
4265 library.Engine, err = rd.ReadString()
4266 case "functions":
4267 library.Functions, err = cmd.readFunctions(rd)
4268 case "library_code":
4269 library.Code, err = rd.ReadString()
4270 default:
4271 return fmt.Errorf("redis: function list unexpected key %s", key)
4272 }
4273
4274 if err != nil {
4275 return err
4276 }
4277 }
4278
4279 libraries[i] = library
4280 }
4281 cmd.val = libraries
4282 return nil
4283 }
4284
4285 func (cmd *FunctionListCmd) readFunctions(rd *proto.Reader) ([]Function, error) {
4286 n, err := rd.ReadArrayLen()
4287 if err != nil {
4288 return nil, err
4289 }
4290
4291 functions := make([]Function, n)
4292 for i := 0; i < n; i++ {
4293 nn, err := rd.ReadMapLen()
4294 if err != nil {
4295 return nil, err
4296 }
4297
4298 function := Function{}
4299 for f := 0; f < nn; f++ {
4300 key, err := rd.ReadString()
4301 if err != nil {
4302 return nil, err
4303 }
4304
4305 switch key {
4306 case "name":
4307 if function.Name, err = rd.ReadString(); err != nil {
4308 return nil, err
4309 }
4310 case "description":
4311 if function.Description, err = rd.ReadString(); err != nil && err != Nil {
4312 return nil, err
4313 }
4314 case "flags":
4315
4316 nx, err := rd.ReadArrayLen()
4317 if err != nil {
4318 return nil, err
4319 }
4320
4321 function.Flags = make([]string, nx)
4322 for j := 0; j < nx; j++ {
4323 if function.Flags[j], err = rd.ReadString(); err != nil {
4324 return nil, err
4325 }
4326 }
4327 default:
4328 return nil, fmt.Errorf("redis: function list unexpected key %s", key)
4329 }
4330 }
4331
4332 functions[i] = function
4333 }
4334 return functions, nil
4335 }
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347 type FunctionStats struct {
4348 Engines []Engine
4349 isRunning bool
4350 rs RunningScript
4351 allrs []RunningScript
4352 }
4353
4354 func (fs *FunctionStats) Running() bool {
4355 return fs.isRunning
4356 }
4357
4358 func (fs *FunctionStats) RunningScript() (RunningScript, bool) {
4359 return fs.rs, fs.isRunning
4360 }
4361
4362
4363
4364 func (fs *FunctionStats) AllRunningScripts() []RunningScript {
4365 return fs.allrs
4366 }
4367
4368 type RunningScript struct {
4369 Name string
4370 Command []string
4371 Duration time.Duration
4372 }
4373
4374 type Engine struct {
4375 Language string
4376 LibrariesCount int64
4377 FunctionsCount int64
4378 }
4379
4380 type FunctionStatsCmd struct {
4381 baseCmd
4382 val FunctionStats
4383 }
4384
4385 var _ Cmder = (*FunctionStatsCmd)(nil)
4386
4387 func NewFunctionStatsCmd(ctx context.Context, args ...interface{}) *FunctionStatsCmd {
4388 return &FunctionStatsCmd{
4389 baseCmd: baseCmd{
4390 ctx: ctx,
4391 args: args,
4392 },
4393 }
4394 }
4395
4396 func (cmd *FunctionStatsCmd) SetVal(val FunctionStats) {
4397 cmd.val = val
4398 }
4399
4400 func (cmd *FunctionStatsCmd) String() string {
4401 return cmdString(cmd, cmd.val)
4402 }
4403
4404 func (cmd *FunctionStatsCmd) Val() FunctionStats {
4405 return cmd.val
4406 }
4407
4408 func (cmd *FunctionStatsCmd) Result() (FunctionStats, error) {
4409 return cmd.val, cmd.err
4410 }
4411
4412 func (cmd *FunctionStatsCmd) readReply(rd *proto.Reader) (err error) {
4413 n, err := rd.ReadMapLen()
4414 if err != nil {
4415 return err
4416 }
4417
4418 var key string
4419 var result FunctionStats
4420 for f := 0; f < n; f++ {
4421 key, err = rd.ReadString()
4422 if err != nil {
4423 return err
4424 }
4425
4426 switch key {
4427 case "running_script":
4428 result.rs, result.isRunning, err = cmd.readRunningScript(rd)
4429 case "engines":
4430 result.Engines, err = cmd.readEngines(rd)
4431 case "all_running_scripts":
4432 result.allrs, result.isRunning, err = cmd.readRunningScripts(rd)
4433 default:
4434 return fmt.Errorf("redis: function stats unexpected key %s", key)
4435 }
4436
4437 if err != nil {
4438 return err
4439 }
4440 }
4441
4442 cmd.val = result
4443 return nil
4444 }
4445
4446 func (cmd *FunctionStatsCmd) readRunningScript(rd *proto.Reader) (RunningScript, bool, error) {
4447 err := rd.ReadFixedMapLen(3)
4448 if err != nil {
4449 if err == Nil {
4450 return RunningScript{}, false, nil
4451 }
4452 return RunningScript{}, false, err
4453 }
4454
4455 var runningScript RunningScript
4456 for i := 0; i < 3; i++ {
4457 key, err := rd.ReadString()
4458 if err != nil {
4459 return RunningScript{}, false, err
4460 }
4461
4462 switch key {
4463 case "name":
4464 runningScript.Name, err = rd.ReadString()
4465 case "duration_ms":
4466 runningScript.Duration, err = cmd.readDuration(rd)
4467 case "command":
4468 runningScript.Command, err = cmd.readCommand(rd)
4469 default:
4470 return RunningScript{}, false, fmt.Errorf("redis: function stats unexpected running_script key %s", key)
4471 }
4472
4473 if err != nil {
4474 return RunningScript{}, false, err
4475 }
4476 }
4477
4478 return runningScript, true, nil
4479 }
4480
4481 func (cmd *FunctionStatsCmd) readEngines(rd *proto.Reader) ([]Engine, error) {
4482 n, err := rd.ReadMapLen()
4483 if err != nil {
4484 return nil, err
4485 }
4486
4487 engines := make([]Engine, 0, n)
4488 for i := 0; i < n; i++ {
4489 engine := Engine{}
4490 engine.Language, err = rd.ReadString()
4491 if err != nil {
4492 return nil, err
4493 }
4494
4495 err = rd.ReadFixedMapLen(2)
4496 if err != nil {
4497 return nil, fmt.Errorf("redis: function stats unexpected %s engine map length", engine.Language)
4498 }
4499
4500 for i := 0; i < 2; i++ {
4501 key, err := rd.ReadString()
4502 switch key {
4503 case "libraries_count":
4504 engine.LibrariesCount, err = rd.ReadInt()
4505 case "functions_count":
4506 engine.FunctionsCount, err = rd.ReadInt()
4507 }
4508 if err != nil {
4509 return nil, err
4510 }
4511 }
4512
4513 engines = append(engines, engine)
4514 }
4515 return engines, nil
4516 }
4517
4518 func (cmd *FunctionStatsCmd) readDuration(rd *proto.Reader) (time.Duration, error) {
4519 t, err := rd.ReadInt()
4520 if err != nil {
4521 return time.Duration(0), err
4522 }
4523 return time.Duration(t) * time.Millisecond, nil
4524 }
4525
4526 func (cmd *FunctionStatsCmd) readCommand(rd *proto.Reader) ([]string, error) {
4527 n, err := rd.ReadArrayLen()
4528 if err != nil {
4529 return nil, err
4530 }
4531
4532 command := make([]string, 0, n)
4533 for i := 0; i < n; i++ {
4534 x, err := rd.ReadString()
4535 if err != nil {
4536 return nil, err
4537 }
4538 command = append(command, x)
4539 }
4540
4541 return command, nil
4542 }
4543
4544 func (cmd *FunctionStatsCmd) readRunningScripts(rd *proto.Reader) ([]RunningScript, bool, error) {
4545 n, err := rd.ReadArrayLen()
4546 if err != nil {
4547 return nil, false, err
4548 }
4549
4550 runningScripts := make([]RunningScript, 0, n)
4551 for i := 0; i < n; i++ {
4552 rs, _, err := cmd.readRunningScript(rd)
4553 if err != nil {
4554 return nil, false, err
4555 }
4556 runningScripts = append(runningScripts, rs)
4557 }
4558
4559 return runningScripts, len(runningScripts) > 0, nil
4560 }
4561
4562
4563
4564
4565 type LCSQuery struct {
4566 Key1 string
4567 Key2 string
4568 Len bool
4569 Idx bool
4570 MinMatchLen int
4571 WithMatchLen bool
4572 }
4573
4574
4575 type LCSMatch struct {
4576 MatchString string
4577 Matches []LCSMatchedPosition
4578 Len int64
4579 }
4580
4581 type LCSMatchedPosition struct {
4582 Key1 LCSPosition
4583 Key2 LCSPosition
4584
4585
4586 MatchLen int64
4587 }
4588
4589 type LCSPosition struct {
4590 Start int64
4591 End int64
4592 }
4593
4594 type LCSCmd struct {
4595 baseCmd
4596
4597
4598
4599
4600 readType uint8
4601 val *LCSMatch
4602 }
4603
4604 func NewLCSCmd(ctx context.Context, q *LCSQuery) *LCSCmd {
4605 args := make([]interface{}, 3, 7)
4606 args[0] = "lcs"
4607 args[1] = q.Key1
4608 args[2] = q.Key2
4609
4610 cmd := &LCSCmd{readType: 1}
4611 if q.Len {
4612 cmd.readType = 2
4613 args = append(args, "len")
4614 } else if q.Idx {
4615 cmd.readType = 3
4616 args = append(args, "idx")
4617 if q.MinMatchLen != 0 {
4618 args = append(args, "minmatchlen", q.MinMatchLen)
4619 }
4620 if q.WithMatchLen {
4621 args = append(args, "withmatchlen")
4622 }
4623 }
4624 cmd.baseCmd = baseCmd{
4625 ctx: ctx,
4626 args: args,
4627 }
4628
4629 return cmd
4630 }
4631
4632 func (cmd *LCSCmd) SetVal(val *LCSMatch) {
4633 cmd.val = val
4634 }
4635
4636 func (cmd *LCSCmd) String() string {
4637 return cmdString(cmd, cmd.val)
4638 }
4639
4640 func (cmd *LCSCmd) Val() *LCSMatch {
4641 return cmd.val
4642 }
4643
4644 func (cmd *LCSCmd) Result() (*LCSMatch, error) {
4645 return cmd.val, cmd.err
4646 }
4647
4648 func (cmd *LCSCmd) readReply(rd *proto.Reader) (err error) {
4649 lcs := &LCSMatch{}
4650 switch cmd.readType {
4651 case 1:
4652
4653 if lcs.MatchString, err = rd.ReadString(); err != nil {
4654 return err
4655 }
4656 case 2:
4657
4658 if lcs.Len, err = rd.ReadInt(); err != nil {
4659 return err
4660 }
4661 case 3:
4662
4663 if err = rd.ReadFixedMapLen(2); err != nil {
4664 return err
4665 }
4666
4667
4668 for i := 0; i < 2; i++ {
4669 key, err := rd.ReadString()
4670 if err != nil {
4671 return err
4672 }
4673
4674 switch key {
4675 case "matches":
4676
4677 if lcs.Matches, err = cmd.readMatchedPositions(rd); err != nil {
4678 return err
4679 }
4680 case "len":
4681
4682 if lcs.Len, err = rd.ReadInt(); err != nil {
4683 return err
4684 }
4685 }
4686 }
4687 }
4688
4689 cmd.val = lcs
4690 return nil
4691 }
4692
4693 func (cmd *LCSCmd) readMatchedPositions(rd *proto.Reader) ([]LCSMatchedPosition, error) {
4694 n, err := rd.ReadArrayLen()
4695 if err != nil {
4696 return nil, err
4697 }
4698
4699 positions := make([]LCSMatchedPosition, n)
4700 for i := 0; i < n; i++ {
4701 pn, err := rd.ReadArrayLen()
4702 if err != nil {
4703 return nil, err
4704 }
4705
4706 if positions[i].Key1, err = cmd.readPosition(rd); err != nil {
4707 return nil, err
4708 }
4709 if positions[i].Key2, err = cmd.readPosition(rd); err != nil {
4710 return nil, err
4711 }
4712
4713
4714 if pn > 2 {
4715 if positions[i].MatchLen, err = rd.ReadInt(); err != nil {
4716 return nil, err
4717 }
4718 }
4719 }
4720
4721 return positions, nil
4722 }
4723
4724 func (cmd *LCSCmd) readPosition(rd *proto.Reader) (pos LCSPosition, err error) {
4725 if err = rd.ReadFixedArrayLen(2); err != nil {
4726 return pos, err
4727 }
4728 if pos.Start, err = rd.ReadInt(); err != nil {
4729 return pos, err
4730 }
4731 if pos.End, err = rd.ReadInt(); err != nil {
4732 return pos, err
4733 }
4734
4735 return pos, nil
4736 }
4737
4738
4739
4740 type KeyFlags struct {
4741 Key string
4742 Flags []string
4743 }
4744
4745 type KeyFlagsCmd struct {
4746 baseCmd
4747
4748 val []KeyFlags
4749 }
4750
4751 var _ Cmder = (*KeyFlagsCmd)(nil)
4752
4753 func NewKeyFlagsCmd(ctx context.Context, args ...interface{}) *KeyFlagsCmd {
4754 return &KeyFlagsCmd{
4755 baseCmd: baseCmd{
4756 ctx: ctx,
4757 args: args,
4758 },
4759 }
4760 }
4761
4762 func (cmd *KeyFlagsCmd) SetVal(val []KeyFlags) {
4763 cmd.val = val
4764 }
4765
4766 func (cmd *KeyFlagsCmd) Val() []KeyFlags {
4767 return cmd.val
4768 }
4769
4770 func (cmd *KeyFlagsCmd) Result() ([]KeyFlags, error) {
4771 return cmd.val, cmd.err
4772 }
4773
4774 func (cmd *KeyFlagsCmd) String() string {
4775 return cmdString(cmd, cmd.val)
4776 }
4777
4778 func (cmd *KeyFlagsCmd) readReply(rd *proto.Reader) error {
4779 n, err := rd.ReadArrayLen()
4780 if err != nil {
4781 return err
4782 }
4783
4784 if n == 0 {
4785 cmd.val = make([]KeyFlags, 0)
4786 return nil
4787 }
4788
4789 cmd.val = make([]KeyFlags, n)
4790
4791 for i := 0; i < len(cmd.val); i++ {
4792
4793 if err = rd.ReadFixedArrayLen(2); err != nil {
4794 return err
4795 }
4796
4797 if cmd.val[i].Key, err = rd.ReadString(); err != nil {
4798 return err
4799 }
4800 flagsLen, err := rd.ReadArrayLen()
4801 if err != nil {
4802 return err
4803 }
4804 cmd.val[i].Flags = make([]string, flagsLen)
4805
4806 for j := 0; j < flagsLen; j++ {
4807 if cmd.val[i].Flags[j], err = rd.ReadString(); err != nil {
4808 return err
4809 }
4810 }
4811 }
4812
4813 return nil
4814 }
4815
4816
4817
4818 type ClusterLink struct {
4819 Direction string
4820 Node string
4821 CreateTime int64
4822 Events string
4823 SendBufferAllocated int64
4824 SendBufferUsed int64
4825 }
4826
4827 type ClusterLinksCmd struct {
4828 baseCmd
4829
4830 val []ClusterLink
4831 }
4832
4833 var _ Cmder = (*ClusterLinksCmd)(nil)
4834
4835 func NewClusterLinksCmd(ctx context.Context, args ...interface{}) *ClusterLinksCmd {
4836 return &ClusterLinksCmd{
4837 baseCmd: baseCmd{
4838 ctx: ctx,
4839 args: args,
4840 },
4841 }
4842 }
4843
4844 func (cmd *ClusterLinksCmd) SetVal(val []ClusterLink) {
4845 cmd.val = val
4846 }
4847
4848 func (cmd *ClusterLinksCmd) Val() []ClusterLink {
4849 return cmd.val
4850 }
4851
4852 func (cmd *ClusterLinksCmd) Result() ([]ClusterLink, error) {
4853 return cmd.val, cmd.err
4854 }
4855
4856 func (cmd *ClusterLinksCmd) String() string {
4857 return cmdString(cmd, cmd.val)
4858 }
4859
4860 func (cmd *ClusterLinksCmd) readReply(rd *proto.Reader) error {
4861 n, err := rd.ReadArrayLen()
4862 if err != nil {
4863 return err
4864 }
4865 cmd.val = make([]ClusterLink, n)
4866
4867 for i := 0; i < len(cmd.val); i++ {
4868 m, err := rd.ReadMapLen()
4869 if err != nil {
4870 return err
4871 }
4872
4873 for j := 0; j < m; j++ {
4874 key, err := rd.ReadString()
4875 if err != nil {
4876 return err
4877 }
4878
4879 switch key {
4880 case "direction":
4881 cmd.val[i].Direction, err = rd.ReadString()
4882 case "node":
4883 cmd.val[i].Node, err = rd.ReadString()
4884 case "create-time":
4885 cmd.val[i].CreateTime, err = rd.ReadInt()
4886 case "events":
4887 cmd.val[i].Events, err = rd.ReadString()
4888 case "send-buffer-allocated":
4889 cmd.val[i].SendBufferAllocated, err = rd.ReadInt()
4890 case "send-buffer-used":
4891 cmd.val[i].SendBufferUsed, err = rd.ReadInt()
4892 default:
4893 return fmt.Errorf("redis: unexpected key %q in CLUSTER LINKS reply", key)
4894 }
4895
4896 if err != nil {
4897 return err
4898 }
4899 }
4900 }
4901
4902 return nil
4903 }
4904
4905
4906
4907 type SlotRange struct {
4908 Start int64
4909 End int64
4910 }
4911
4912 type Node struct {
4913 ID string
4914 Endpoint string
4915 IP string
4916 Hostname string
4917 Port int64
4918 TLSPort int64
4919 Role string
4920 ReplicationOffset int64
4921 Health string
4922 }
4923
4924 type ClusterShard struct {
4925 Slots []SlotRange
4926 Nodes []Node
4927 }
4928
4929 type ClusterShardsCmd struct {
4930 baseCmd
4931
4932 val []ClusterShard
4933 }
4934
4935 var _ Cmder = (*ClusterShardsCmd)(nil)
4936
4937 func NewClusterShardsCmd(ctx context.Context, args ...interface{}) *ClusterShardsCmd {
4938 return &ClusterShardsCmd{
4939 baseCmd: baseCmd{
4940 ctx: ctx,
4941 args: args,
4942 },
4943 }
4944 }
4945
4946 func (cmd *ClusterShardsCmd) SetVal(val []ClusterShard) {
4947 cmd.val = val
4948 }
4949
4950 func (cmd *ClusterShardsCmd) Val() []ClusterShard {
4951 return cmd.val
4952 }
4953
4954 func (cmd *ClusterShardsCmd) Result() ([]ClusterShard, error) {
4955 return cmd.val, cmd.err
4956 }
4957
4958 func (cmd *ClusterShardsCmd) String() string {
4959 return cmdString(cmd, cmd.val)
4960 }
4961
4962 func (cmd *ClusterShardsCmd) readReply(rd *proto.Reader) error {
4963 n, err := rd.ReadArrayLen()
4964 if err != nil {
4965 return err
4966 }
4967 cmd.val = make([]ClusterShard, n)
4968
4969 for i := 0; i < n; i++ {
4970 m, err := rd.ReadMapLen()
4971 if err != nil {
4972 return err
4973 }
4974
4975 for j := 0; j < m; j++ {
4976 key, err := rd.ReadString()
4977 if err != nil {
4978 return err
4979 }
4980
4981 switch key {
4982 case "slots":
4983 l, err := rd.ReadArrayLen()
4984 if err != nil {
4985 return err
4986 }
4987 for k := 0; k < l; k += 2 {
4988 start, err := rd.ReadInt()
4989 if err != nil {
4990 return err
4991 }
4992
4993 end, err := rd.ReadInt()
4994 if err != nil {
4995 return err
4996 }
4997
4998 cmd.val[i].Slots = append(cmd.val[i].Slots, SlotRange{Start: start, End: end})
4999 }
5000 case "nodes":
5001 nodesLen, err := rd.ReadArrayLen()
5002 if err != nil {
5003 return err
5004 }
5005 cmd.val[i].Nodes = make([]Node, nodesLen)
5006 for k := 0; k < nodesLen; k++ {
5007 nodeMapLen, err := rd.ReadMapLen()
5008 if err != nil {
5009 return err
5010 }
5011
5012 for l := 0; l < nodeMapLen; l++ {
5013 nodeKey, err := rd.ReadString()
5014 if err != nil {
5015 return err
5016 }
5017
5018 switch nodeKey {
5019 case "id":
5020 cmd.val[i].Nodes[k].ID, err = rd.ReadString()
5021 case "endpoint":
5022 cmd.val[i].Nodes[k].Endpoint, err = rd.ReadString()
5023 case "ip":
5024 cmd.val[i].Nodes[k].IP, err = rd.ReadString()
5025 case "hostname":
5026 cmd.val[i].Nodes[k].Hostname, err = rd.ReadString()
5027 case "port":
5028 cmd.val[i].Nodes[k].Port, err = rd.ReadInt()
5029 case "tls-port":
5030 cmd.val[i].Nodes[k].TLSPort, err = rd.ReadInt()
5031 case "role":
5032 cmd.val[i].Nodes[k].Role, err = rd.ReadString()
5033 case "replication-offset":
5034 cmd.val[i].Nodes[k].ReplicationOffset, err = rd.ReadInt()
5035 case "health":
5036 cmd.val[i].Nodes[k].Health, err = rd.ReadString()
5037 default:
5038 return fmt.Errorf("redis: unexpected key %q in CLUSTER SHARDS node reply", nodeKey)
5039 }
5040
5041 if err != nil {
5042 return err
5043 }
5044 }
5045 }
5046 default:
5047 return fmt.Errorf("redis: unexpected key %q in CLUSTER SHARDS reply", key)
5048 }
5049 }
5050 }
5051
5052 return nil
5053 }
5054
5055
5056
5057 type RankScore struct {
5058 Rank int64
5059 Score float64
5060 }
5061
5062 type RankWithScoreCmd struct {
5063 baseCmd
5064
5065 val RankScore
5066 }
5067
5068 var _ Cmder = (*RankWithScoreCmd)(nil)
5069
5070 func NewRankWithScoreCmd(ctx context.Context, args ...interface{}) *RankWithScoreCmd {
5071 return &RankWithScoreCmd{
5072 baseCmd: baseCmd{
5073 ctx: ctx,
5074 args: args,
5075 },
5076 }
5077 }
5078
5079 func (cmd *RankWithScoreCmd) SetVal(val RankScore) {
5080 cmd.val = val
5081 }
5082
5083 func (cmd *RankWithScoreCmd) Val() RankScore {
5084 return cmd.val
5085 }
5086
5087 func (cmd *RankWithScoreCmd) Result() (RankScore, error) {
5088 return cmd.val, cmd.err
5089 }
5090
5091 func (cmd *RankWithScoreCmd) String() string {
5092 return cmdString(cmd, cmd.val)
5093 }
5094
5095 func (cmd *RankWithScoreCmd) readReply(rd *proto.Reader) error {
5096 if err := rd.ReadFixedArrayLen(2); err != nil {
5097 return err
5098 }
5099
5100 rank, err := rd.ReadInt()
5101 if err != nil {
5102 return err
5103 }
5104
5105 score, err := rd.ReadFloat()
5106 if err != nil {
5107 return err
5108 }
5109
5110 cmd.val = RankScore{Rank: rank, Score: score}
5111
5112 return nil
5113 }
5114
5115
5116
5117
5118 type ClientFlags uint64
5119
5120 const (
5121 ClientSlave ClientFlags = 1 << 0
5122 ClientMaster ClientFlags = 1 << 1
5123 ClientMonitor ClientFlags = 1 << 2
5124 ClientMulti ClientFlags = 1 << 3
5125 ClientBlocked ClientFlags = 1 << 4
5126 ClientDirtyCAS ClientFlags = 1 << 5
5127 ClientCloseAfterReply ClientFlags = 1 << 6
5128 ClientUnBlocked ClientFlags = 1 << 7
5129 ClientScript ClientFlags = 1 << 8
5130 ClientAsking ClientFlags = 1 << 9
5131 ClientCloseASAP ClientFlags = 1 << 10
5132 ClientUnixSocket ClientFlags = 1 << 11
5133 ClientDirtyExec ClientFlags = 1 << 12
5134 ClientMasterForceReply ClientFlags = 1 << 13
5135 ClientForceAOF ClientFlags = 1 << 14
5136 ClientForceRepl ClientFlags = 1 << 15
5137 ClientPrePSync ClientFlags = 1 << 16
5138 ClientReadOnly ClientFlags = 1 << 17
5139 ClientPubSub ClientFlags = 1 << 18
5140 ClientPreventAOFProp ClientFlags = 1 << 19
5141 ClientPreventReplProp ClientFlags = 1 << 20
5142 ClientPreventProp ClientFlags = ClientPreventAOFProp | ClientPreventReplProp
5143 ClientPendingWrite ClientFlags = 1 << 21
5144 ClientReplyOff ClientFlags = 1 << 22
5145 ClientReplySkipNext ClientFlags = 1 << 23
5146 ClientReplySkip ClientFlags = 1 << 24
5147 ClientLuaDebug ClientFlags = 1 << 25
5148 ClientLuaDebugSync ClientFlags = 1 << 26
5149 ClientModule ClientFlags = 1 << 27
5150 ClientProtected ClientFlags = 1 << 28
5151 ClientExecutingCommand ClientFlags = 1 << 29
5155 ClientPendingCommand ClientFlags = 1 << 30
5156 ClientTracking ClientFlags = 1 << 31
5157 ClientTrackingBrokenRedir ClientFlags = 1 << 32
5158 ClientTrackingBCAST ClientFlags = 1 << 33
5159 ClientTrackingOptIn ClientFlags = 1 << 34
5160 ClientTrackingOptOut ClientFlags = 1 << 35
5161 ClientTrackingCaching ClientFlags = 1 << 36
5162 ClientTrackingNoLoop ClientFlags = 1 << 37
5163 ClientInTimeoutTable ClientFlags = 1 << 38
5164 ClientProtocolError ClientFlags = 1 << 39
5165 ClientCloseAfterCommand ClientFlags = 1 << 40
5166 ClientDenyBlocking ClientFlags = 1 << 41
5167 ClientReplRDBOnly ClientFlags = 1 << 42
5168 ClientNoEvict ClientFlags = 1 << 43
5169 ClientAllowOOM ClientFlags = 1 << 44
5170 ClientNoTouch ClientFlags = 1 << 45
5171 ClientPushing ClientFlags = 1 << 46
5172 )
5173
5174
5175 type ClientInfo struct {
5176 ID int64
5177 Addr string
5178 LAddr string
5179 FD int64
5180 Name string
5181 Age time.Duration
5182 Idle time.Duration
5183 Flags ClientFlags
5184 DB int
5185 Sub int
5186 PSub int
5187 SSub int
5188 Multi int
5189 Watch int
5190 QueryBuf int
5191 QueryBufFree int
5192 ArgvMem int
5193 MultiMem int
5194 BufferSize int
5195 BufferPeak int
5196 OutputBufferLength int
5197 OutputListLength int
5198 OutputMemory int
5199 TotalMemory int
5200 TotalNetIn int
5201 TotalNetOut int
5202 TotalCmds int
5203 IoThread int
5204 Events string
5205 LastCmd string
5206 User string
5207 Redir int64
5208 Resp int
5209 LibName string
5210 LibVer string
5211 }
5212
5213 type ClientInfoCmd struct {
5214 baseCmd
5215
5216 val *ClientInfo
5217 }
5218
5219 var _ Cmder = (*ClientInfoCmd)(nil)
5220
5221 func NewClientInfoCmd(ctx context.Context, args ...interface{}) *ClientInfoCmd {
5222 return &ClientInfoCmd{
5223 baseCmd: baseCmd{
5224 ctx: ctx,
5225 args: args,
5226 },
5227 }
5228 }
5229
5230 func (cmd *ClientInfoCmd) SetVal(val *ClientInfo) {
5231 cmd.val = val
5232 }
5233
5234 func (cmd *ClientInfoCmd) String() string {
5235 return cmdString(cmd, cmd.val)
5236 }
5237
5238 func (cmd *ClientInfoCmd) Val() *ClientInfo {
5239 return cmd.val
5240 }
5241
5242 func (cmd *ClientInfoCmd) Result() (*ClientInfo, error) {
5243 return cmd.val, cmd.err
5244 }
5245
5246 func (cmd *ClientInfoCmd) readReply(rd *proto.Reader) (err error) {
5247 txt, err := rd.ReadString()
5248 if err != nil {
5249 return err
5250 }
5251
5252
5253
5254
5255
5256 cmd.val, err = parseClientInfo(strings.TrimSpace(txt))
5257 return err
5258 }
5259
5260
5261 func parseClientInfo(txt string) (info *ClientInfo, err error) {
5262 info = &ClientInfo{}
5263 for _, s := range strings.Split(txt, " ") {
5264 kv := strings.Split(s, "=")
5265 if len(kv) != 2 {
5266 return nil, fmt.Errorf("redis: unexpected client info data (%s)", s)
5267 }
5268 key, val := kv[0], kv[1]
5269
5270 switch key {
5271 case "id":
5272 info.ID, err = strconv.ParseInt(val, 10, 64)
5273 case "addr":
5274 info.Addr = val
5275 case "laddr":
5276 info.LAddr = val
5277 case "fd":
5278 info.FD, err = strconv.ParseInt(val, 10, 64)
5279 case "name":
5280 info.Name = val
5281 case "age":
5282 var age int
5283 if age, err = strconv.Atoi(val); err == nil {
5284 info.Age = time.Duration(age) * time.Second
5285 }
5286 case "idle":
5287 var idle int
5288 if idle, err = strconv.Atoi(val); err == nil {
5289 info.Idle = time.Duration(idle) * time.Second
5290 }
5291 case "flags":
5292 if val == "N" {
5293 break
5294 }
5295
5296 for i := 0; i < len(val); i++ {
5297 switch val[i] {
5298 case 'S':
5299 info.Flags |= ClientSlave
5300 case 'O':
5301 info.Flags |= ClientSlave | ClientMonitor
5302 case 'M':
5303 info.Flags |= ClientMaster
5304 case 'P':
5305 info.Flags |= ClientPubSub
5306 case 'x':
5307 info.Flags |= ClientMulti
5308 case 'b':
5309 info.Flags |= ClientBlocked
5310 case 't':
5311 info.Flags |= ClientTracking
5312 case 'R':
5313 info.Flags |= ClientTrackingBrokenRedir
5314 case 'B':
5315 info.Flags |= ClientTrackingBCAST
5316 case 'd':
5317 info.Flags |= ClientDirtyCAS
5318 case 'c':
5319 info.Flags |= ClientCloseAfterCommand
5320 case 'u':
5321 info.Flags |= ClientUnBlocked
5322 case 'A':
5323 info.Flags |= ClientCloseASAP
5324 case 'U':
5325 info.Flags |= ClientUnixSocket
5326 case 'r':
5327 info.Flags |= ClientReadOnly
5328 case 'e':
5329 info.Flags |= ClientNoEvict
5330 case 'T':
5331 info.Flags |= ClientNoTouch
5332 default:
5333 return nil, fmt.Errorf("redis: unexpected client info flags(%s)", string(val[i]))
5334 }
5335 }
5336 case "db":
5337 info.DB, err = strconv.Atoi(val)
5338 case "sub":
5339 info.Sub, err = strconv.Atoi(val)
5340 case "psub":
5341 info.PSub, err = strconv.Atoi(val)
5342 case "ssub":
5343 info.SSub, err = strconv.Atoi(val)
5344 case "multi":
5345 info.Multi, err = strconv.Atoi(val)
5346 case "watch":
5347 info.Watch, err = strconv.Atoi(val)
5348 case "qbuf":
5349 info.QueryBuf, err = strconv.Atoi(val)
5350 case "qbuf-free":
5351 info.QueryBufFree, err = strconv.Atoi(val)
5352 case "argv-mem":
5353 info.ArgvMem, err = strconv.Atoi(val)
5354 case "multi-mem":
5355 info.MultiMem, err = strconv.Atoi(val)
5356 case "rbs":
5357 info.BufferSize, err = strconv.Atoi(val)
5358 case "rbp":
5359 info.BufferPeak, err = strconv.Atoi(val)
5360 case "obl":
5361 info.OutputBufferLength, err = strconv.Atoi(val)
5362 case "oll":
5363 info.OutputListLength, err = strconv.Atoi(val)
5364 case "omem":
5365 info.OutputMemory, err = strconv.Atoi(val)
5366 case "tot-mem":
5367 info.TotalMemory, err = strconv.Atoi(val)
5368 case "tot-net-in":
5369 info.TotalNetIn, err = strconv.Atoi(val)
5370 case "tot-net-out":
5371 info.TotalNetOut, err = strconv.Atoi(val)
5372 case "tot-cmds":
5373 info.TotalCmds, err = strconv.Atoi(val)
5374 case "events":
5375 info.Events = val
5376 case "cmd":
5377 info.LastCmd = val
5378 case "user":
5379 info.User = val
5380 case "redir":
5381 info.Redir, err = strconv.ParseInt(val, 10, 64)
5382 case "resp":
5383 info.Resp, err = strconv.Atoi(val)
5384 case "lib-name":
5385 info.LibName = val
5386 case "lib-ver":
5387 info.LibVer = val
5388 case "io-thread":
5389 info.IoThread, err = strconv.Atoi(val)
5390 default:
5391 return nil, fmt.Errorf("redis: unexpected client info key(%s)", key)
5392 }
5393
5394 if err != nil {
5395 return nil, err
5396 }
5397 }
5398
5399 return info, nil
5400 }
5401
5402
5403
5404 type ACLLogEntry struct {
5405 Count int64
5406 Reason string
5407 Context string
5408 Object string
5409 Username string
5410 AgeSeconds float64
5411 ClientInfo *ClientInfo
5412 EntryID int64
5413 TimestampCreated int64
5414 TimestampLastUpdated int64
5415 }
5416
5417 type ACLLogCmd struct {
5418 baseCmd
5419
5420 val []*ACLLogEntry
5421 }
5422
5423 var _ Cmder = (*ACLLogCmd)(nil)
5424
5425 func NewACLLogCmd(ctx context.Context, args ...interface{}) *ACLLogCmd {
5426 return &ACLLogCmd{
5427 baseCmd: baseCmd{
5428 ctx: ctx,
5429 args: args,
5430 },
5431 }
5432 }
5433
5434 func (cmd *ACLLogCmd) SetVal(val []*ACLLogEntry) {
5435 cmd.val = val
5436 }
5437
5438 func (cmd *ACLLogCmd) Val() []*ACLLogEntry {
5439 return cmd.val
5440 }
5441
5442 func (cmd *ACLLogCmd) Result() ([]*ACLLogEntry, error) {
5443 return cmd.val, cmd.err
5444 }
5445
5446 func (cmd *ACLLogCmd) String() string {
5447 return cmdString(cmd, cmd.val)
5448 }
5449
5450 func (cmd *ACLLogCmd) readReply(rd *proto.Reader) error {
5451 n, err := rd.ReadArrayLen()
5452 if err != nil {
5453 return err
5454 }
5455
5456 cmd.val = make([]*ACLLogEntry, n)
5457 for i := 0; i < n; i++ {
5458 cmd.val[i] = &ACLLogEntry{}
5459 entry := cmd.val[i]
5460 respLen, err := rd.ReadMapLen()
5461 if err != nil {
5462 return err
5463 }
5464 for j := 0; j < respLen; j++ {
5465 key, err := rd.ReadString()
5466 if err != nil {
5467 return err
5468 }
5469
5470 switch key {
5471 case "count":
5472 entry.Count, err = rd.ReadInt()
5473 case "reason":
5474 entry.Reason, err = rd.ReadString()
5475 case "context":
5476 entry.Context, err = rd.ReadString()
5477 case "object":
5478 entry.Object, err = rd.ReadString()
5479 case "username":
5480 entry.Username, err = rd.ReadString()
5481 case "age-seconds":
5482 entry.AgeSeconds, err = rd.ReadFloat()
5483 case "client-info":
5484 txt, err := rd.ReadString()
5485 if err != nil {
5486 return err
5487 }
5488 entry.ClientInfo, err = parseClientInfo(strings.TrimSpace(txt))
5489 if err != nil {
5490 return err
5491 }
5492 case "entry-id":
5493 entry.EntryID, err = rd.ReadInt()
5494 case "timestamp-created":
5495 entry.TimestampCreated, err = rd.ReadInt()
5496 case "timestamp-last-updated":
5497 entry.TimestampLastUpdated, err = rd.ReadInt()
5498 default:
5499 return fmt.Errorf("redis: unexpected key %q in ACL LOG reply", key)
5500 }
5501
5502 if err != nil {
5503 return err
5504 }
5505 }
5506 }
5507
5508 return nil
5509 }
5510
5511
5512 type LibraryInfo struct {
5513 LibName *string
5514 LibVer *string
5515 }
5516
5517
5518 func WithLibraryName(libName string) LibraryInfo {
5519 return LibraryInfo{LibName: &libName}
5520 }
5521
5522
5523 func WithLibraryVersion(libVer string) LibraryInfo {
5524 return LibraryInfo{LibVer: &libVer}
5525 }
5526
5527
5528
5529 type InfoCmd struct {
5530 baseCmd
5531 val map[string]map[string]string
5532 }
5533
5534 var _ Cmder = (*InfoCmd)(nil)
5535
5536 func NewInfoCmd(ctx context.Context, args ...interface{}) *InfoCmd {
5537 return &InfoCmd{
5538 baseCmd: baseCmd{
5539 ctx: ctx,
5540 args: args,
5541 },
5542 }
5543 }
5544
5545 func (cmd *InfoCmd) SetVal(val map[string]map[string]string) {
5546 cmd.val = val
5547 }
5548
5549 func (cmd *InfoCmd) Val() map[string]map[string]string {
5550 return cmd.val
5551 }
5552
5553 func (cmd *InfoCmd) Result() (map[string]map[string]string, error) {
5554 return cmd.val, cmd.err
5555 }
5556
5557 func (cmd *InfoCmd) String() string {
5558 return cmdString(cmd, cmd.val)
5559 }
5560
5561 func (cmd *InfoCmd) readReply(rd *proto.Reader) error {
5562 val, err := rd.ReadString()
5563 if err != nil {
5564 return err
5565 }
5566
5567 section := ""
5568 scanner := bufio.NewScanner(strings.NewReader(val))
5569 for scanner.Scan() {
5570 line := scanner.Text()
5571 if strings.HasPrefix(line, "#") {
5572 if cmd.val == nil {
5573 cmd.val = make(map[string]map[string]string)
5574 }
5575 section = strings.TrimPrefix(line, "# ")
5576 cmd.val[section] = make(map[string]string)
5577 } else if line != "" {
5578 if section == "Modules" {
5579 moduleRe := regexp.MustCompile(`module:name=(.+?),(.+)$`)
5580 kv := moduleRe.FindStringSubmatch(line)
5581 if len(kv) == 3 {
5582 cmd.val[section][kv[1]] = kv[2]
5583 }
5584 } else {
5585 kv := strings.SplitN(line, ":", 2)
5586 if len(kv) == 2 {
5587 cmd.val[section][kv[0]] = kv[1]
5588 }
5589 }
5590 }
5591 }
5592
5593 return nil
5594 }
5595
5596 func (cmd *InfoCmd) Item(section, key string) string {
5597 if cmd.val == nil {
5598 return ""
5599 } else if cmd.val[section] == nil {
5600 return ""
5601 } else {
5602 return cmd.val[section][key]
5603 }
5604 }
5605
5606 type MonitorStatus int
5607
5608 const (
5609 monitorStatusIdle MonitorStatus = iota
5610 monitorStatusStart
5611 monitorStatusStop
5612 )
5613
5614 type MonitorCmd struct {
5615 baseCmd
5616 ch chan string
5617 status MonitorStatus
5618 mu sync.Mutex
5619 }
5620
5621 func newMonitorCmd(ctx context.Context, ch chan string) *MonitorCmd {
5622 return &MonitorCmd{
5623 baseCmd: baseCmd{
5624 ctx: ctx,
5625 args: []interface{}{"monitor"},
5626 },
5627 ch: ch,
5628 status: monitorStatusIdle,
5629 mu: sync.Mutex{},
5630 }
5631 }
5632
5633 func (cmd *MonitorCmd) String() string {
5634 return cmdString(cmd, nil)
5635 }
5636
5637 func (cmd *MonitorCmd) readReply(rd *proto.Reader) error {
5638 ctx, cancel := context.WithCancel(cmd.ctx)
5639 go func(ctx context.Context) {
5640 for {
5641 select {
5642 case <-ctx.Done():
5643 return
5644 default:
5645 err := cmd.readMonitor(rd, cancel)
5646 if err != nil {
5647 cmd.err = err
5648 return
5649 }
5650 }
5651 }
5652 }(ctx)
5653 return nil
5654 }
5655
5656 func (cmd *MonitorCmd) readMonitor(rd *proto.Reader, cancel context.CancelFunc) error {
5657 for {
5658 cmd.mu.Lock()
5659 st := cmd.status
5660 pk, _ := rd.Peek(1)
5661 cmd.mu.Unlock()
5662 if len(pk) != 0 && st == monitorStatusStart {
5663 cmd.mu.Lock()
5664 line, err := rd.ReadString()
5665 cmd.mu.Unlock()
5666 if err != nil {
5667 return err
5668 }
5669 cmd.ch <- line
5670 }
5671 if st == monitorStatusStop {
5672 cancel()
5673 break
5674 }
5675 }
5676 return nil
5677 }
5678
5679 func (cmd *MonitorCmd) Start() {
5680 cmd.mu.Lock()
5681 defer cmd.mu.Unlock()
5682 cmd.status = monitorStatusStart
5683 }
5684
5685 func (cmd *MonitorCmd) Stop() {
5686 cmd.mu.Lock()
5687 defer cmd.mu.Unlock()
5688 cmd.status = monitorStatusStop
5689 }
5690
5691 type VectorScoreSliceCmd struct {
5692 baseCmd
5693
5694 val []VectorScore
5695 }
5696
5697 var _ Cmder = (*VectorScoreSliceCmd)(nil)
5698
5699 func NewVectorInfoSliceCmd(ctx context.Context, args ...any) *VectorScoreSliceCmd {
5700 return &VectorScoreSliceCmd{
5701 baseCmd: baseCmd{
5702 ctx: ctx,
5703 args: args,
5704 },
5705 }
5706 }
5707
5708 func (cmd *VectorScoreSliceCmd) SetVal(val []VectorScore) {
5709 cmd.val = val
5710 }
5711
5712 func (cmd *VectorScoreSliceCmd) Val() []VectorScore {
5713 return cmd.val
5714 }
5715
5716 func (cmd *VectorScoreSliceCmd) Result() ([]VectorScore, error) {
5717 return cmd.val, cmd.err
5718 }
5719
5720 func (cmd *VectorScoreSliceCmd) String() string {
5721 return cmdString(cmd, cmd.val)
5722 }
5723
5724 func (cmd *VectorScoreSliceCmd) readReply(rd *proto.Reader) error {
5725 n, err := rd.ReadMapLen()
5726 if err != nil {
5727 return err
5728 }
5729
5730 cmd.val = make([]VectorScore, n)
5731 for i := 0; i < n; i++ {
5732 name, err := rd.ReadString()
5733 if err != nil {
5734 return err
5735 }
5736 cmd.val[i].Name = name
5737
5738 score, err := rd.ReadFloat()
5739 if err != nil {
5740 return err
5741 }
5742 cmd.val[i].Score = score
5743 }
5744 return nil
5745 }
5746
View as plain text