Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

5746 righe
117 KiB

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