You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3479 lines
67 KiB

  1. package redis
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "time"
  8. "github.com/go-redis/redis/v8/internal"
  9. "github.com/go-redis/redis/v8/internal/hscan"
  10. "github.com/go-redis/redis/v8/internal/proto"
  11. "github.com/go-redis/redis/v8/internal/util"
  12. )
  13. type Cmder interface {
  14. Name() string
  15. FullName() string
  16. Args() []interface{}
  17. String() string
  18. stringArg(int) string
  19. firstKeyPos() int8
  20. SetFirstKeyPos(int8)
  21. readTimeout() *time.Duration
  22. readReply(rd *proto.Reader) error
  23. SetErr(error)
  24. Err() error
  25. }
  26. func setCmdsErr(cmds []Cmder, e error) {
  27. for _, cmd := range cmds {
  28. if cmd.Err() == nil {
  29. cmd.SetErr(e)
  30. }
  31. }
  32. }
  33. func cmdsFirstErr(cmds []Cmder) error {
  34. for _, cmd := range cmds {
  35. if err := cmd.Err(); err != nil {
  36. return err
  37. }
  38. }
  39. return nil
  40. }
  41. func writeCmds(wr *proto.Writer, cmds []Cmder) error {
  42. for _, cmd := range cmds {
  43. if err := writeCmd(wr, cmd); err != nil {
  44. return err
  45. }
  46. }
  47. return nil
  48. }
  49. func writeCmd(wr *proto.Writer, cmd Cmder) error {
  50. return wr.WriteArgs(cmd.Args())
  51. }
  52. func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
  53. if pos := cmd.firstKeyPos(); pos != 0 {
  54. return int(pos)
  55. }
  56. switch cmd.Name() {
  57. case "eval", "evalsha":
  58. if cmd.stringArg(2) != "0" {
  59. return 3
  60. }
  61. return 0
  62. case "publish":
  63. return 1
  64. case "memory":
  65. // https://github.com/redis/redis/issues/7493
  66. if cmd.stringArg(1) == "usage" {
  67. return 2
  68. }
  69. }
  70. if info != nil {
  71. return int(info.FirstKeyPos)
  72. }
  73. return 0
  74. }
  75. func cmdString(cmd Cmder, val interface{}) string {
  76. b := make([]byte, 0, 64)
  77. for i, arg := range cmd.Args() {
  78. if i > 0 {
  79. b = append(b, ' ')
  80. }
  81. b = internal.AppendArg(b, arg)
  82. }
  83. if err := cmd.Err(); err != nil {
  84. b = append(b, ": "...)
  85. b = append(b, err.Error()...)
  86. } else if val != nil {
  87. b = append(b, ": "...)
  88. b = internal.AppendArg(b, val)
  89. }
  90. return internal.String(b)
  91. }
  92. //------------------------------------------------------------------------------
  93. type baseCmd struct {
  94. ctx context.Context
  95. args []interface{}
  96. err error
  97. keyPos int8
  98. _readTimeout *time.Duration
  99. }
  100. var _ Cmder = (*Cmd)(nil)
  101. func (cmd *baseCmd) Name() string {
  102. if len(cmd.args) == 0 {
  103. return ""
  104. }
  105. // Cmd name must be lower cased.
  106. return internal.ToLower(cmd.stringArg(0))
  107. }
  108. func (cmd *baseCmd) FullName() string {
  109. switch name := cmd.Name(); name {
  110. case "cluster", "command":
  111. if len(cmd.args) == 1 {
  112. return name
  113. }
  114. if s2, ok := cmd.args[1].(string); ok {
  115. return name + " " + s2
  116. }
  117. return name
  118. default:
  119. return name
  120. }
  121. }
  122. func (cmd *baseCmd) Args() []interface{} {
  123. return cmd.args
  124. }
  125. func (cmd *baseCmd) stringArg(pos int) string {
  126. if pos < 0 || pos >= len(cmd.args) {
  127. return ""
  128. }
  129. arg := cmd.args[pos]
  130. switch v := arg.(type) {
  131. case string:
  132. return v
  133. default:
  134. // TODO: consider using appendArg
  135. return fmt.Sprint(v)
  136. }
  137. }
  138. func (cmd *baseCmd) firstKeyPos() int8 {
  139. return cmd.keyPos
  140. }
  141. func (cmd *baseCmd) SetFirstKeyPos(keyPos int8) {
  142. cmd.keyPos = keyPos
  143. }
  144. func (cmd *baseCmd) SetErr(e error) {
  145. cmd.err = e
  146. }
  147. func (cmd *baseCmd) Err() error {
  148. return cmd.err
  149. }
  150. func (cmd *baseCmd) readTimeout() *time.Duration {
  151. return cmd._readTimeout
  152. }
  153. func (cmd *baseCmd) setReadTimeout(d time.Duration) {
  154. cmd._readTimeout = &d
  155. }
  156. //------------------------------------------------------------------------------
  157. type Cmd struct {
  158. baseCmd
  159. val interface{}
  160. }
  161. func NewCmd(ctx context.Context, args ...interface{}) *Cmd {
  162. return &Cmd{
  163. baseCmd: baseCmd{
  164. ctx: ctx,
  165. args: args,
  166. },
  167. }
  168. }
  169. func (cmd *Cmd) String() string {
  170. return cmdString(cmd, cmd.val)
  171. }
  172. func (cmd *Cmd) SetVal(val interface{}) {
  173. cmd.val = val
  174. }
  175. func (cmd *Cmd) Val() interface{} {
  176. return cmd.val
  177. }
  178. func (cmd *Cmd) Result() (interface{}, error) {
  179. return cmd.val, cmd.err
  180. }
  181. func (cmd *Cmd) Text() (string, error) {
  182. if cmd.err != nil {
  183. return "", cmd.err
  184. }
  185. return toString(cmd.val)
  186. }
  187. func toString(val interface{}) (string, error) {
  188. switch val := val.(type) {
  189. case string:
  190. return val, nil
  191. default:
  192. err := fmt.Errorf("redis: unexpected type=%T for String", val)
  193. return "", err
  194. }
  195. }
  196. func (cmd *Cmd) Int() (int, error) {
  197. if cmd.err != nil {
  198. return 0, cmd.err
  199. }
  200. switch val := cmd.val.(type) {
  201. case int64:
  202. return int(val), nil
  203. case string:
  204. return strconv.Atoi(val)
  205. default:
  206. err := fmt.Errorf("redis: unexpected type=%T for Int", val)
  207. return 0, err
  208. }
  209. }
  210. func (cmd *Cmd) Int64() (int64, error) {
  211. if cmd.err != nil {
  212. return 0, cmd.err
  213. }
  214. return toInt64(cmd.val)
  215. }
  216. func toInt64(val interface{}) (int64, error) {
  217. switch val := val.(type) {
  218. case int64:
  219. return val, nil
  220. case string:
  221. return strconv.ParseInt(val, 10, 64)
  222. default:
  223. err := fmt.Errorf("redis: unexpected type=%T for Int64", val)
  224. return 0, err
  225. }
  226. }
  227. func (cmd *Cmd) Uint64() (uint64, error) {
  228. if cmd.err != nil {
  229. return 0, cmd.err
  230. }
  231. return toUint64(cmd.val)
  232. }
  233. func toUint64(val interface{}) (uint64, error) {
  234. switch val := val.(type) {
  235. case int64:
  236. return uint64(val), nil
  237. case string:
  238. return strconv.ParseUint(val, 10, 64)
  239. default:
  240. err := fmt.Errorf("redis: unexpected type=%T for Uint64", val)
  241. return 0, err
  242. }
  243. }
  244. func (cmd *Cmd) Float32() (float32, error) {
  245. if cmd.err != nil {
  246. return 0, cmd.err
  247. }
  248. return toFloat32(cmd.val)
  249. }
  250. func toFloat32(val interface{}) (float32, error) {
  251. switch val := val.(type) {
  252. case int64:
  253. return float32(val), nil
  254. case string:
  255. f, err := strconv.ParseFloat(val, 32)
  256. if err != nil {
  257. return 0, err
  258. }
  259. return float32(f), nil
  260. default:
  261. err := fmt.Errorf("redis: unexpected type=%T for Float32", val)
  262. return 0, err
  263. }
  264. }
  265. func (cmd *Cmd) Float64() (float64, error) {
  266. if cmd.err != nil {
  267. return 0, cmd.err
  268. }
  269. return toFloat64(cmd.val)
  270. }
  271. func toFloat64(val interface{}) (float64, error) {
  272. switch val := val.(type) {
  273. case int64:
  274. return float64(val), nil
  275. case string:
  276. return strconv.ParseFloat(val, 64)
  277. default:
  278. err := fmt.Errorf("redis: unexpected type=%T for Float64", val)
  279. return 0, err
  280. }
  281. }
  282. func (cmd *Cmd) Bool() (bool, error) {
  283. if cmd.err != nil {
  284. return false, cmd.err
  285. }
  286. return toBool(cmd.val)
  287. }
  288. func toBool(val interface{}) (bool, error) {
  289. switch val := val.(type) {
  290. case int64:
  291. return val != 0, nil
  292. case string:
  293. return strconv.ParseBool(val)
  294. default:
  295. err := fmt.Errorf("redis: unexpected type=%T for Bool", val)
  296. return false, err
  297. }
  298. }
  299. func (cmd *Cmd) Slice() ([]interface{}, error) {
  300. if cmd.err != nil {
  301. return nil, cmd.err
  302. }
  303. switch val := cmd.val.(type) {
  304. case []interface{}:
  305. return val, nil
  306. default:
  307. return nil, fmt.Errorf("redis: unexpected type=%T for Slice", val)
  308. }
  309. }
  310. func (cmd *Cmd) StringSlice() ([]string, error) {
  311. slice, err := cmd.Slice()
  312. if err != nil {
  313. return nil, err
  314. }
  315. ss := make([]string, len(slice))
  316. for i, iface := range slice {
  317. val, err := toString(iface)
  318. if err != nil {
  319. return nil, err
  320. }
  321. ss[i] = val
  322. }
  323. return ss, nil
  324. }
  325. func (cmd *Cmd) Int64Slice() ([]int64, error) {
  326. slice, err := cmd.Slice()
  327. if err != nil {
  328. return nil, err
  329. }
  330. nums := make([]int64, len(slice))
  331. for i, iface := range slice {
  332. val, err := toInt64(iface)
  333. if err != nil {
  334. return nil, err
  335. }
  336. nums[i] = val
  337. }
  338. return nums, nil
  339. }
  340. func (cmd *Cmd) Uint64Slice() ([]uint64, error) {
  341. slice, err := cmd.Slice()
  342. if err != nil {
  343. return nil, err
  344. }
  345. nums := make([]uint64, len(slice))
  346. for i, iface := range slice {
  347. val, err := toUint64(iface)
  348. if err != nil {
  349. return nil, err
  350. }
  351. nums[i] = val
  352. }
  353. return nums, nil
  354. }
  355. func (cmd *Cmd) Float32Slice() ([]float32, error) {
  356. slice, err := cmd.Slice()
  357. if err != nil {
  358. return nil, err
  359. }
  360. floats := make([]float32, len(slice))
  361. for i, iface := range slice {
  362. val, err := toFloat32(iface)
  363. if err != nil {
  364. return nil, err
  365. }
  366. floats[i] = val
  367. }
  368. return floats, nil
  369. }
  370. func (cmd *Cmd) Float64Slice() ([]float64, error) {
  371. slice, err := cmd.Slice()
  372. if err != nil {
  373. return nil, err
  374. }
  375. floats := make([]float64, len(slice))
  376. for i, iface := range slice {
  377. val, err := toFloat64(iface)
  378. if err != nil {
  379. return nil, err
  380. }
  381. floats[i] = val
  382. }
  383. return floats, nil
  384. }
  385. func (cmd *Cmd) BoolSlice() ([]bool, error) {
  386. slice, err := cmd.Slice()
  387. if err != nil {
  388. return nil, err
  389. }
  390. bools := make([]bool, len(slice))
  391. for i, iface := range slice {
  392. val, err := toBool(iface)
  393. if err != nil {
  394. return nil, err
  395. }
  396. bools[i] = val
  397. }
  398. return bools, nil
  399. }
  400. func (cmd *Cmd) readReply(rd *proto.Reader) (err error) {
  401. cmd.val, err = rd.ReadReply(sliceParser)
  402. return err
  403. }
  404. // sliceParser implements proto.MultiBulkParse.
  405. func sliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  406. vals := make([]interface{}, n)
  407. for i := 0; i < len(vals); i++ {
  408. v, err := rd.ReadReply(sliceParser)
  409. if err != nil {
  410. if err == Nil {
  411. vals[i] = nil
  412. continue
  413. }
  414. if err, ok := err.(proto.RedisError); ok {
  415. vals[i] = err
  416. continue
  417. }
  418. return nil, err
  419. }
  420. vals[i] = v
  421. }
  422. return vals, nil
  423. }
  424. //------------------------------------------------------------------------------
  425. type SliceCmd struct {
  426. baseCmd
  427. val []interface{}
  428. }
  429. var _ Cmder = (*SliceCmd)(nil)
  430. func NewSliceCmd(ctx context.Context, args ...interface{}) *SliceCmd {
  431. return &SliceCmd{
  432. baseCmd: baseCmd{
  433. ctx: ctx,
  434. args: args,
  435. },
  436. }
  437. }
  438. func (cmd *SliceCmd) SetVal(val []interface{}) {
  439. cmd.val = val
  440. }
  441. func (cmd *SliceCmd) Val() []interface{} {
  442. return cmd.val
  443. }
  444. func (cmd *SliceCmd) Result() ([]interface{}, error) {
  445. return cmd.val, cmd.err
  446. }
  447. func (cmd *SliceCmd) String() string {
  448. return cmdString(cmd, cmd.val)
  449. }
  450. // Scan scans the results from the map into a destination struct. The map keys
  451. // are matched in the Redis struct fields by the `redis:"field"` tag.
  452. func (cmd *SliceCmd) Scan(dst interface{}) error {
  453. if cmd.err != nil {
  454. return cmd.err
  455. }
  456. // Pass the list of keys and values.
  457. // Skip the first two args for: HMGET key
  458. var args []interface{}
  459. if cmd.args[0] == "hmget" {
  460. args = cmd.args[2:]
  461. } else {
  462. // Otherwise, it's: MGET field field ...
  463. args = cmd.args[1:]
  464. }
  465. return hscan.Scan(dst, args, cmd.val)
  466. }
  467. func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
  468. v, err := rd.ReadArrayReply(sliceParser)
  469. if err != nil {
  470. return err
  471. }
  472. cmd.val = v.([]interface{})
  473. return nil
  474. }
  475. //------------------------------------------------------------------------------
  476. type StatusCmd struct {
  477. baseCmd
  478. val string
  479. }
  480. var _ Cmder = (*StatusCmd)(nil)
  481. func NewStatusCmd(ctx context.Context, args ...interface{}) *StatusCmd {
  482. return &StatusCmd{
  483. baseCmd: baseCmd{
  484. ctx: ctx,
  485. args: args,
  486. },
  487. }
  488. }
  489. func (cmd *StatusCmd) SetVal(val string) {
  490. cmd.val = val
  491. }
  492. func (cmd *StatusCmd) Val() string {
  493. return cmd.val
  494. }
  495. func (cmd *StatusCmd) Result() (string, error) {
  496. return cmd.val, cmd.err
  497. }
  498. func (cmd *StatusCmd) String() string {
  499. return cmdString(cmd, cmd.val)
  500. }
  501. func (cmd *StatusCmd) readReply(rd *proto.Reader) (err error) {
  502. cmd.val, err = rd.ReadString()
  503. return err
  504. }
  505. //------------------------------------------------------------------------------
  506. type IntCmd struct {
  507. baseCmd
  508. val int64
  509. }
  510. var _ Cmder = (*IntCmd)(nil)
  511. func NewIntCmd(ctx context.Context, args ...interface{}) *IntCmd {
  512. return &IntCmd{
  513. baseCmd: baseCmd{
  514. ctx: ctx,
  515. args: args,
  516. },
  517. }
  518. }
  519. func (cmd *IntCmd) SetVal(val int64) {
  520. cmd.val = val
  521. }
  522. func (cmd *IntCmd) Val() int64 {
  523. return cmd.val
  524. }
  525. func (cmd *IntCmd) Result() (int64, error) {
  526. return cmd.val, cmd.err
  527. }
  528. func (cmd *IntCmd) Uint64() (uint64, error) {
  529. return uint64(cmd.val), cmd.err
  530. }
  531. func (cmd *IntCmd) String() string {
  532. return cmdString(cmd, cmd.val)
  533. }
  534. func (cmd *IntCmd) readReply(rd *proto.Reader) (err error) {
  535. cmd.val, err = rd.ReadIntReply()
  536. return err
  537. }
  538. //------------------------------------------------------------------------------
  539. type IntSliceCmd struct {
  540. baseCmd
  541. val []int64
  542. }
  543. var _ Cmder = (*IntSliceCmd)(nil)
  544. func NewIntSliceCmd(ctx context.Context, args ...interface{}) *IntSliceCmd {
  545. return &IntSliceCmd{
  546. baseCmd: baseCmd{
  547. ctx: ctx,
  548. args: args,
  549. },
  550. }
  551. }
  552. func (cmd *IntSliceCmd) SetVal(val []int64) {
  553. cmd.val = val
  554. }
  555. func (cmd *IntSliceCmd) Val() []int64 {
  556. return cmd.val
  557. }
  558. func (cmd *IntSliceCmd) Result() ([]int64, error) {
  559. return cmd.val, cmd.err
  560. }
  561. func (cmd *IntSliceCmd) String() string {
  562. return cmdString(cmd, cmd.val)
  563. }
  564. func (cmd *IntSliceCmd) readReply(rd *proto.Reader) error {
  565. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  566. cmd.val = make([]int64, n)
  567. for i := 0; i < len(cmd.val); i++ {
  568. num, err := rd.ReadIntReply()
  569. if err != nil {
  570. return nil, err
  571. }
  572. cmd.val[i] = num
  573. }
  574. return nil, nil
  575. })
  576. return err
  577. }
  578. //------------------------------------------------------------------------------
  579. type DurationCmd struct {
  580. baseCmd
  581. val time.Duration
  582. precision time.Duration
  583. }
  584. var _ Cmder = (*DurationCmd)(nil)
  585. func NewDurationCmd(ctx context.Context, precision time.Duration, args ...interface{}) *DurationCmd {
  586. return &DurationCmd{
  587. baseCmd: baseCmd{
  588. ctx: ctx,
  589. args: args,
  590. },
  591. precision: precision,
  592. }
  593. }
  594. func (cmd *DurationCmd) SetVal(val time.Duration) {
  595. cmd.val = val
  596. }
  597. func (cmd *DurationCmd) Val() time.Duration {
  598. return cmd.val
  599. }
  600. func (cmd *DurationCmd) Result() (time.Duration, error) {
  601. return cmd.val, cmd.err
  602. }
  603. func (cmd *DurationCmd) String() string {
  604. return cmdString(cmd, cmd.val)
  605. }
  606. func (cmd *DurationCmd) readReply(rd *proto.Reader) error {
  607. n, err := rd.ReadIntReply()
  608. if err != nil {
  609. return err
  610. }
  611. switch n {
  612. // -2 if the key does not exist
  613. // -1 if the key exists but has no associated expire
  614. case -2, -1:
  615. cmd.val = time.Duration(n)
  616. default:
  617. cmd.val = time.Duration(n) * cmd.precision
  618. }
  619. return nil
  620. }
  621. //------------------------------------------------------------------------------
  622. type TimeCmd struct {
  623. baseCmd
  624. val time.Time
  625. }
  626. var _ Cmder = (*TimeCmd)(nil)
  627. func NewTimeCmd(ctx context.Context, args ...interface{}) *TimeCmd {
  628. return &TimeCmd{
  629. baseCmd: baseCmd{
  630. ctx: ctx,
  631. args: args,
  632. },
  633. }
  634. }
  635. func (cmd *TimeCmd) SetVal(val time.Time) {
  636. cmd.val = val
  637. }
  638. func (cmd *TimeCmd) Val() time.Time {
  639. return cmd.val
  640. }
  641. func (cmd *TimeCmd) Result() (time.Time, error) {
  642. return cmd.val, cmd.err
  643. }
  644. func (cmd *TimeCmd) String() string {
  645. return cmdString(cmd, cmd.val)
  646. }
  647. func (cmd *TimeCmd) readReply(rd *proto.Reader) error {
  648. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  649. if n != 2 {
  650. return nil, fmt.Errorf("got %d elements, expected 2", n)
  651. }
  652. sec, err := rd.ReadInt()
  653. if err != nil {
  654. return nil, err
  655. }
  656. microsec, err := rd.ReadInt()
  657. if err != nil {
  658. return nil, err
  659. }
  660. cmd.val = time.Unix(sec, microsec*1000)
  661. return nil, nil
  662. })
  663. return err
  664. }
  665. //------------------------------------------------------------------------------
  666. type BoolCmd struct {
  667. baseCmd
  668. val bool
  669. }
  670. var _ Cmder = (*BoolCmd)(nil)
  671. func NewBoolCmd(ctx context.Context, args ...interface{}) *BoolCmd {
  672. return &BoolCmd{
  673. baseCmd: baseCmd{
  674. ctx: ctx,
  675. args: args,
  676. },
  677. }
  678. }
  679. func (cmd *BoolCmd) SetVal(val bool) {
  680. cmd.val = val
  681. }
  682. func (cmd *BoolCmd) Val() bool {
  683. return cmd.val
  684. }
  685. func (cmd *BoolCmd) Result() (bool, error) {
  686. return cmd.val, cmd.err
  687. }
  688. func (cmd *BoolCmd) String() string {
  689. return cmdString(cmd, cmd.val)
  690. }
  691. func (cmd *BoolCmd) readReply(rd *proto.Reader) error {
  692. v, err := rd.ReadReply(nil)
  693. // `SET key value NX` returns nil when key already exists. But
  694. // `SETNX key value` returns bool (0/1). So convert nil to bool.
  695. if err == Nil {
  696. cmd.val = false
  697. return nil
  698. }
  699. if err != nil {
  700. return err
  701. }
  702. switch v := v.(type) {
  703. case int64:
  704. cmd.val = v == 1
  705. return nil
  706. case string:
  707. cmd.val = v == "OK"
  708. return nil
  709. default:
  710. return fmt.Errorf("got %T, wanted int64 or string", v)
  711. }
  712. }
  713. //------------------------------------------------------------------------------
  714. type StringCmd struct {
  715. baseCmd
  716. val string
  717. }
  718. var _ Cmder = (*StringCmd)(nil)
  719. func NewStringCmd(ctx context.Context, args ...interface{}) *StringCmd {
  720. return &StringCmd{
  721. baseCmd: baseCmd{
  722. ctx: ctx,
  723. args: args,
  724. },
  725. }
  726. }
  727. func (cmd *StringCmd) SetVal(val string) {
  728. cmd.val = val
  729. }
  730. func (cmd *StringCmd) Val() string {
  731. return cmd.val
  732. }
  733. func (cmd *StringCmd) Result() (string, error) {
  734. return cmd.Val(), cmd.err
  735. }
  736. func (cmd *StringCmd) Bytes() ([]byte, error) {
  737. return util.StringToBytes(cmd.val), cmd.err
  738. }
  739. func (cmd *StringCmd) Bool() (bool, error) {
  740. if cmd.err != nil {
  741. return false, cmd.err
  742. }
  743. return strconv.ParseBool(cmd.val)
  744. }
  745. func (cmd *StringCmd) Int() (int, error) {
  746. if cmd.err != nil {
  747. return 0, cmd.err
  748. }
  749. return strconv.Atoi(cmd.Val())
  750. }
  751. func (cmd *StringCmd) Int64() (int64, error) {
  752. if cmd.err != nil {
  753. return 0, cmd.err
  754. }
  755. return strconv.ParseInt(cmd.Val(), 10, 64)
  756. }
  757. func (cmd *StringCmd) Uint64() (uint64, error) {
  758. if cmd.err != nil {
  759. return 0, cmd.err
  760. }
  761. return strconv.ParseUint(cmd.Val(), 10, 64)
  762. }
  763. func (cmd *StringCmd) Float32() (float32, error) {
  764. if cmd.err != nil {
  765. return 0, cmd.err
  766. }
  767. f, err := strconv.ParseFloat(cmd.Val(), 32)
  768. if err != nil {
  769. return 0, err
  770. }
  771. return float32(f), nil
  772. }
  773. func (cmd *StringCmd) Float64() (float64, error) {
  774. if cmd.err != nil {
  775. return 0, cmd.err
  776. }
  777. return strconv.ParseFloat(cmd.Val(), 64)
  778. }
  779. func (cmd *StringCmd) Time() (time.Time, error) {
  780. if cmd.err != nil {
  781. return time.Time{}, cmd.err
  782. }
  783. return time.Parse(time.RFC3339Nano, cmd.Val())
  784. }
  785. func (cmd *StringCmd) Scan(val interface{}) error {
  786. if cmd.err != nil {
  787. return cmd.err
  788. }
  789. return proto.Scan([]byte(cmd.val), val)
  790. }
  791. func (cmd *StringCmd) String() string {
  792. return cmdString(cmd, cmd.val)
  793. }
  794. func (cmd *StringCmd) readReply(rd *proto.Reader) (err error) {
  795. cmd.val, err = rd.ReadString()
  796. return err
  797. }
  798. //------------------------------------------------------------------------------
  799. type FloatCmd struct {
  800. baseCmd
  801. val float64
  802. }
  803. var _ Cmder = (*FloatCmd)(nil)
  804. func NewFloatCmd(ctx context.Context, args ...interface{}) *FloatCmd {
  805. return &FloatCmd{
  806. baseCmd: baseCmd{
  807. ctx: ctx,
  808. args: args,
  809. },
  810. }
  811. }
  812. func (cmd *FloatCmd) SetVal(val float64) {
  813. cmd.val = val
  814. }
  815. func (cmd *FloatCmd) Val() float64 {
  816. return cmd.val
  817. }
  818. func (cmd *FloatCmd) Result() (float64, error) {
  819. return cmd.Val(), cmd.Err()
  820. }
  821. func (cmd *FloatCmd) String() string {
  822. return cmdString(cmd, cmd.val)
  823. }
  824. func (cmd *FloatCmd) readReply(rd *proto.Reader) (err error) {
  825. cmd.val, err = rd.ReadFloatReply()
  826. return err
  827. }
  828. //------------------------------------------------------------------------------
  829. type FloatSliceCmd struct {
  830. baseCmd
  831. val []float64
  832. }
  833. var _ Cmder = (*FloatSliceCmd)(nil)
  834. func NewFloatSliceCmd(ctx context.Context, args ...interface{}) *FloatSliceCmd {
  835. return &FloatSliceCmd{
  836. baseCmd: baseCmd{
  837. ctx: ctx,
  838. args: args,
  839. },
  840. }
  841. }
  842. func (cmd *FloatSliceCmd) SetVal(val []float64) {
  843. cmd.val = val
  844. }
  845. func (cmd *FloatSliceCmd) Val() []float64 {
  846. return cmd.val
  847. }
  848. func (cmd *FloatSliceCmd) Result() ([]float64, error) {
  849. return cmd.val, cmd.err
  850. }
  851. func (cmd *FloatSliceCmd) String() string {
  852. return cmdString(cmd, cmd.val)
  853. }
  854. func (cmd *FloatSliceCmd) readReply(rd *proto.Reader) error {
  855. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  856. cmd.val = make([]float64, n)
  857. for i := 0; i < len(cmd.val); i++ {
  858. switch num, err := rd.ReadFloatReply(); {
  859. case err == Nil:
  860. cmd.val[i] = 0
  861. case err != nil:
  862. return nil, err
  863. default:
  864. cmd.val[i] = num
  865. }
  866. }
  867. return nil, nil
  868. })
  869. return err
  870. }
  871. //------------------------------------------------------------------------------
  872. type StringSliceCmd struct {
  873. baseCmd
  874. val []string
  875. }
  876. var _ Cmder = (*StringSliceCmd)(nil)
  877. func NewStringSliceCmd(ctx context.Context, args ...interface{}) *StringSliceCmd {
  878. return &StringSliceCmd{
  879. baseCmd: baseCmd{
  880. ctx: ctx,
  881. args: args,
  882. },
  883. }
  884. }
  885. func (cmd *StringSliceCmd) SetVal(val []string) {
  886. cmd.val = val
  887. }
  888. func (cmd *StringSliceCmd) Val() []string {
  889. return cmd.val
  890. }
  891. func (cmd *StringSliceCmd) Result() ([]string, error) {
  892. return cmd.Val(), cmd.Err()
  893. }
  894. func (cmd *StringSliceCmd) String() string {
  895. return cmdString(cmd, cmd.val)
  896. }
  897. func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
  898. return proto.ScanSlice(cmd.Val(), container)
  899. }
  900. func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error {
  901. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  902. cmd.val = make([]string, n)
  903. for i := 0; i < len(cmd.val); i++ {
  904. switch s, err := rd.ReadString(); {
  905. case err == Nil:
  906. cmd.val[i] = ""
  907. case err != nil:
  908. return nil, err
  909. default:
  910. cmd.val[i] = s
  911. }
  912. }
  913. return nil, nil
  914. })
  915. return err
  916. }
  917. //------------------------------------------------------------------------------
  918. type BoolSliceCmd struct {
  919. baseCmd
  920. val []bool
  921. }
  922. var _ Cmder = (*BoolSliceCmd)(nil)
  923. func NewBoolSliceCmd(ctx context.Context, args ...interface{}) *BoolSliceCmd {
  924. return &BoolSliceCmd{
  925. baseCmd: baseCmd{
  926. ctx: ctx,
  927. args: args,
  928. },
  929. }
  930. }
  931. func (cmd *BoolSliceCmd) SetVal(val []bool) {
  932. cmd.val = val
  933. }
  934. func (cmd *BoolSliceCmd) Val() []bool {
  935. return cmd.val
  936. }
  937. func (cmd *BoolSliceCmd) Result() ([]bool, error) {
  938. return cmd.val, cmd.err
  939. }
  940. func (cmd *BoolSliceCmd) String() string {
  941. return cmdString(cmd, cmd.val)
  942. }
  943. func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error {
  944. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  945. cmd.val = make([]bool, n)
  946. for i := 0; i < len(cmd.val); i++ {
  947. n, err := rd.ReadIntReply()
  948. if err != nil {
  949. return nil, err
  950. }
  951. cmd.val[i] = n == 1
  952. }
  953. return nil, nil
  954. })
  955. return err
  956. }
  957. //------------------------------------------------------------------------------
  958. type StringStringMapCmd struct {
  959. baseCmd
  960. val map[string]string
  961. }
  962. var _ Cmder = (*StringStringMapCmd)(nil)
  963. func NewStringStringMapCmd(ctx context.Context, args ...interface{}) *StringStringMapCmd {
  964. return &StringStringMapCmd{
  965. baseCmd: baseCmd{
  966. ctx: ctx,
  967. args: args,
  968. },
  969. }
  970. }
  971. func (cmd *StringStringMapCmd) SetVal(val map[string]string) {
  972. cmd.val = val
  973. }
  974. func (cmd *StringStringMapCmd) Val() map[string]string {
  975. return cmd.val
  976. }
  977. func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
  978. return cmd.val, cmd.err
  979. }
  980. func (cmd *StringStringMapCmd) String() string {
  981. return cmdString(cmd, cmd.val)
  982. }
  983. // Scan scans the results from the map into a destination struct. The map keys
  984. // are matched in the Redis struct fields by the `redis:"field"` tag.
  985. func (cmd *StringStringMapCmd) Scan(dest interface{}) error {
  986. if cmd.err != nil {
  987. return cmd.err
  988. }
  989. strct, err := hscan.Struct(dest)
  990. if err != nil {
  991. return err
  992. }
  993. for k, v := range cmd.val {
  994. if err := strct.Scan(k, v); err != nil {
  995. return err
  996. }
  997. }
  998. return nil
  999. }
  1000. func (cmd *StringStringMapCmd) readReply(rd *proto.Reader) error {
  1001. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1002. cmd.val = make(map[string]string, n/2)
  1003. for i := int64(0); i < n; i += 2 {
  1004. key, err := rd.ReadString()
  1005. if err != nil {
  1006. return nil, err
  1007. }
  1008. value, err := rd.ReadString()
  1009. if err != nil {
  1010. return nil, err
  1011. }
  1012. cmd.val[key] = value
  1013. }
  1014. return nil, nil
  1015. })
  1016. return err
  1017. }
  1018. //------------------------------------------------------------------------------
  1019. type StringIntMapCmd struct {
  1020. baseCmd
  1021. val map[string]int64
  1022. }
  1023. var _ Cmder = (*StringIntMapCmd)(nil)
  1024. func NewStringIntMapCmd(ctx context.Context, args ...interface{}) *StringIntMapCmd {
  1025. return &StringIntMapCmd{
  1026. baseCmd: baseCmd{
  1027. ctx: ctx,
  1028. args: args,
  1029. },
  1030. }
  1031. }
  1032. func (cmd *StringIntMapCmd) SetVal(val map[string]int64) {
  1033. cmd.val = val
  1034. }
  1035. func (cmd *StringIntMapCmd) Val() map[string]int64 {
  1036. return cmd.val
  1037. }
  1038. func (cmd *StringIntMapCmd) Result() (map[string]int64, error) {
  1039. return cmd.val, cmd.err
  1040. }
  1041. func (cmd *StringIntMapCmd) String() string {
  1042. return cmdString(cmd, cmd.val)
  1043. }
  1044. func (cmd *StringIntMapCmd) readReply(rd *proto.Reader) error {
  1045. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1046. cmd.val = make(map[string]int64, n/2)
  1047. for i := int64(0); i < n; i += 2 {
  1048. key, err := rd.ReadString()
  1049. if err != nil {
  1050. return nil, err
  1051. }
  1052. n, err := rd.ReadIntReply()
  1053. if err != nil {
  1054. return nil, err
  1055. }
  1056. cmd.val[key] = n
  1057. }
  1058. return nil, nil
  1059. })
  1060. return err
  1061. }
  1062. //------------------------------------------------------------------------------
  1063. type StringStructMapCmd struct {
  1064. baseCmd
  1065. val map[string]struct{}
  1066. }
  1067. var _ Cmder = (*StringStructMapCmd)(nil)
  1068. func NewStringStructMapCmd(ctx context.Context, args ...interface{}) *StringStructMapCmd {
  1069. return &StringStructMapCmd{
  1070. baseCmd: baseCmd{
  1071. ctx: ctx,
  1072. args: args,
  1073. },
  1074. }
  1075. }
  1076. func (cmd *StringStructMapCmd) SetVal(val map[string]struct{}) {
  1077. cmd.val = val
  1078. }
  1079. func (cmd *StringStructMapCmd) Val() map[string]struct{} {
  1080. return cmd.val
  1081. }
  1082. func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
  1083. return cmd.val, cmd.err
  1084. }
  1085. func (cmd *StringStructMapCmd) String() string {
  1086. return cmdString(cmd, cmd.val)
  1087. }
  1088. func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error {
  1089. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1090. cmd.val = make(map[string]struct{}, n)
  1091. for i := int64(0); i < n; i++ {
  1092. key, err := rd.ReadString()
  1093. if err != nil {
  1094. return nil, err
  1095. }
  1096. cmd.val[key] = struct{}{}
  1097. }
  1098. return nil, nil
  1099. })
  1100. return err
  1101. }
  1102. //------------------------------------------------------------------------------
  1103. type XMessage struct {
  1104. ID string
  1105. Values map[string]interface{}
  1106. }
  1107. type XMessageSliceCmd struct {
  1108. baseCmd
  1109. val []XMessage
  1110. }
  1111. var _ Cmder = (*XMessageSliceCmd)(nil)
  1112. func NewXMessageSliceCmd(ctx context.Context, args ...interface{}) *XMessageSliceCmd {
  1113. return &XMessageSliceCmd{
  1114. baseCmd: baseCmd{
  1115. ctx: ctx,
  1116. args: args,
  1117. },
  1118. }
  1119. }
  1120. func (cmd *XMessageSliceCmd) SetVal(val []XMessage) {
  1121. cmd.val = val
  1122. }
  1123. func (cmd *XMessageSliceCmd) Val() []XMessage {
  1124. return cmd.val
  1125. }
  1126. func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) {
  1127. return cmd.val, cmd.err
  1128. }
  1129. func (cmd *XMessageSliceCmd) String() string {
  1130. return cmdString(cmd, cmd.val)
  1131. }
  1132. func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error {
  1133. var err error
  1134. cmd.val, err = readXMessageSlice(rd)
  1135. return err
  1136. }
  1137. func readXMessageSlice(rd *proto.Reader) ([]XMessage, error) {
  1138. n, err := rd.ReadArrayLen()
  1139. if err != nil {
  1140. return nil, err
  1141. }
  1142. msgs := make([]XMessage, n)
  1143. for i := 0; i < n; i++ {
  1144. var err error
  1145. msgs[i], err = readXMessage(rd)
  1146. if err != nil {
  1147. return nil, err
  1148. }
  1149. }
  1150. return msgs, nil
  1151. }
  1152. func readXMessage(rd *proto.Reader) (XMessage, error) {
  1153. n, err := rd.ReadArrayLen()
  1154. if err != nil {
  1155. return XMessage{}, err
  1156. }
  1157. if n != 2 {
  1158. return XMessage{}, fmt.Errorf("got %d, wanted 2", n)
  1159. }
  1160. id, err := rd.ReadString()
  1161. if err != nil {
  1162. return XMessage{}, err
  1163. }
  1164. var values map[string]interface{}
  1165. v, err := rd.ReadArrayReply(stringInterfaceMapParser)
  1166. if err != nil {
  1167. if err != proto.Nil {
  1168. return XMessage{}, err
  1169. }
  1170. } else {
  1171. values = v.(map[string]interface{})
  1172. }
  1173. return XMessage{
  1174. ID: id,
  1175. Values: values,
  1176. }, nil
  1177. }
  1178. // stringInterfaceMapParser implements proto.MultiBulkParse.
  1179. func stringInterfaceMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  1180. m := make(map[string]interface{}, n/2)
  1181. for i := int64(0); i < n; i += 2 {
  1182. key, err := rd.ReadString()
  1183. if err != nil {
  1184. return nil, err
  1185. }
  1186. value, err := rd.ReadString()
  1187. if err != nil {
  1188. return nil, err
  1189. }
  1190. m[key] = value
  1191. }
  1192. return m, nil
  1193. }
  1194. //------------------------------------------------------------------------------
  1195. type XStream struct {
  1196. Stream string
  1197. Messages []XMessage
  1198. }
  1199. type XStreamSliceCmd struct {
  1200. baseCmd
  1201. val []XStream
  1202. }
  1203. var _ Cmder = (*XStreamSliceCmd)(nil)
  1204. func NewXStreamSliceCmd(ctx context.Context, args ...interface{}) *XStreamSliceCmd {
  1205. return &XStreamSliceCmd{
  1206. baseCmd: baseCmd{
  1207. ctx: ctx,
  1208. args: args,
  1209. },
  1210. }
  1211. }
  1212. func (cmd *XStreamSliceCmd) SetVal(val []XStream) {
  1213. cmd.val = val
  1214. }
  1215. func (cmd *XStreamSliceCmd) Val() []XStream {
  1216. return cmd.val
  1217. }
  1218. func (cmd *XStreamSliceCmd) Result() ([]XStream, error) {
  1219. return cmd.val, cmd.err
  1220. }
  1221. func (cmd *XStreamSliceCmd) String() string {
  1222. return cmdString(cmd, cmd.val)
  1223. }
  1224. func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error {
  1225. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1226. cmd.val = make([]XStream, n)
  1227. for i := 0; i < len(cmd.val); i++ {
  1228. i := i
  1229. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1230. if n != 2 {
  1231. return nil, fmt.Errorf("got %d, wanted 2", n)
  1232. }
  1233. stream, err := rd.ReadString()
  1234. if err != nil {
  1235. return nil, err
  1236. }
  1237. msgs, err := readXMessageSlice(rd)
  1238. if err != nil {
  1239. return nil, err
  1240. }
  1241. cmd.val[i] = XStream{
  1242. Stream: stream,
  1243. Messages: msgs,
  1244. }
  1245. return nil, nil
  1246. })
  1247. if err != nil {
  1248. return nil, err
  1249. }
  1250. }
  1251. return nil, nil
  1252. })
  1253. return err
  1254. }
  1255. //------------------------------------------------------------------------------
  1256. type XPending struct {
  1257. Count int64
  1258. Lower string
  1259. Higher string
  1260. Consumers map[string]int64
  1261. }
  1262. type XPendingCmd struct {
  1263. baseCmd
  1264. val *XPending
  1265. }
  1266. var _ Cmder = (*XPendingCmd)(nil)
  1267. func NewXPendingCmd(ctx context.Context, args ...interface{}) *XPendingCmd {
  1268. return &XPendingCmd{
  1269. baseCmd: baseCmd{
  1270. ctx: ctx,
  1271. args: args,
  1272. },
  1273. }
  1274. }
  1275. func (cmd *XPendingCmd) SetVal(val *XPending) {
  1276. cmd.val = val
  1277. }
  1278. func (cmd *XPendingCmd) Val() *XPending {
  1279. return cmd.val
  1280. }
  1281. func (cmd *XPendingCmd) Result() (*XPending, error) {
  1282. return cmd.val, cmd.err
  1283. }
  1284. func (cmd *XPendingCmd) String() string {
  1285. return cmdString(cmd, cmd.val)
  1286. }
  1287. func (cmd *XPendingCmd) readReply(rd *proto.Reader) error {
  1288. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1289. if n != 4 {
  1290. return nil, fmt.Errorf("got %d, wanted 4", n)
  1291. }
  1292. count, err := rd.ReadIntReply()
  1293. if err != nil {
  1294. return nil, err
  1295. }
  1296. lower, err := rd.ReadString()
  1297. if err != nil && err != Nil {
  1298. return nil, err
  1299. }
  1300. higher, err := rd.ReadString()
  1301. if err != nil && err != Nil {
  1302. return nil, err
  1303. }
  1304. cmd.val = &XPending{
  1305. Count: count,
  1306. Lower: lower,
  1307. Higher: higher,
  1308. }
  1309. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1310. for i := int64(0); i < n; i++ {
  1311. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1312. if n != 2 {
  1313. return nil, fmt.Errorf("got %d, wanted 2", n)
  1314. }
  1315. consumerName, err := rd.ReadString()
  1316. if err != nil {
  1317. return nil, err
  1318. }
  1319. consumerPending, err := rd.ReadInt()
  1320. if err != nil {
  1321. return nil, err
  1322. }
  1323. if cmd.val.Consumers == nil {
  1324. cmd.val.Consumers = make(map[string]int64)
  1325. }
  1326. cmd.val.Consumers[consumerName] = consumerPending
  1327. return nil, nil
  1328. })
  1329. if err != nil {
  1330. return nil, err
  1331. }
  1332. }
  1333. return nil, nil
  1334. })
  1335. if err != nil && err != Nil {
  1336. return nil, err
  1337. }
  1338. return nil, nil
  1339. })
  1340. return err
  1341. }
  1342. //------------------------------------------------------------------------------
  1343. type XPendingExt struct {
  1344. ID string
  1345. Consumer string
  1346. Idle time.Duration
  1347. RetryCount int64
  1348. }
  1349. type XPendingExtCmd struct {
  1350. baseCmd
  1351. val []XPendingExt
  1352. }
  1353. var _ Cmder = (*XPendingExtCmd)(nil)
  1354. func NewXPendingExtCmd(ctx context.Context, args ...interface{}) *XPendingExtCmd {
  1355. return &XPendingExtCmd{
  1356. baseCmd: baseCmd{
  1357. ctx: ctx,
  1358. args: args,
  1359. },
  1360. }
  1361. }
  1362. func (cmd *XPendingExtCmd) SetVal(val []XPendingExt) {
  1363. cmd.val = val
  1364. }
  1365. func (cmd *XPendingExtCmd) Val() []XPendingExt {
  1366. return cmd.val
  1367. }
  1368. func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) {
  1369. return cmd.val, cmd.err
  1370. }
  1371. func (cmd *XPendingExtCmd) String() string {
  1372. return cmdString(cmd, cmd.val)
  1373. }
  1374. func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error {
  1375. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1376. cmd.val = make([]XPendingExt, 0, n)
  1377. for i := int64(0); i < n; i++ {
  1378. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1379. if n != 4 {
  1380. return nil, fmt.Errorf("got %d, wanted 4", n)
  1381. }
  1382. id, err := rd.ReadString()
  1383. if err != nil {
  1384. return nil, err
  1385. }
  1386. consumer, err := rd.ReadString()
  1387. if err != nil && err != Nil {
  1388. return nil, err
  1389. }
  1390. idle, err := rd.ReadIntReply()
  1391. if err != nil && err != Nil {
  1392. return nil, err
  1393. }
  1394. retryCount, err := rd.ReadIntReply()
  1395. if err != nil && err != Nil {
  1396. return nil, err
  1397. }
  1398. cmd.val = append(cmd.val, XPendingExt{
  1399. ID: id,
  1400. Consumer: consumer,
  1401. Idle: time.Duration(idle) * time.Millisecond,
  1402. RetryCount: retryCount,
  1403. })
  1404. return nil, nil
  1405. })
  1406. if err != nil {
  1407. return nil, err
  1408. }
  1409. }
  1410. return nil, nil
  1411. })
  1412. return err
  1413. }
  1414. //------------------------------------------------------------------------------
  1415. type XAutoClaimCmd struct {
  1416. baseCmd
  1417. start string
  1418. val []XMessage
  1419. }
  1420. var _ Cmder = (*XAutoClaimCmd)(nil)
  1421. func NewXAutoClaimCmd(ctx context.Context, args ...interface{}) *XAutoClaimCmd {
  1422. return &XAutoClaimCmd{
  1423. baseCmd: baseCmd{
  1424. ctx: ctx,
  1425. args: args,
  1426. },
  1427. }
  1428. }
  1429. func (cmd *XAutoClaimCmd) SetVal(val []XMessage, start string) {
  1430. cmd.val = val
  1431. cmd.start = start
  1432. }
  1433. func (cmd *XAutoClaimCmd) Val() (messages []XMessage, start string) {
  1434. return cmd.val, cmd.start
  1435. }
  1436. func (cmd *XAutoClaimCmd) Result() (messages []XMessage, start string, err error) {
  1437. return cmd.val, cmd.start, cmd.err
  1438. }
  1439. func (cmd *XAutoClaimCmd) String() string {
  1440. return cmdString(cmd, cmd.val)
  1441. }
  1442. func (cmd *XAutoClaimCmd) readReply(rd *proto.Reader) error {
  1443. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1444. if n != 2 {
  1445. return nil, fmt.Errorf("got %d, wanted 2", n)
  1446. }
  1447. var err error
  1448. cmd.start, err = rd.ReadString()
  1449. if err != nil {
  1450. return nil, err
  1451. }
  1452. cmd.val, err = readXMessageSlice(rd)
  1453. if err != nil {
  1454. return nil, err
  1455. }
  1456. return nil, nil
  1457. })
  1458. return err
  1459. }
  1460. //------------------------------------------------------------------------------
  1461. type XAutoClaimJustIDCmd struct {
  1462. baseCmd
  1463. start string
  1464. val []string
  1465. }
  1466. var _ Cmder = (*XAutoClaimJustIDCmd)(nil)
  1467. func NewXAutoClaimJustIDCmd(ctx context.Context, args ...interface{}) *XAutoClaimJustIDCmd {
  1468. return &XAutoClaimJustIDCmd{
  1469. baseCmd: baseCmd{
  1470. ctx: ctx,
  1471. args: args,
  1472. },
  1473. }
  1474. }
  1475. func (cmd *XAutoClaimJustIDCmd) SetVal(val []string, start string) {
  1476. cmd.val = val
  1477. cmd.start = start
  1478. }
  1479. func (cmd *XAutoClaimJustIDCmd) Val() (ids []string, start string) {
  1480. return cmd.val, cmd.start
  1481. }
  1482. func (cmd *XAutoClaimJustIDCmd) Result() (ids []string, start string, err error) {
  1483. return cmd.val, cmd.start, cmd.err
  1484. }
  1485. func (cmd *XAutoClaimJustIDCmd) String() string {
  1486. return cmdString(cmd, cmd.val)
  1487. }
  1488. func (cmd *XAutoClaimJustIDCmd) readReply(rd *proto.Reader) error {
  1489. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1490. if n != 2 {
  1491. return nil, fmt.Errorf("got %d, wanted 2", n)
  1492. }
  1493. var err error
  1494. cmd.start, err = rd.ReadString()
  1495. if err != nil {
  1496. return nil, err
  1497. }
  1498. nn, err := rd.ReadArrayLen()
  1499. if err != nil {
  1500. return nil, err
  1501. }
  1502. cmd.val = make([]string, nn)
  1503. for i := 0; i < nn; i++ {
  1504. cmd.val[i], err = rd.ReadString()
  1505. if err != nil {
  1506. return nil, err
  1507. }
  1508. }
  1509. return nil, nil
  1510. })
  1511. return err
  1512. }
  1513. //------------------------------------------------------------------------------
  1514. type XInfoConsumersCmd struct {
  1515. baseCmd
  1516. val []XInfoConsumer
  1517. }
  1518. type XInfoConsumer struct {
  1519. Name string
  1520. Pending int64
  1521. Idle int64
  1522. }
  1523. var _ Cmder = (*XInfoConsumersCmd)(nil)
  1524. func NewXInfoConsumersCmd(ctx context.Context, stream string, group string) *XInfoConsumersCmd {
  1525. return &XInfoConsumersCmd{
  1526. baseCmd: baseCmd{
  1527. ctx: ctx,
  1528. args: []interface{}{"xinfo", "consumers", stream, group},
  1529. },
  1530. }
  1531. }
  1532. func (cmd *XInfoConsumersCmd) SetVal(val []XInfoConsumer) {
  1533. cmd.val = val
  1534. }
  1535. func (cmd *XInfoConsumersCmd) Val() []XInfoConsumer {
  1536. return cmd.val
  1537. }
  1538. func (cmd *XInfoConsumersCmd) Result() ([]XInfoConsumer, error) {
  1539. return cmd.val, cmd.err
  1540. }
  1541. func (cmd *XInfoConsumersCmd) String() string {
  1542. return cmdString(cmd, cmd.val)
  1543. }
  1544. func (cmd *XInfoConsumersCmd) readReply(rd *proto.Reader) error {
  1545. n, err := rd.ReadArrayLen()
  1546. if err != nil {
  1547. return err
  1548. }
  1549. cmd.val = make([]XInfoConsumer, n)
  1550. for i := 0; i < n; i++ {
  1551. cmd.val[i], err = readXConsumerInfo(rd)
  1552. if err != nil {
  1553. return err
  1554. }
  1555. }
  1556. return nil
  1557. }
  1558. func readXConsumerInfo(rd *proto.Reader) (XInfoConsumer, error) {
  1559. var consumer XInfoConsumer
  1560. n, err := rd.ReadArrayLen()
  1561. if err != nil {
  1562. return consumer, err
  1563. }
  1564. if n != 6 {
  1565. return consumer, fmt.Errorf("redis: got %d elements in XINFO CONSUMERS reply, wanted 6", n)
  1566. }
  1567. for i := 0; i < 3; i++ {
  1568. key, err := rd.ReadString()
  1569. if err != nil {
  1570. return consumer, err
  1571. }
  1572. val, err := rd.ReadString()
  1573. if err != nil {
  1574. return consumer, err
  1575. }
  1576. switch key {
  1577. case "name":
  1578. consumer.Name = val
  1579. case "pending":
  1580. consumer.Pending, err = strconv.ParseInt(val, 0, 64)
  1581. if err != nil {
  1582. return consumer, err
  1583. }
  1584. case "idle":
  1585. consumer.Idle, err = strconv.ParseInt(val, 0, 64)
  1586. if err != nil {
  1587. return consumer, err
  1588. }
  1589. default:
  1590. return consumer, fmt.Errorf("redis: unexpected content %s in XINFO CONSUMERS reply", key)
  1591. }
  1592. }
  1593. return consumer, nil
  1594. }
  1595. //------------------------------------------------------------------------------
  1596. type XInfoGroupsCmd struct {
  1597. baseCmd
  1598. val []XInfoGroup
  1599. }
  1600. type XInfoGroup struct {
  1601. Name string
  1602. Consumers int64
  1603. Pending int64
  1604. LastDeliveredID string
  1605. }
  1606. var _ Cmder = (*XInfoGroupsCmd)(nil)
  1607. func NewXInfoGroupsCmd(ctx context.Context, stream string) *XInfoGroupsCmd {
  1608. return &XInfoGroupsCmd{
  1609. baseCmd: baseCmd{
  1610. ctx: ctx,
  1611. args: []interface{}{"xinfo", "groups", stream},
  1612. },
  1613. }
  1614. }
  1615. func (cmd *XInfoGroupsCmd) SetVal(val []XInfoGroup) {
  1616. cmd.val = val
  1617. }
  1618. func (cmd *XInfoGroupsCmd) Val() []XInfoGroup {
  1619. return cmd.val
  1620. }
  1621. func (cmd *XInfoGroupsCmd) Result() ([]XInfoGroup, error) {
  1622. return cmd.val, cmd.err
  1623. }
  1624. func (cmd *XInfoGroupsCmd) String() string {
  1625. return cmdString(cmd, cmd.val)
  1626. }
  1627. func (cmd *XInfoGroupsCmd) readReply(rd *proto.Reader) error {
  1628. n, err := rd.ReadArrayLen()
  1629. if err != nil {
  1630. return err
  1631. }
  1632. cmd.val = make([]XInfoGroup, n)
  1633. for i := 0; i < n; i++ {
  1634. cmd.val[i], err = readXGroupInfo(rd)
  1635. if err != nil {
  1636. return err
  1637. }
  1638. }
  1639. return nil
  1640. }
  1641. func readXGroupInfo(rd *proto.Reader) (XInfoGroup, error) {
  1642. var group XInfoGroup
  1643. n, err := rd.ReadArrayLen()
  1644. if err != nil {
  1645. return group, err
  1646. }
  1647. if n != 8 {
  1648. return group, fmt.Errorf("redis: got %d elements in XINFO GROUPS reply, wanted 8", n)
  1649. }
  1650. for i := 0; i < 4; i++ {
  1651. key, err := rd.ReadString()
  1652. if err != nil {
  1653. return group, err
  1654. }
  1655. val, err := rd.ReadString()
  1656. if err != nil {
  1657. return group, err
  1658. }
  1659. switch key {
  1660. case "name":
  1661. group.Name = val
  1662. case "consumers":
  1663. group.Consumers, err = strconv.ParseInt(val, 0, 64)
  1664. if err != nil {
  1665. return group, err
  1666. }
  1667. case "pending":
  1668. group.Pending, err = strconv.ParseInt(val, 0, 64)
  1669. if err != nil {
  1670. return group, err
  1671. }
  1672. case "last-delivered-id":
  1673. group.LastDeliveredID = val
  1674. default:
  1675. return group, fmt.Errorf("redis: unexpected content %s in XINFO GROUPS reply", key)
  1676. }
  1677. }
  1678. return group, nil
  1679. }
  1680. //------------------------------------------------------------------------------
  1681. type XInfoStreamCmd struct {
  1682. baseCmd
  1683. val *XInfoStream
  1684. }
  1685. type XInfoStream struct {
  1686. Length int64
  1687. RadixTreeKeys int64
  1688. RadixTreeNodes int64
  1689. Groups int64
  1690. LastGeneratedID string
  1691. FirstEntry XMessage
  1692. LastEntry XMessage
  1693. }
  1694. var _ Cmder = (*XInfoStreamCmd)(nil)
  1695. func NewXInfoStreamCmd(ctx context.Context, stream string) *XInfoStreamCmd {
  1696. return &XInfoStreamCmd{
  1697. baseCmd: baseCmd{
  1698. ctx: ctx,
  1699. args: []interface{}{"xinfo", "stream", stream},
  1700. },
  1701. }
  1702. }
  1703. func (cmd *XInfoStreamCmd) SetVal(val *XInfoStream) {
  1704. cmd.val = val
  1705. }
  1706. func (cmd *XInfoStreamCmd) Val() *XInfoStream {
  1707. return cmd.val
  1708. }
  1709. func (cmd *XInfoStreamCmd) Result() (*XInfoStream, error) {
  1710. return cmd.val, cmd.err
  1711. }
  1712. func (cmd *XInfoStreamCmd) String() string {
  1713. return cmdString(cmd, cmd.val)
  1714. }
  1715. func (cmd *XInfoStreamCmd) readReply(rd *proto.Reader) error {
  1716. v, err := rd.ReadReply(xStreamInfoParser)
  1717. if err != nil {
  1718. return err
  1719. }
  1720. cmd.val = v.(*XInfoStream)
  1721. return nil
  1722. }
  1723. func xStreamInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
  1724. if n != 14 {
  1725. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM reply,"+
  1726. "wanted 14", n)
  1727. }
  1728. var info XInfoStream
  1729. for i := 0; i < 7; i++ {
  1730. key, err := rd.ReadString()
  1731. if err != nil {
  1732. return nil, err
  1733. }
  1734. switch key {
  1735. case "length":
  1736. info.Length, err = rd.ReadIntReply()
  1737. case "radix-tree-keys":
  1738. info.RadixTreeKeys, err = rd.ReadIntReply()
  1739. case "radix-tree-nodes":
  1740. info.RadixTreeNodes, err = rd.ReadIntReply()
  1741. case "groups":
  1742. info.Groups, err = rd.ReadIntReply()
  1743. case "last-generated-id":
  1744. info.LastGeneratedID, err = rd.ReadString()
  1745. case "first-entry":
  1746. info.FirstEntry, err = readXMessage(rd)
  1747. if err == Nil {
  1748. err = nil
  1749. }
  1750. case "last-entry":
  1751. info.LastEntry, err = readXMessage(rd)
  1752. if err == Nil {
  1753. err = nil
  1754. }
  1755. default:
  1756. return nil, fmt.Errorf("redis: unexpected content %s "+
  1757. "in XINFO STREAM reply", key)
  1758. }
  1759. if err != nil {
  1760. return nil, err
  1761. }
  1762. }
  1763. return &info, nil
  1764. }
  1765. //------------------------------------------------------------------------------
  1766. type XInfoStreamFullCmd struct {
  1767. baseCmd
  1768. val *XInfoStreamFull
  1769. }
  1770. type XInfoStreamFull struct {
  1771. Length int64
  1772. RadixTreeKeys int64
  1773. RadixTreeNodes int64
  1774. LastGeneratedID string
  1775. Entries []XMessage
  1776. Groups []XInfoStreamGroup
  1777. }
  1778. type XInfoStreamGroup struct {
  1779. Name string
  1780. LastDeliveredID string
  1781. PelCount int64
  1782. Pending []XInfoStreamGroupPending
  1783. Consumers []XInfoStreamConsumer
  1784. }
  1785. type XInfoStreamGroupPending struct {
  1786. ID string
  1787. Consumer string
  1788. DeliveryTime time.Time
  1789. DeliveryCount int64
  1790. }
  1791. type XInfoStreamConsumer struct {
  1792. Name string
  1793. SeenTime time.Time
  1794. PelCount int64
  1795. Pending []XInfoStreamConsumerPending
  1796. }
  1797. type XInfoStreamConsumerPending struct {
  1798. ID string
  1799. DeliveryTime time.Time
  1800. DeliveryCount int64
  1801. }
  1802. var _ Cmder = (*XInfoStreamFullCmd)(nil)
  1803. func NewXInfoStreamFullCmd(ctx context.Context, args ...interface{}) *XInfoStreamFullCmd {
  1804. return &XInfoStreamFullCmd{
  1805. baseCmd: baseCmd{
  1806. ctx: ctx,
  1807. args: args,
  1808. },
  1809. }
  1810. }
  1811. func (cmd *XInfoStreamFullCmd) SetVal(val *XInfoStreamFull) {
  1812. cmd.val = val
  1813. }
  1814. func (cmd *XInfoStreamFullCmd) Val() *XInfoStreamFull {
  1815. return cmd.val
  1816. }
  1817. func (cmd *XInfoStreamFullCmd) Result() (*XInfoStreamFull, error) {
  1818. return cmd.val, cmd.err
  1819. }
  1820. func (cmd *XInfoStreamFullCmd) String() string {
  1821. return cmdString(cmd, cmd.val)
  1822. }
  1823. func (cmd *XInfoStreamFullCmd) readReply(rd *proto.Reader) error {
  1824. n, err := rd.ReadArrayLen()
  1825. if err != nil {
  1826. return err
  1827. }
  1828. if n != 12 {
  1829. return fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1830. "wanted 12", n)
  1831. }
  1832. cmd.val = &XInfoStreamFull{}
  1833. for i := 0; i < 6; i++ {
  1834. key, err := rd.ReadString()
  1835. if err != nil {
  1836. return err
  1837. }
  1838. switch key {
  1839. case "length":
  1840. cmd.val.Length, err = rd.ReadIntReply()
  1841. case "radix-tree-keys":
  1842. cmd.val.RadixTreeKeys, err = rd.ReadIntReply()
  1843. case "radix-tree-nodes":
  1844. cmd.val.RadixTreeNodes, err = rd.ReadIntReply()
  1845. case "last-generated-id":
  1846. cmd.val.LastGeneratedID, err = rd.ReadString()
  1847. case "entries":
  1848. cmd.val.Entries, err = readXMessageSlice(rd)
  1849. case "groups":
  1850. cmd.val.Groups, err = readStreamGroups(rd)
  1851. default:
  1852. return fmt.Errorf("redis: unexpected content %s "+
  1853. "in XINFO STREAM reply", key)
  1854. }
  1855. if err != nil {
  1856. return err
  1857. }
  1858. }
  1859. return nil
  1860. }
  1861. func readStreamGroups(rd *proto.Reader) ([]XInfoStreamGroup, error) {
  1862. n, err := rd.ReadArrayLen()
  1863. if err != nil {
  1864. return nil, err
  1865. }
  1866. groups := make([]XInfoStreamGroup, 0, n)
  1867. for i := 0; i < n; i++ {
  1868. nn, err := rd.ReadArrayLen()
  1869. if err != nil {
  1870. return nil, err
  1871. }
  1872. if nn != 10 {
  1873. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1874. "wanted 10", nn)
  1875. }
  1876. group := XInfoStreamGroup{}
  1877. for f := 0; f < 5; f++ {
  1878. key, err := rd.ReadString()
  1879. if err != nil {
  1880. return nil, err
  1881. }
  1882. switch key {
  1883. case "name":
  1884. group.Name, err = rd.ReadString()
  1885. case "last-delivered-id":
  1886. group.LastDeliveredID, err = rd.ReadString()
  1887. case "pel-count":
  1888. group.PelCount, err = rd.ReadIntReply()
  1889. case "pending":
  1890. group.Pending, err = readXInfoStreamGroupPending(rd)
  1891. case "consumers":
  1892. group.Consumers, err = readXInfoStreamConsumers(rd)
  1893. default:
  1894. return nil, fmt.Errorf("redis: unexpected content %s "+
  1895. "in XINFO STREAM reply", key)
  1896. }
  1897. if err != nil {
  1898. return nil, err
  1899. }
  1900. }
  1901. groups = append(groups, group)
  1902. }
  1903. return groups, nil
  1904. }
  1905. func readXInfoStreamGroupPending(rd *proto.Reader) ([]XInfoStreamGroupPending, error) {
  1906. n, err := rd.ReadArrayLen()
  1907. if err != nil {
  1908. return nil, err
  1909. }
  1910. pending := make([]XInfoStreamGroupPending, 0, n)
  1911. for i := 0; i < n; i++ {
  1912. nn, err := rd.ReadArrayLen()
  1913. if err != nil {
  1914. return nil, err
  1915. }
  1916. if nn != 4 {
  1917. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1918. "wanted 4", nn)
  1919. }
  1920. p := XInfoStreamGroupPending{}
  1921. p.ID, err = rd.ReadString()
  1922. if err != nil {
  1923. return nil, err
  1924. }
  1925. p.Consumer, err = rd.ReadString()
  1926. if err != nil {
  1927. return nil, err
  1928. }
  1929. delivery, err := rd.ReadIntReply()
  1930. if err != nil {
  1931. return nil, err
  1932. }
  1933. p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
  1934. p.DeliveryCount, err = rd.ReadIntReply()
  1935. if err != nil {
  1936. return nil, err
  1937. }
  1938. pending = append(pending, p)
  1939. }
  1940. return pending, nil
  1941. }
  1942. func readXInfoStreamConsumers(rd *proto.Reader) ([]XInfoStreamConsumer, error) {
  1943. n, err := rd.ReadArrayLen()
  1944. if err != nil {
  1945. return nil, err
  1946. }
  1947. consumers := make([]XInfoStreamConsumer, 0, n)
  1948. for i := 0; i < n; i++ {
  1949. nn, err := rd.ReadArrayLen()
  1950. if err != nil {
  1951. return nil, err
  1952. }
  1953. if nn != 8 {
  1954. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1955. "wanted 8", nn)
  1956. }
  1957. c := XInfoStreamConsumer{}
  1958. for f := 0; f < 4; f++ {
  1959. cKey, err := rd.ReadString()
  1960. if err != nil {
  1961. return nil, err
  1962. }
  1963. switch cKey {
  1964. case "name":
  1965. c.Name, err = rd.ReadString()
  1966. case "seen-time":
  1967. seen, err := rd.ReadIntReply()
  1968. if err != nil {
  1969. return nil, err
  1970. }
  1971. c.SeenTime = time.Unix(seen/1000, seen%1000*int64(time.Millisecond))
  1972. case "pel-count":
  1973. c.PelCount, err = rd.ReadIntReply()
  1974. case "pending":
  1975. pendingNumber, err := rd.ReadArrayLen()
  1976. if err != nil {
  1977. return nil, err
  1978. }
  1979. c.Pending = make([]XInfoStreamConsumerPending, 0, pendingNumber)
  1980. for pn := 0; pn < pendingNumber; pn++ {
  1981. nn, err := rd.ReadArrayLen()
  1982. if err != nil {
  1983. return nil, err
  1984. }
  1985. if nn != 3 {
  1986. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM reply,"+
  1987. "wanted 3", nn)
  1988. }
  1989. p := XInfoStreamConsumerPending{}
  1990. p.ID, err = rd.ReadString()
  1991. if err != nil {
  1992. return nil, err
  1993. }
  1994. delivery, err := rd.ReadIntReply()
  1995. if err != nil {
  1996. return nil, err
  1997. }
  1998. p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
  1999. p.DeliveryCount, err = rd.ReadIntReply()
  2000. if err != nil {
  2001. return nil, err
  2002. }
  2003. c.Pending = append(c.Pending, p)
  2004. }
  2005. default:
  2006. return nil, fmt.Errorf("redis: unexpected content %s "+
  2007. "in XINFO STREAM reply", cKey)
  2008. }
  2009. if err != nil {
  2010. return nil, err
  2011. }
  2012. }
  2013. consumers = append(consumers, c)
  2014. }
  2015. return consumers, nil
  2016. }
  2017. //------------------------------------------------------------------------------
  2018. type ZSliceCmd struct {
  2019. baseCmd
  2020. val []Z
  2021. }
  2022. var _ Cmder = (*ZSliceCmd)(nil)
  2023. func NewZSliceCmd(ctx context.Context, args ...interface{}) *ZSliceCmd {
  2024. return &ZSliceCmd{
  2025. baseCmd: baseCmd{
  2026. ctx: ctx,
  2027. args: args,
  2028. },
  2029. }
  2030. }
  2031. func (cmd *ZSliceCmd) SetVal(val []Z) {
  2032. cmd.val = val
  2033. }
  2034. func (cmd *ZSliceCmd) Val() []Z {
  2035. return cmd.val
  2036. }
  2037. func (cmd *ZSliceCmd) Result() ([]Z, error) {
  2038. return cmd.val, cmd.err
  2039. }
  2040. func (cmd *ZSliceCmd) String() string {
  2041. return cmdString(cmd, cmd.val)
  2042. }
  2043. func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error {
  2044. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2045. cmd.val = make([]Z, n/2)
  2046. for i := 0; i < len(cmd.val); i++ {
  2047. member, err := rd.ReadString()
  2048. if err != nil {
  2049. return nil, err
  2050. }
  2051. score, err := rd.ReadFloatReply()
  2052. if err != nil {
  2053. return nil, err
  2054. }
  2055. cmd.val[i] = Z{
  2056. Member: member,
  2057. Score: score,
  2058. }
  2059. }
  2060. return nil, nil
  2061. })
  2062. return err
  2063. }
  2064. //------------------------------------------------------------------------------
  2065. type ZWithKeyCmd struct {
  2066. baseCmd
  2067. val *ZWithKey
  2068. }
  2069. var _ Cmder = (*ZWithKeyCmd)(nil)
  2070. func NewZWithKeyCmd(ctx context.Context, args ...interface{}) *ZWithKeyCmd {
  2071. return &ZWithKeyCmd{
  2072. baseCmd: baseCmd{
  2073. ctx: ctx,
  2074. args: args,
  2075. },
  2076. }
  2077. }
  2078. func (cmd *ZWithKeyCmd) SetVal(val *ZWithKey) {
  2079. cmd.val = val
  2080. }
  2081. func (cmd *ZWithKeyCmd) Val() *ZWithKey {
  2082. return cmd.val
  2083. }
  2084. func (cmd *ZWithKeyCmd) Result() (*ZWithKey, error) {
  2085. return cmd.Val(), cmd.Err()
  2086. }
  2087. func (cmd *ZWithKeyCmd) String() string {
  2088. return cmdString(cmd, cmd.val)
  2089. }
  2090. func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error {
  2091. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2092. if n != 3 {
  2093. return nil, fmt.Errorf("got %d elements, expected 3", n)
  2094. }
  2095. cmd.val = &ZWithKey{}
  2096. var err error
  2097. cmd.val.Key, err = rd.ReadString()
  2098. if err != nil {
  2099. return nil, err
  2100. }
  2101. cmd.val.Member, err = rd.ReadString()
  2102. if err != nil {
  2103. return nil, err
  2104. }
  2105. cmd.val.Score, err = rd.ReadFloatReply()
  2106. if err != nil {
  2107. return nil, err
  2108. }
  2109. return nil, nil
  2110. })
  2111. return err
  2112. }
  2113. //------------------------------------------------------------------------------
  2114. type ScanCmd struct {
  2115. baseCmd
  2116. page []string
  2117. cursor uint64
  2118. process cmdable
  2119. }
  2120. var _ Cmder = (*ScanCmd)(nil)
  2121. func NewScanCmd(ctx context.Context, process cmdable, args ...interface{}) *ScanCmd {
  2122. return &ScanCmd{
  2123. baseCmd: baseCmd{
  2124. ctx: ctx,
  2125. args: args,
  2126. },
  2127. process: process,
  2128. }
  2129. }
  2130. func (cmd *ScanCmd) SetVal(page []string, cursor uint64) {
  2131. cmd.page = page
  2132. cmd.cursor = cursor
  2133. }
  2134. func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
  2135. return cmd.page, cmd.cursor
  2136. }
  2137. func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
  2138. return cmd.page, cmd.cursor, cmd.err
  2139. }
  2140. func (cmd *ScanCmd) String() string {
  2141. return cmdString(cmd, cmd.page)
  2142. }
  2143. func (cmd *ScanCmd) readReply(rd *proto.Reader) (err error) {
  2144. cmd.page, cmd.cursor, err = rd.ReadScanReply()
  2145. return err
  2146. }
  2147. // Iterator creates a new ScanIterator.
  2148. func (cmd *ScanCmd) Iterator() *ScanIterator {
  2149. return &ScanIterator{
  2150. cmd: cmd,
  2151. }
  2152. }
  2153. //------------------------------------------------------------------------------
  2154. type ClusterNode struct {
  2155. ID string
  2156. Addr string
  2157. }
  2158. type ClusterSlot struct {
  2159. Start int
  2160. End int
  2161. Nodes []ClusterNode
  2162. }
  2163. type ClusterSlotsCmd struct {
  2164. baseCmd
  2165. val []ClusterSlot
  2166. }
  2167. var _ Cmder = (*ClusterSlotsCmd)(nil)
  2168. func NewClusterSlotsCmd(ctx context.Context, args ...interface{}) *ClusterSlotsCmd {
  2169. return &ClusterSlotsCmd{
  2170. baseCmd: baseCmd{
  2171. ctx: ctx,
  2172. args: args,
  2173. },
  2174. }
  2175. }
  2176. func (cmd *ClusterSlotsCmd) SetVal(val []ClusterSlot) {
  2177. cmd.val = val
  2178. }
  2179. func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
  2180. return cmd.val
  2181. }
  2182. func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
  2183. return cmd.Val(), cmd.Err()
  2184. }
  2185. func (cmd *ClusterSlotsCmd) String() string {
  2186. return cmdString(cmd, cmd.val)
  2187. }
  2188. func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error {
  2189. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2190. cmd.val = make([]ClusterSlot, n)
  2191. for i := 0; i < len(cmd.val); i++ {
  2192. n, err := rd.ReadArrayLen()
  2193. if err != nil {
  2194. return nil, err
  2195. }
  2196. if n < 2 {
  2197. err := fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n)
  2198. return nil, err
  2199. }
  2200. start, err := rd.ReadIntReply()
  2201. if err != nil {
  2202. return nil, err
  2203. }
  2204. end, err := rd.ReadIntReply()
  2205. if err != nil {
  2206. return nil, err
  2207. }
  2208. nodes := make([]ClusterNode, n-2)
  2209. for j := 0; j < len(nodes); j++ {
  2210. n, err := rd.ReadArrayLen()
  2211. if err != nil {
  2212. return nil, err
  2213. }
  2214. if n != 2 && n != 3 {
  2215. err := fmt.Errorf("got %d elements in cluster info address, expected 2 or 3", n)
  2216. return nil, err
  2217. }
  2218. ip, err := rd.ReadString()
  2219. if err != nil {
  2220. return nil, err
  2221. }
  2222. port, err := rd.ReadString()
  2223. if err != nil {
  2224. return nil, err
  2225. }
  2226. nodes[j].Addr = net.JoinHostPort(ip, port)
  2227. if n == 3 {
  2228. id, err := rd.ReadString()
  2229. if err != nil {
  2230. return nil, err
  2231. }
  2232. nodes[j].ID = id
  2233. }
  2234. }
  2235. cmd.val[i] = ClusterSlot{
  2236. Start: int(start),
  2237. End: int(end),
  2238. Nodes: nodes,
  2239. }
  2240. }
  2241. return nil, nil
  2242. })
  2243. return err
  2244. }
  2245. //------------------------------------------------------------------------------
  2246. // GeoLocation is used with GeoAdd to add geospatial location.
  2247. type GeoLocation struct {
  2248. Name string
  2249. Longitude, Latitude, Dist float64
  2250. GeoHash int64
  2251. }
  2252. // GeoRadiusQuery is used with GeoRadius to query geospatial index.
  2253. type GeoRadiusQuery struct {
  2254. Radius float64
  2255. // Can be m, km, ft, or mi. Default is km.
  2256. Unit string
  2257. WithCoord bool
  2258. WithDist bool
  2259. WithGeoHash bool
  2260. Count int
  2261. // Can be ASC or DESC. Default is no sort order.
  2262. Sort string
  2263. Store string
  2264. StoreDist string
  2265. }
  2266. type GeoLocationCmd struct {
  2267. baseCmd
  2268. q *GeoRadiusQuery
  2269. locations []GeoLocation
  2270. }
  2271. var _ Cmder = (*GeoLocationCmd)(nil)
  2272. func NewGeoLocationCmd(ctx context.Context, q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
  2273. return &GeoLocationCmd{
  2274. baseCmd: baseCmd{
  2275. ctx: ctx,
  2276. args: geoLocationArgs(q, args...),
  2277. },
  2278. q: q,
  2279. }
  2280. }
  2281. func geoLocationArgs(q *GeoRadiusQuery, args ...interface{}) []interface{} {
  2282. args = append(args, q.Radius)
  2283. if q.Unit != "" {
  2284. args = append(args, q.Unit)
  2285. } else {
  2286. args = append(args, "km")
  2287. }
  2288. if q.WithCoord {
  2289. args = append(args, "withcoord")
  2290. }
  2291. if q.WithDist {
  2292. args = append(args, "withdist")
  2293. }
  2294. if q.WithGeoHash {
  2295. args = append(args, "withhash")
  2296. }
  2297. if q.Count > 0 {
  2298. args = append(args, "count", q.Count)
  2299. }
  2300. if q.Sort != "" {
  2301. args = append(args, q.Sort)
  2302. }
  2303. if q.Store != "" {
  2304. args = append(args, "store")
  2305. args = append(args, q.Store)
  2306. }
  2307. if q.StoreDist != "" {
  2308. args = append(args, "storedist")
  2309. args = append(args, q.StoreDist)
  2310. }
  2311. return args
  2312. }
  2313. func (cmd *GeoLocationCmd) SetVal(locations []GeoLocation) {
  2314. cmd.locations = locations
  2315. }
  2316. func (cmd *GeoLocationCmd) Val() []GeoLocation {
  2317. return cmd.locations
  2318. }
  2319. func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
  2320. return cmd.locations, cmd.err
  2321. }
  2322. func (cmd *GeoLocationCmd) String() string {
  2323. return cmdString(cmd, cmd.locations)
  2324. }
  2325. func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error {
  2326. v, err := rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q))
  2327. if err != nil {
  2328. return err
  2329. }
  2330. cmd.locations = v.([]GeoLocation)
  2331. return nil
  2332. }
  2333. func newGeoLocationSliceParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  2334. return func(rd *proto.Reader, n int64) (interface{}, error) {
  2335. locs := make([]GeoLocation, 0, n)
  2336. for i := int64(0); i < n; i++ {
  2337. v, err := rd.ReadReply(newGeoLocationParser(q))
  2338. if err != nil {
  2339. return nil, err
  2340. }
  2341. switch vv := v.(type) {
  2342. case string:
  2343. locs = append(locs, GeoLocation{
  2344. Name: vv,
  2345. })
  2346. case *GeoLocation:
  2347. // TODO: avoid copying
  2348. locs = append(locs, *vv)
  2349. default:
  2350. return nil, fmt.Errorf("got %T, expected string or *GeoLocation", v)
  2351. }
  2352. }
  2353. return locs, nil
  2354. }
  2355. }
  2356. func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  2357. return func(rd *proto.Reader, n int64) (interface{}, error) {
  2358. var loc GeoLocation
  2359. var err error
  2360. loc.Name, err = rd.ReadString()
  2361. if err != nil {
  2362. return nil, err
  2363. }
  2364. if q.WithDist {
  2365. loc.Dist, err = rd.ReadFloatReply()
  2366. if err != nil {
  2367. return nil, err
  2368. }
  2369. }
  2370. if q.WithGeoHash {
  2371. loc.GeoHash, err = rd.ReadIntReply()
  2372. if err != nil {
  2373. return nil, err
  2374. }
  2375. }
  2376. if q.WithCoord {
  2377. n, err := rd.ReadArrayLen()
  2378. if err != nil {
  2379. return nil, err
  2380. }
  2381. if n != 2 {
  2382. return nil, fmt.Errorf("got %d coordinates, expected 2", n)
  2383. }
  2384. loc.Longitude, err = rd.ReadFloatReply()
  2385. if err != nil {
  2386. return nil, err
  2387. }
  2388. loc.Latitude, err = rd.ReadFloatReply()
  2389. if err != nil {
  2390. return nil, err
  2391. }
  2392. }
  2393. return &loc, nil
  2394. }
  2395. }
  2396. //------------------------------------------------------------------------------
  2397. // GeoSearchQuery is used for GEOSearch/GEOSearchStore command query.
  2398. type GeoSearchQuery struct {
  2399. Member string
  2400. // Latitude and Longitude when using FromLonLat option.
  2401. Longitude float64
  2402. Latitude float64
  2403. // Distance and unit when using ByRadius option.
  2404. // Can use m, km, ft, or mi. Default is km.
  2405. Radius float64
  2406. RadiusUnit string
  2407. // Height, width and unit when using ByBox option.
  2408. // Can be m, km, ft, or mi. Default is km.
  2409. BoxWidth float64
  2410. BoxHeight float64
  2411. BoxUnit string
  2412. // Can be ASC or DESC. Default is no sort order.
  2413. Sort string
  2414. Count int
  2415. CountAny bool
  2416. }
  2417. type GeoSearchLocationQuery struct {
  2418. GeoSearchQuery
  2419. WithCoord bool
  2420. WithDist bool
  2421. WithHash bool
  2422. }
  2423. type GeoSearchStoreQuery struct {
  2424. GeoSearchQuery
  2425. // When using the StoreDist option, the command stores the items in a
  2426. // sorted set populated with their distance from the center of the circle or box,
  2427. // as a floating-point number, in the same unit specified for that shape.
  2428. StoreDist bool
  2429. }
  2430. func geoSearchLocationArgs(q *GeoSearchLocationQuery, args []interface{}) []interface{} {
  2431. args = geoSearchArgs(&q.GeoSearchQuery, args)
  2432. if q.WithCoord {
  2433. args = append(args, "withcoord")
  2434. }
  2435. if q.WithDist {
  2436. args = append(args, "withdist")
  2437. }
  2438. if q.WithHash {
  2439. args = append(args, "withhash")
  2440. }
  2441. return args
  2442. }
  2443. func geoSearchArgs(q *GeoSearchQuery, args []interface{}) []interface{} {
  2444. if q.Member != "" {
  2445. args = append(args, "frommember", q.Member)
  2446. } else {
  2447. args = append(args, "fromlonlat", q.Longitude, q.Latitude)
  2448. }
  2449. if q.Radius > 0 {
  2450. if q.RadiusUnit == "" {
  2451. q.RadiusUnit = "km"
  2452. }
  2453. args = append(args, "byradius", q.Radius, q.RadiusUnit)
  2454. } else {
  2455. if q.BoxUnit == "" {
  2456. q.BoxUnit = "km"
  2457. }
  2458. args = append(args, "bybox", q.BoxWidth, q.BoxHeight, q.BoxUnit)
  2459. }
  2460. if q.Sort != "" {
  2461. args = append(args, q.Sort)
  2462. }
  2463. if q.Count > 0 {
  2464. args = append(args, "count", q.Count)
  2465. if q.CountAny {
  2466. args = append(args, "any")
  2467. }
  2468. }
  2469. return args
  2470. }
  2471. type GeoSearchLocationCmd struct {
  2472. baseCmd
  2473. opt *GeoSearchLocationQuery
  2474. val []GeoLocation
  2475. }
  2476. var _ Cmder = (*GeoSearchLocationCmd)(nil)
  2477. func NewGeoSearchLocationCmd(
  2478. ctx context.Context, opt *GeoSearchLocationQuery, args ...interface{},
  2479. ) *GeoSearchLocationCmd {
  2480. return &GeoSearchLocationCmd{
  2481. baseCmd: baseCmd{
  2482. ctx: ctx,
  2483. args: args,
  2484. },
  2485. opt: opt,
  2486. }
  2487. }
  2488. func (cmd *GeoSearchLocationCmd) SetVal(val []GeoLocation) {
  2489. cmd.val = val
  2490. }
  2491. func (cmd *GeoSearchLocationCmd) Val() []GeoLocation {
  2492. return cmd.val
  2493. }
  2494. func (cmd *GeoSearchLocationCmd) Result() ([]GeoLocation, error) {
  2495. return cmd.val, cmd.err
  2496. }
  2497. func (cmd *GeoSearchLocationCmd) String() string {
  2498. return cmdString(cmd, cmd.val)
  2499. }
  2500. func (cmd *GeoSearchLocationCmd) readReply(rd *proto.Reader) error {
  2501. n, err := rd.ReadArrayLen()
  2502. if err != nil {
  2503. return err
  2504. }
  2505. cmd.val = make([]GeoLocation, n)
  2506. for i := 0; i < n; i++ {
  2507. _, err = rd.ReadArrayLen()
  2508. if err != nil {
  2509. return err
  2510. }
  2511. var loc GeoLocation
  2512. loc.Name, err = rd.ReadString()
  2513. if err != nil {
  2514. return err
  2515. }
  2516. if cmd.opt.WithDist {
  2517. loc.Dist, err = rd.ReadFloatReply()
  2518. if err != nil {
  2519. return err
  2520. }
  2521. }
  2522. if cmd.opt.WithHash {
  2523. loc.GeoHash, err = rd.ReadIntReply()
  2524. if err != nil {
  2525. return err
  2526. }
  2527. }
  2528. if cmd.opt.WithCoord {
  2529. nn, err := rd.ReadArrayLen()
  2530. if err != nil {
  2531. return err
  2532. }
  2533. if nn != 2 {
  2534. return fmt.Errorf("got %d coordinates, expected 2", nn)
  2535. }
  2536. loc.Longitude, err = rd.ReadFloatReply()
  2537. if err != nil {
  2538. return err
  2539. }
  2540. loc.Latitude, err = rd.ReadFloatReply()
  2541. if err != nil {
  2542. return err
  2543. }
  2544. }
  2545. cmd.val[i] = loc
  2546. }
  2547. return nil
  2548. }
  2549. //------------------------------------------------------------------------------
  2550. type GeoPos struct {
  2551. Longitude, Latitude float64
  2552. }
  2553. type GeoPosCmd struct {
  2554. baseCmd
  2555. val []*GeoPos
  2556. }
  2557. var _ Cmder = (*GeoPosCmd)(nil)
  2558. func NewGeoPosCmd(ctx context.Context, args ...interface{}) *GeoPosCmd {
  2559. return &GeoPosCmd{
  2560. baseCmd: baseCmd{
  2561. ctx: ctx,
  2562. args: args,
  2563. },
  2564. }
  2565. }
  2566. func (cmd *GeoPosCmd) SetVal(val []*GeoPos) {
  2567. cmd.val = val
  2568. }
  2569. func (cmd *GeoPosCmd) Val() []*GeoPos {
  2570. return cmd.val
  2571. }
  2572. func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
  2573. return cmd.Val(), cmd.Err()
  2574. }
  2575. func (cmd *GeoPosCmd) String() string {
  2576. return cmdString(cmd, cmd.val)
  2577. }
  2578. func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error {
  2579. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2580. cmd.val = make([]*GeoPos, n)
  2581. for i := 0; i < len(cmd.val); i++ {
  2582. i := i
  2583. _, err := rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2584. longitude, err := rd.ReadFloatReply()
  2585. if err != nil {
  2586. return nil, err
  2587. }
  2588. latitude, err := rd.ReadFloatReply()
  2589. if err != nil {
  2590. return nil, err
  2591. }
  2592. cmd.val[i] = &GeoPos{
  2593. Longitude: longitude,
  2594. Latitude: latitude,
  2595. }
  2596. return nil, nil
  2597. })
  2598. if err != nil {
  2599. if err == Nil {
  2600. cmd.val[i] = nil
  2601. continue
  2602. }
  2603. return nil, err
  2604. }
  2605. }
  2606. return nil, nil
  2607. })
  2608. return err
  2609. }
  2610. //------------------------------------------------------------------------------
  2611. type CommandInfo struct {
  2612. Name string
  2613. Arity int8
  2614. Flags []string
  2615. ACLFlags []string
  2616. FirstKeyPos int8
  2617. LastKeyPos int8
  2618. StepCount int8
  2619. ReadOnly bool
  2620. }
  2621. type CommandsInfoCmd struct {
  2622. baseCmd
  2623. val map[string]*CommandInfo
  2624. }
  2625. var _ Cmder = (*CommandsInfoCmd)(nil)
  2626. func NewCommandsInfoCmd(ctx context.Context, args ...interface{}) *CommandsInfoCmd {
  2627. return &CommandsInfoCmd{
  2628. baseCmd: baseCmd{
  2629. ctx: ctx,
  2630. args: args,
  2631. },
  2632. }
  2633. }
  2634. func (cmd *CommandsInfoCmd) SetVal(val map[string]*CommandInfo) {
  2635. cmd.val = val
  2636. }
  2637. func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
  2638. return cmd.val
  2639. }
  2640. func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
  2641. return cmd.Val(), cmd.Err()
  2642. }
  2643. func (cmd *CommandsInfoCmd) String() string {
  2644. return cmdString(cmd, cmd.val)
  2645. }
  2646. func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
  2647. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2648. cmd.val = make(map[string]*CommandInfo, n)
  2649. for i := int64(0); i < n; i++ {
  2650. v, err := rd.ReadReply(commandInfoParser)
  2651. if err != nil {
  2652. return nil, err
  2653. }
  2654. vv := v.(*CommandInfo)
  2655. cmd.val[vv.Name] = vv
  2656. }
  2657. return nil, nil
  2658. })
  2659. return err
  2660. }
  2661. func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
  2662. const numArgRedis5 = 6
  2663. const numArgRedis6 = 7
  2664. switch n {
  2665. case numArgRedis5, numArgRedis6:
  2666. // continue
  2667. default:
  2668. return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 7", n)
  2669. }
  2670. var cmd CommandInfo
  2671. var err error
  2672. cmd.Name, err = rd.ReadString()
  2673. if err != nil {
  2674. return nil, err
  2675. }
  2676. arity, err := rd.ReadIntReply()
  2677. if err != nil {
  2678. return nil, err
  2679. }
  2680. cmd.Arity = int8(arity)
  2681. _, err = rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2682. cmd.Flags = make([]string, n)
  2683. for i := 0; i < len(cmd.Flags); i++ {
  2684. switch s, err := rd.ReadString(); {
  2685. case err == Nil:
  2686. cmd.Flags[i] = ""
  2687. case err != nil:
  2688. return nil, err
  2689. default:
  2690. cmd.Flags[i] = s
  2691. }
  2692. }
  2693. return nil, nil
  2694. })
  2695. if err != nil {
  2696. return nil, err
  2697. }
  2698. firstKeyPos, err := rd.ReadIntReply()
  2699. if err != nil {
  2700. return nil, err
  2701. }
  2702. cmd.FirstKeyPos = int8(firstKeyPos)
  2703. lastKeyPos, err := rd.ReadIntReply()
  2704. if err != nil {
  2705. return nil, err
  2706. }
  2707. cmd.LastKeyPos = int8(lastKeyPos)
  2708. stepCount, err := rd.ReadIntReply()
  2709. if err != nil {
  2710. return nil, err
  2711. }
  2712. cmd.StepCount = int8(stepCount)
  2713. for _, flag := range cmd.Flags {
  2714. if flag == "readonly" {
  2715. cmd.ReadOnly = true
  2716. break
  2717. }
  2718. }
  2719. if n == numArgRedis5 {
  2720. return &cmd, nil
  2721. }
  2722. _, err = rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2723. cmd.ACLFlags = make([]string, n)
  2724. for i := 0; i < len(cmd.ACLFlags); i++ {
  2725. switch s, err := rd.ReadString(); {
  2726. case err == Nil:
  2727. cmd.ACLFlags[i] = ""
  2728. case err != nil:
  2729. return nil, err
  2730. default:
  2731. cmd.ACLFlags[i] = s
  2732. }
  2733. }
  2734. return nil, nil
  2735. })
  2736. if err != nil {
  2737. return nil, err
  2738. }
  2739. return &cmd, nil
  2740. }
  2741. //------------------------------------------------------------------------------
  2742. type cmdsInfoCache struct {
  2743. fn func(ctx context.Context) (map[string]*CommandInfo, error)
  2744. once internal.Once
  2745. cmds map[string]*CommandInfo
  2746. }
  2747. func newCmdsInfoCache(fn func(ctx context.Context) (map[string]*CommandInfo, error)) *cmdsInfoCache {
  2748. return &cmdsInfoCache{
  2749. fn: fn,
  2750. }
  2751. }
  2752. func (c *cmdsInfoCache) Get(ctx context.Context) (map[string]*CommandInfo, error) {
  2753. err := c.once.Do(func() error {
  2754. cmds, err := c.fn(ctx)
  2755. if err != nil {
  2756. return err
  2757. }
  2758. // Extensions have cmd names in upper case. Convert them to lower case.
  2759. for k, v := range cmds {
  2760. lower := internal.ToLower(k)
  2761. if lower != k {
  2762. cmds[lower] = v
  2763. }
  2764. }
  2765. c.cmds = cmds
  2766. return nil
  2767. })
  2768. return c.cmds, err
  2769. }
  2770. //------------------------------------------------------------------------------
  2771. type SlowLog struct {
  2772. ID int64
  2773. Time time.Time
  2774. Duration time.Duration
  2775. Args []string
  2776. // These are also optional fields emitted only by Redis 4.0 or greater:
  2777. // https://redis.io/commands/slowlog#output-format
  2778. ClientAddr string
  2779. ClientName string
  2780. }
  2781. type SlowLogCmd struct {
  2782. baseCmd
  2783. val []SlowLog
  2784. }
  2785. var _ Cmder = (*SlowLogCmd)(nil)
  2786. func NewSlowLogCmd(ctx context.Context, args ...interface{}) *SlowLogCmd {
  2787. return &SlowLogCmd{
  2788. baseCmd: baseCmd{
  2789. ctx: ctx,
  2790. args: args,
  2791. },
  2792. }
  2793. }
  2794. func (cmd *SlowLogCmd) SetVal(val []SlowLog) {
  2795. cmd.val = val
  2796. }
  2797. func (cmd *SlowLogCmd) Val() []SlowLog {
  2798. return cmd.val
  2799. }
  2800. func (cmd *SlowLogCmd) Result() ([]SlowLog, error) {
  2801. return cmd.Val(), cmd.Err()
  2802. }
  2803. func (cmd *SlowLogCmd) String() string {
  2804. return cmdString(cmd, cmd.val)
  2805. }
  2806. func (cmd *SlowLogCmd) readReply(rd *proto.Reader) error {
  2807. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2808. cmd.val = make([]SlowLog, n)
  2809. for i := 0; i < len(cmd.val); i++ {
  2810. n, err := rd.ReadArrayLen()
  2811. if err != nil {
  2812. return nil, err
  2813. }
  2814. if n < 4 {
  2815. err := fmt.Errorf("redis: got %d elements in slowlog get, expected at least 4", n)
  2816. return nil, err
  2817. }
  2818. id, err := rd.ReadIntReply()
  2819. if err != nil {
  2820. return nil, err
  2821. }
  2822. createdAt, err := rd.ReadIntReply()
  2823. if err != nil {
  2824. return nil, err
  2825. }
  2826. createdAtTime := time.Unix(createdAt, 0)
  2827. costs, err := rd.ReadIntReply()
  2828. if err != nil {
  2829. return nil, err
  2830. }
  2831. costsDuration := time.Duration(costs) * time.Microsecond
  2832. cmdLen, err := rd.ReadArrayLen()
  2833. if err != nil {
  2834. return nil, err
  2835. }
  2836. if cmdLen < 1 {
  2837. err := fmt.Errorf("redis: got %d elements commands reply in slowlog get, expected at least 1", cmdLen)
  2838. return nil, err
  2839. }
  2840. cmdString := make([]string, cmdLen)
  2841. for i := 0; i < cmdLen; i++ {
  2842. cmdString[i], err = rd.ReadString()
  2843. if err != nil {
  2844. return nil, err
  2845. }
  2846. }
  2847. var address, name string
  2848. for i := 4; i < n; i++ {
  2849. str, err := rd.ReadString()
  2850. if err != nil {
  2851. return nil, err
  2852. }
  2853. if i == 4 {
  2854. address = str
  2855. } else if i == 5 {
  2856. name = str
  2857. }
  2858. }
  2859. cmd.val[i] = SlowLog{
  2860. ID: id,
  2861. Time: createdAtTime,
  2862. Duration: costsDuration,
  2863. Args: cmdString,
  2864. ClientAddr: address,
  2865. ClientName: name,
  2866. }
  2867. }
  2868. return nil, nil
  2869. })
  2870. return err
  2871. }