Skip to content

Commit

Permalink
Refactor reply parser.
Browse files Browse the repository at this point in the history
  • Loading branch information
vmihailenco committed Oct 7, 2015
1 parent 2d37474 commit b23b9b7
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 267 deletions.
2 changes: 1 addition & 1 deletion cluster_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (pipe *ClusterPipeline) execClusterCmds(

var firstCmdErr error
for i, cmd := range cmds {
err := cmd.parseReply(cn)
err := cmd.readReply(cn)
if err == nil {
continue
}
Expand Down
178 changes: 74 additions & 104 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var (

type Cmder interface {
args() []interface{}
parseReply(*conn) error
readReply(*conn) error
setErr(error)
reset()

Expand Down Expand Up @@ -152,14 +152,20 @@ func (cmd *Cmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *Cmd) parseReply(cn *conn) error {
cmd.val, cmd.err = parseReply(cn, parseSlice)
// Convert to string to preserve old behaviour.
// TODO: remove in v4
if v, ok := cmd.val.([]byte); ok {
func (cmd *Cmd) readReply(cn *conn) error {
val, err := readReply(cn, sliceParser)
if err != nil {
cmd.err = err
return cmd.err
}
if v, ok := val.([]byte); ok {
// Convert to string to preserve old behaviour.
// TODO: remove in v4
cmd.val = string(v)
} else {
cmd.val = val
}
return cmd.err
return nil
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -191,8 +197,8 @@ func (cmd *SliceCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *SliceCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseSlice)
func (cmd *SliceCmd) readReply(cn *conn) error {
v, err := readReply(cn, sliceParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -234,8 +240,8 @@ func (cmd *StatusCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *StatusCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *StatusCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -273,8 +279,8 @@ func (cmd *IntCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *IntCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *IntCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -316,8 +322,8 @@ func (cmd *DurationCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *DurationCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *DurationCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -357,8 +363,8 @@ func (cmd *BoolCmd) String() string {

var ok = []byte("OK")

func (cmd *BoolCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *BoolCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
// `SET key value NX` returns nil when key already exists, which
// is inconsistent with `SETNX key value`.
// TODO: is this okay?
Expand Down Expand Up @@ -443,8 +449,8 @@ func (cmd *StringCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *StringCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *StringCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -482,8 +488,8 @@ func (cmd *FloatCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *FloatCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, nil)
func (cmd *FloatCmd) readReply(cn *conn) error {
v, err := readReply(cn, nil)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -522,8 +528,8 @@ func (cmd *StringSliceCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *StringSliceCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseStringSlice)
func (cmd *StringSliceCmd) readReply(cn *conn) error {
v, err := readReply(cn, stringSliceParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -561,8 +567,8 @@ func (cmd *BoolSliceCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *BoolSliceCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseBoolSlice)
func (cmd *BoolSliceCmd) readReply(cn *conn) error {
v, err := readReply(cn, boolSliceParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -600,8 +606,8 @@ func (cmd *StringStringMapCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *StringStringMapCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseStringStringMap)
func (cmd *StringStringMapCmd) readReply(cn *conn) error {
v, err := readReply(cn, stringStringMapParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -639,8 +645,8 @@ func (cmd *StringIntMapCmd) reset() {
cmd.err = nil
}

func (cmd *StringIntMapCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseStringIntMap)
func (cmd *StringIntMapCmd) readReply(cn *conn) error {
v, err := readReply(cn, stringIntMapParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -678,8 +684,8 @@ func (cmd *ZSliceCmd) String() string {
return cmdString(cmd, cmd.val)
}

func (cmd *ZSliceCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseZSlice)
func (cmd *ZSliceCmd) readReply(cn *conn) error {
v, err := readReply(cn, zSliceParser)
if err != nil {
cmd.err = err
return err
Expand Down Expand Up @@ -719,8 +725,8 @@ func (cmd *ScanCmd) String() string {
return cmdString(cmd, cmd.keys)
}

func (cmd *ScanCmd) parseReply(cn *conn) error {
vi, err := parseReply(cn, parseSlice)
func (cmd *ScanCmd) readReply(cn *conn) error {
vi, err := readReply(cn, sliceParser)
if err != nil {
cmd.err = err
return cmd.err
Expand All @@ -743,8 +749,9 @@ func (cmd *ScanCmd) parseReply(cn *conn) error {
//------------------------------------------------------------------------------

type ClusterSlotInfo struct {
Start, End int
Addrs []string
Start int
End int
Addrs []string
}

type ClusterSlotCmd struct {
Expand Down Expand Up @@ -774,8 +781,8 @@ func (cmd *ClusterSlotCmd) reset() {
cmd.err = nil
}

func (cmd *ClusterSlotCmd) parseReply(cn *conn) error {
v, err := parseReply(cn, parseClusterSlotInfoSlice)
func (cmd *ClusterSlotCmd) readReply(cn *conn) error {
v, err := readReply(cn, clusterSlotInfoSliceParser)
if err != nil {
cmd.err = err
return err
Expand All @@ -786,99 +793,62 @@ func (cmd *ClusterSlotCmd) parseReply(cn *conn) error {

//------------------------------------------------------------------------------

// Location type for GEO operations in Redis
// GeoLocation is used with GeoAdd to add geospatial location.
type GeoLocation struct {
Name string
Name string
Longitude, Latitude, Distance float64
GeoHash int64
GeoHash int64
}

type GeoCmd struct {
// GeoRadiusQuery is used with GeoRadius to query geospatial index.
type GeoRadiusQuery struct {
Key string
Longitude float64
Latitude float64
Radius float64
// Can be m, km, ft, or mi. Default is km.
Unit string
WithCoordinates bool
WithDistance bool
WithGeoHash bool
Count int
// Can be ASC or DESC. Default is no sort order.
Sort string
}

type GeoLocationCmd struct {
baseCmd

locations []GeoLocation
}

// Query type for geo radius
type GeoRadiusQuery struct {
Key string
Longitude, Latitude, Radius float64
// Unit default to km when nil
Unit string
WithCoordinates, WithDistance, WithGeoHash bool
// Count default to 0 and ignored limit.
Count int
// Sort default to unsorted, ASC or DESC otherwise
Sort string
func NewGeoLocationCmd(args ...interface{}) *GeoLocationCmd {
return &GeoLocationCmd{baseCmd: baseCmd{_args: args, _clusterKeyPos: 1}}
}

func NewGeoCmd(args ...interface{}) *GeoCmd {
return &GeoCmd{baseCmd: baseCmd{_args: args, _clusterKeyPos: 1}}
}

func (cmd *GeoCmd) reset() {
func (cmd *GeoLocationCmd) reset() {
cmd.locations = nil
cmd.err = nil
}

func (cmd *GeoCmd) Val() ([]GeoLocation) {
func (cmd *GeoLocationCmd) Val() []GeoLocation {
return cmd.locations
}

func (cmd *GeoCmd) Result() ([]GeoLocation, error) {
func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
return cmd.locations, cmd.err
}

func (cmd *GeoCmd) String() string {
func (cmd *GeoLocationCmd) String() string {
return cmdString(cmd, cmd.locations)
}

func (cmd *GeoCmd) parseReply(cn *conn) error {
vi, err := parseReply(cn, parseSlice)
func (cmd *GeoLocationCmd) readReply(cn *conn) error {
reply, err := readReply(cn, geoLocationSliceParser)
if err != nil {
cmd.err = err
return cmd.err
}

v := vi.([]interface{})

if len(v) == 0 {
return nil
}

if _, ok := v[0].(string); ok { // Location names only (single level string array)
for _, keyi := range v {
cmd.locations = append(cmd.locations, GeoLocation{Name: keyi.(string)})
}
} else { // Full location details (nested arrays)
for _, keyi := range v {
tmpLocation := GeoLocation{}
keyiface := keyi.([]interface{})
for _, subKeyi := range keyiface {
if strVal, ok := subKeyi.(string); ok {
if len(tmpLocation.Name) == 0 {
tmpLocation.Name = strVal
} else {
tmpLocation.Distance, err = strconv.ParseFloat(strVal, 64)
if err != nil {
return err
}
}
} else if intVal, ok := subKeyi.(int64); ok {
tmpLocation.GeoHash = intVal
} else if ifcVal, ok := subKeyi.([]interface{}); ok {
tmpLocation.Longitude, err = strconv.ParseFloat(ifcVal[0].(string), 64)
if err != nil {
return err
}
tmpLocation.Latitude, err = strconv.ParseFloat(ifcVal[1].(string), 64)
if err != nil {
return err
}
}
}
cmd.locations = append(cmd.locations, tmpLocation)
}
return err
}
cmd.locations = reply.([]GeoLocation)
return nil
}
Loading

0 comments on commit b23b9b7

Please sign in to comment.