Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go: INFO. #2988

Merged
merged 7 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions go/api/command_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package api
import (
"strconv"

"github.com/valkey-io/valkey-glide/go/glide/api/config"
"github.com/valkey-io/valkey-glide/go/glide/api/errors"
"github.com/valkey-io/valkey-glide/go/glide/utils"
)
Expand Down Expand Up @@ -357,6 +358,73 @@ func (opts *RestoreOptions) toArgs() ([]string, error) {
return args, err
}

type Section string

const (
// SERVER: General information about the server
Server Section = "server"
// CLIENTS: Client connections section
Clients Section = "clients"
// MEMORY: Memory consumption related information
Memory Section = "memory"
// PERSISTENCE: RDB and AOF related information
Persistence Section = "persistence"
// STATS: General statistics
Stats Section = "stats"
// REPLICATION: Master/replica replication information
Replication Section = "replication"
// CPU: CPU consumption statistics
Cpu Section = "cpu"
// COMMANDSTATS: Valkey command statistics
Commandstats Section = "commandstats"
// LATENCYSTATS: Valkey command latency percentile distribution statistics
Latencystats Section = "latencystats"
// SENTINEL: Valkey Sentinel section (only applicable to Sentinel instances)
Sentinel Section = "sentinel"
// CLUSTER: Valkey Cluster section
Cluster Section = "cluster"
// MODULES: Modules section
Modules Section = "modules"
// KEYSPACE: Database related statistics
Keyspace Section = "keyspace"
// ERRORSTATS: Valkey error statistics
Errorstats Section = "errorstats"
// ALL: Return all sections (excluding module generated ones)
All Section = "all"
// DEFAULT: Return only the default set of sections
Default Section = "default"
// EVERYTHING: Includes all and modules
Everything Section = "everything"
)

// Optional arguments for `Info` for standalone client
type InfoOptions struct {
// A list of [Section] values specifying which sections of information to retrieve.
// When no parameter is provided, [Section.Default] is assumed.
// Starting with server version 7.0.0 `INFO` command supports multiple sections.
Sections []Section
}

// Optional arguments for `Info` for cluster client
type ClusterInfoOptions struct {
*InfoOptions
// Specifies the routing configuration for the command.
// The client will route the command to the nodes defined by `Route`.
// The command will be routed to all primary nodes, unless `Route` is provided.
Route *config.Route
}

func (opts *InfoOptions) toArgs() []string {
if opts == nil {
return []string{}
}
args := make([]string, 0, len(opts.Sections))
for _, section := range opts.Sections {
args = append(args, string(section))
}
return args
}

