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: Implement Custom Command with route(Generic Cluster cmd), Ping with Route #2979

Merged
merged 27 commits into from
Jan 29, 2025
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e25d23e
Custom Cmd(Generic Cluster cmd), Ping with Route
niharikabhavaraju Jan 20, 2025
d13523b
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 20, 2025
46ba328
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 20, 2025
b8a7720
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 21, 2025
b082b30
Added Ping , PingWithOptions
niharikabhavaraju Jan 22, 2025
91806cd
Minor changes
niharikabhavaraju Jan 22, 2025
17b1ed8
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 22, 2025
51884e6
Minor lint fix and error fix
niharikabhavaraju Jan 22, 2025
eb60104
Fixed failing tests
niharikabhavaraju Jan 22, 2025
0fd48d2
Fixed linting error
niharikabhavaraju Jan 22, 2025
2761f5d
Fixed lint error
niharikabhavaraju Jan 22, 2025
767e001
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 24, 2025
d6a5c21
Fixed review comments
niharikabhavaraju Jan 27, 2025
1de3c7d
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 27, 2025
2e3d2d7
Minor comments changes
niharikabhavaraju Jan 27, 2025
8ed86c5
Merge branch 'pingcommand-niharika' of github.com:niharikabhavaraju/v…
niharikabhavaraju Jan 27, 2025
6b9a527
Fixed indents
niharikabhavaraju Jan 27, 2025
7e2d86d
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 27, 2025
2ef3929
Fixed Response for Ping
niharikabhavaraju Jan 27, 2025
eacc4a8
Merge branch 'pingcommand-niharika' of github.com:niharikabhavaraju/v…
niharikabhavaraju Jan 27, 2025
b8cf9a5
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 28, 2025
d725726
Fixed code review comments
niharikabhavaraju Jan 28, 2025
88a7a23
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 28, 2025
ac3b8ff
Merge branch 'main' into pingcommand-niharika
niharikabhavaraju Jan 29, 2025
a3f6549
Fixed review comments and failing tests
niharikabhavaraju Jan 29, 2025
23b0bd3
Fixed failed tests
niharikabhavaraju Jan 29, 2025
2c04be7
Update go/api/glide_cluster_client.go
Yury-Fridlyand Jan 29, 2025
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
Next Next commit
Custom Cmd(Generic Cluster cmd), Ping with Route
Signed-off-by: Niharika Bhavaraju <nbhavaraju@google.com>
  • Loading branch information
niharikabhavaraju committed Jan 20, 2025
commit e25d23e241bee89522eec395fe4b7e80b4556809
14 changes: 14 additions & 0 deletions go/api/connection_management_cluster_commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0

package api

// Supports commands and transactions for the "Connection Management" group of commands for cluster client.
//
// See [valkey.io] for details.
//
// [valkey.io]: https://valkey.io/commands/#connection
type ConnectionManagementClusterCommands interface {
PingWithRoute(route route) (string, error)

PingWithMessageRoute(message string, route route) (string, error)
}
2 changes: 2 additions & 0 deletions go/api/generic_cluster_commands.go
Original file line number Diff line number Diff line change
@@ -34,4 +34,6 @@ type GenericClusterCommands interface {
//
// [Valkey GLIDE Wiki]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#custom-command
CustomCommand(args []string) (ClusterValue[interface{}], error)

CustomCommandWithRoute(args []string, route route) (ClusterValue[interface{}], error)
}
92 changes: 92 additions & 0 deletions go/api/glide_cluster_client.go
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ var _ GlideClusterClient = (*glideClusterClient)(nil)
type GlideClusterClient interface {
BaseClient
GenericClusterCommands
ConnectionManagementClusterCommands
}

// glideClusterClient implements cluster mode operations by extending baseClient functionality.
@@ -41,3 +42,94 @@ func (client *glideClusterClient) CustomCommand(args []string) (ClusterValue[int
}
return CreateClusterValue(data), nil
}

// CustomCommandWithRoute executes a single command, specified by args, without checking inputs. Every part of the command,
// including the command name and subcommands, should be added as a separate value in args. The returning value depends on
// the executed
// command.
//
// The command will be routed automatically based on the passed command's default request policy.
//
// See [Valkey GLIDE Wiki] for details on the restrictions and limitations of the custom command API.
//
// Parameters:
//
// args - Arguments for the custom command including the command name.
// route - Specifies the routing configuration for the command. The client will route the
// command to the nodes defined by route.
//
// Return value:
//
// The returning value depends on the executed command and route.
//
// For example:
//
// route := api.SimpleNodeRoute(api.RandomRoute)
// result, err := client.CustomCommand([]string{"ping"}, route)
// result.Value().(string): "PONG"
//
// [Valkey GLIDE Wiki]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#custom-command
func (client *glideClusterClient) CustomCommandWithRoute(args []string, route route) (ClusterValue[interface{}], error) {
res, err := client.executeCommandWithRoute(C.CustomCommand, args, route)
if err != nil {
return CreateEmptyClusterValue(), err
}
data, err := handleInterfaceResponse(res)
if err != nil {
return CreateEmptyClusterValue(), err
}
return CreateClusterValue(data), nil
}