// Optional arguments to Copy(source string, destination string, option *CopyOptions)
//
// [valkey.io]: https://valkey.io/commands/Copy/
Expand Down
17 changes: 17 additions & 0 deletions go/api/config/request_routing_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ import (
// - [config.ByAddressRoute]
type Route interface {
ToRoutesProtobuf() (*protobuf.Routes, error)
IsMultiNode() bool
}

type notMultiNode struct{}

func (*notMultiNode) IsMultiNode() bool { return false }

type SimpleNodeRoute int

const (
Expand Down Expand Up @@ -47,6 +52,15 @@ func (simpleNodeRoute SimpleNodeRoute) ToRoutesProtobuf() (*protobuf.Routes, err
return request, nil
}

func (route SimpleNodeRoute) IsMultiNode() bool {
return route != RandomRoute
}

func (snr SimpleNodeRoute) ToPtr() *Route {
a := Route(snr)
return &a
}

func mapSimpleNodeRoute(simpleNodeRoute SimpleNodeRoute) (protobuf.SimpleRoutes, error) {
switch simpleNodeRoute {
case AllNodes:
Expand Down Expand Up @@ -86,6 +100,7 @@ func mapSlotType(slotType SlotType) (protobuf.SlotTypes, error) {
type SlotIdRoute struct {
slotType SlotType
slotID int32
notMultiNode
}

// - slotType: Defines type of the node being addressed.
Expand Down Expand Up @@ -117,6 +132,7 @@ func (slotIdRoute *SlotIdRoute) ToRoutesProtobuf() (*protobuf.Routes, error) {
type SlotKeyRoute struct {
slotType SlotType
slotKey string
notMultiNode
}

// - slotType: Defines type of the node being addressed.
Expand Down Expand Up @@ -146,6 +162,7 @@ func (slotKeyRoute *SlotKeyRoute) ToRoutesProtobuf() (*protobuf.Routes, error) {
type ByAddressRoute struct {
host string
port int32
notMultiNode
}

// Create a route using hostname/address and port.
Expand Down
56 changes: 54 additions & 2 deletions go/api/glide_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (client *GlideClient) CustomCommand(args []string) (interface{}, error) {
func (client *GlideClient) ConfigSet(parameters map[string]string) (string, error) {
result, err := client.executeCommand(C.ConfigSet, utils.MapToString(parameters))
if err != nil {
return "", err
return defaultStringResponse, err
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome job on fixing little code quality issues. We should all be looking for opportunities to do this as part of our PRs when we are already making changes to existing code.

}
return handleStringResponse(result)
}
Expand Down Expand Up @@ -145,7 +145,59 @@ func (client *GlideClient) ConfigGet(args []string) (map[string]string, error) {
func (client *GlideClient) Select(index int64) (string, error) {
result, err := client.executeCommand(C.Select, []string{utils.IntToString(index)})
if err != nil {
return "", err
return defaultStringResponse, err
}

return handleStringResponse(result)
}

// Gets information and statistics about the server.
//
// See [valkey.io] for details.
//
// Return value:
//
// A string with the information for the default sections.
//
// Example:
//
// response, err := standaloneClient.Info(opts)
// if err != nil {
// // handle error
// }
// fmt.Println(response)
//
// [valkey.io]: https://valkey.io/commands/info/
func (client *GlideClient) Info() (string, error) {
return client.InfoWithOptions(InfoOptions{[]Section{}})
}

// Gets information and statistics about the server.
//
// See [valkey.io] for details.
//
// Parameters:
//
// options - Additional command parameters, see [InfoOptions] for more details.
//
// Return value:
//
// A string containing the information for the sections requested.
//
// Example:
//
// opts := api.InfoOptions{Sections: []api.Section{api.Server}}
// response, err := standaloneClient.InfoWithOptions(opts)
// if err != nil {
// // handle error
// }
// fmt.Println(response)
//
// [valkey.io]: https://valkey.io/commands/info/
func (client *GlideClient) InfoWithOptions(options InfoOptions) (string, error) {
result, err := client.executeCommand(C.Info, options.toArgs())
if err != nil {
return defaultStringResponse, err
}

return handleStringResponse(result)
Expand Down
97 changes: 94 additions & 3 deletions go/api/glide_cluster_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var _ GlideClusterClientCommands = (*GlideClusterClient)(nil)
type GlideClusterClientCommands interface {
BaseClient
GenericClusterCommands
ServerManagementClusterCommands
}

// GlideClusterClient implements cluster mode operations by extending baseClient functionality.
Expand Down Expand Up @@ -61,11 +62,101 @@ func NewGlideClusterClient(config *GlideClusterClientConfiguration) (GlideCluste
func (client *GlideClusterClient) CustomCommand(args []string) (ClusterValue[interface{}], error) {
res, err := client.executeCommand(C.CustomCommand, args)
if err != nil {
return CreateEmptyClusterValue(), err
return createEmptyClusterValue[interface{}](), err
}
data, err := handleInterfaceResponse(res)
if err != nil {
return CreateEmptyClusterValue(), err
return createEmptyClusterValue[interface{}](), err
}
return CreateClusterValue(data), nil
return createClusterValue[interface{}](data), nil
}

// Gets information and statistics about the server.
//
// The command will be routed to all primary nodes.
//
// See [valkey.io] for details.
//
// Return value:
//
// A map where each address is the key and its corresponding node response is the information for the default sections.
//
// Example:
//
// response, err := clusterClient.Info(opts)
// if err != nil {
// // handle error
// }
// for node, data := range response {
// fmt.Printf("%s node returned %s\n", node, data)
// }
//
// [valkey.io]: https://valkey.io/commands/info/
func (client *GlideClusterClient) Info() (map[string]string, error) {
result, err := client.executeCommand(C.Info, []string{})
if err != nil {
return nil, err
}

return handleStringToStringMapResponse(result)
}

// Gets information and statistics about the server.
//
// The command will be routed to all primary nodes, unless `route` in [ClusterInfoOptions] is provided.
//
// See [valkey.io] for details.
//
// Parameters:
//
// options - Additional command parameters, see [ClusterInfoOptions] for more details.
//
// Return value:
//
// When specifying a route other than a single node or when route is not given,
// it returns a map where each address is the key and its corresponding node response is the value.
// When a single node route is given, command returns a string containing the information for the sections requested.
//
// Example:
//
// opts := api.ClusterInfoOptions{
// InfoOptions: &api.InfoOptions{Sections: []api.Section{api.Server}},
// Route: api.RandomRoute.ToPtr(),
// }
// response, err := clusterClient.InfoWithOptions(opts)
// if err != nil {
// // handle error
// }
// // Command sent to a single random node via RANDOM route, expecting SingleValue result as a `string`.
// fmt.Println(response.SingleValue())
//
// [valkey.io]: https://valkey.io/commands/info/
func (client *GlideClusterClient) InfoWithOptions(options ClusterInfoOptions) (ClusterValue[string], error) {
if options.Route == nil {
response, err := client.executeCommand(C.Info, options.toArgs())
if err != nil {
return createEmptyClusterValue[string](), err
}
data, err := handleStringToStringMapResponse(response)
if err != nil {
return createEmptyClusterValue[string](), err
}
return createClusterMultiValue[string](data), nil
}
response, err := client.executeCommandWithRoute(C.Info, options.toArgs(), *options.Route)
if err != nil {
return createEmptyClusterValue[string](), err
}
if (*options.Route).IsMultiNode() {
data, err := handleStringToStringMapResponse(response)
if err != nil {
return createEmptyClusterValue[string](), err
}
return createClusterMultiValue[string](data), nil
}
data, err := handleStringResponse(response)
if err != nil {
return createEmptyClusterValue[string](), err
}
return createClusterSingleValue[string](data), nil
}
Loading
Loading