// Pings the server.
//
// Parameters:
//
// route - Specifies the routing configuration for the command.
// The client will route the command to the nodes defined by route.
//
// Return value:
//
// Returns "PONG".
//
// For example:
//
// route := api.SimpleNodeRoute(api.RandomRoute)
// result, err := client.Ping(route)
// fmt.Println(result) // Output: "PONG"
//
// [valkey.io]: https://valkey.io/commands/ping/
func (client *glideClusterClient) PingWithRoute(route route) (string, error) {
res, err := client.executeCommandWithRoute(C.Ping, []string{}, route)
if err != nil {
return defaultStringResponse, err
}
return handleStringResponse(res)
}

// Pings the server with a custom message.
//
// Parameters:
//
// message - A message to include in the `PING` command.
// route - Specifies the routing configuration for the command.
// The client will route the command to the nodes defined by route.
//
// Return value:
//
// Returns the copy of message.
//
// For example:
//
// route := api.SimpleNodeRoute(api.RandomRoute)
// result, err := client.PingWithMessage("Hello", route)
// fmt.Println(result) // Output: "Hello"
//
// [valkey.io]: https://valkey.io/commands/ping/
func (client *glideClusterClient) PingWithMessageRoute(message string, route route) (string, error) {
res, err := client.executeCommandWithRoute(C.Ping, []string{message}, route)
if err != nil {
return defaultStringResponse, err
}
return handleStringResponse(res)
}
104 changes: 104 additions & 0 deletions go/integTest/cluster_commands_test.go
Original file line number Diff line number Diff line change
@@ -3,9 +3,11 @@
package integTest

import (
"fmt"
"strings"

"github.com/stretchr/testify/assert"
"github.com/valkey-io/valkey-glide/go/glide/api"
)

func (suite *GlideTestSuite) TestClusterCustomCommandInfo() {
@@ -27,3 +29,105 @@ func (suite *GlideTestSuite) TestClusterCustomCommandEcho() {
// ECHO is routed to a single random node
assert.Equal(suite.T(), "GO GLIDE GO", result.Value().(string))
}

func (suite *GlideTestSuite) TestPingWithRoute_ValidRoute() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.RandomRoute)
result, err := client.PingWithRoute(route)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "PONG", result)
}

func (suite *GlideTestSuite) TestPingWithRoute_InvalidRoute() {
client := suite.defaultClusterClient()
invalidRoute := api.NewByAddressRoute("invalidHost", 9999)

result, err := client.PingWithRoute(invalidRoute)

assert.NotNil(suite.T(), err)
assert.Empty(suite.T(), result)
}

func (suite *GlideTestSuite) TestPingWithMessageRoute_ValidRoute_ValidMessage() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.RandomRoute)

customMessage := "Hello Glide"

result, err := client.PingWithMessageRoute(customMessage, route)

assert.NoError(suite.T(), err)
assert.Equal(suite.T(), customMessage, result)
}

func (suite *GlideTestSuite) TestPingWithMessageRoute_EmptyMessage() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.RandomRoute)

customMessage := ""

result, err := client.PingWithMessageRoute(customMessage, route)

assert.NoError(suite.T(), err)

assert.Equal(suite.T(), customMessage, result)
}

func (suite *GlideTestSuite) TestPingWithMessageRoute_InvalidRoute() {
client := suite.defaultClusterClient()
invalidRoute := api.NewByAddressRoute("invalidHost", 9999)

customMessage := "Hello Glide"

result, err := client.PingWithMessageRoute(customMessage, invalidRoute)

assert.NotNil(suite.T(), err)
assert.Empty(suite.T(), result)
}

func (suite *GlideTestSuite) TestClusterCustomCommandWithRoute_Info() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.AllPrimaries)
result, err := client.CustomCommandWithRoute([]string{"INFO"}, route)
assert.Nil(suite.T(), err)
for _, value := range result.Value().(map[string]interface{}) {
assert.True(suite.T(), strings.Contains(value.(string), "# Stats"))
}
}

func (suite *GlideTestSuite) TestClusterCustomCommandWithRoute_Echo() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.RandomRoute)
result, err := client.CustomCommandWithRoute([]string{"ECHO", "GO GLIDE GO"}, route)
assert.Nil(suite.T(), err)
assert.Equal(suite.T(), "GO GLIDE GO", result.Value().(string))
}

func (suite *GlideTestSuite) TestClusterCustomCommandWithRoute_InvalidRoute() {
client := suite.defaultClusterClient()
invalidRoute := api.NewByAddressRoute("invalidHost", 9999)
result, err := client.CustomCommandWithRoute([]string{"PING"}, invalidRoute)
assert.NotNil(suite.T(), err)
assert.Equal(suite.T(), api.CreateEmptyClusterValue(), result)
}

func (suite *GlideTestSuite) TestClusterCustomCommandWithRoute_AllNodes() {
client := suite.defaultClusterClient()
route := api.SimpleNodeRoute(api.AllNodes)
result, err := client.CustomCommandWithRoute([]string{"PING"}, route)

assert.Nil(suite.T(), err)
value := result.Value()

fmt.Printf("Value type: %T\n", value)

if result.IsMultiValue() {
responses := value.(map[string]interface{})
assert.Greater(suite.T(), len(responses), 0)
for _, response := range responses {
assert.Equal(suite.T(), "PONG", response.(string))
}
} else {
assert.Equal(suite.T(), "PONG", value.(string))
}
}
Loading