From 0426631fd6986a1654453687465cb1ab27ddbc12 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 20 Jan 2025 10:01:01 -0800 Subject: [PATCH 1/5] Go: `XGROUP CREATE`. (#2966) * Go: `XGROUP CREATE`. Signed-off-by: Yury-Fridlyand --- go/api/base_client.go | 67 ++++++++++++++++++++++++++++ go/api/options/stream_options.go | 40 +++++++++++++++++ go/api/stream_commands.go | 4 ++ go/integTest/shared_commands_test.go | 63 +++++++++++++++++++++----- 4 files changed, 162 insertions(+), 12 deletions(-) diff --git a/go/api/base_client.go b/go/api/base_client.go index 19138e2601..f7313e05d6 100644 --- a/go/api/base_client.go +++ b/go/api/base_client.go @@ -2506,6 +2506,73 @@ func (client *baseClient) XPendingWithOptions( return handleXPendingDetailResponse(result) } +// Creates a new consumer group uniquely identified by `groupname` for the stream stored at `key`. +// +// See [valkey.io] for details. +// +// Parameters: +// +// key - The key of the stream. +// group - The newly created consumer group name. +// id - Stream entry ID that specifies the last delivered entry in the stream from the new +// group’s perspective. The special ID `"$"` can be used to specify the last entry in the stream. +// +// Return value: +// +// `"OK"`. +// +// Example: +// +// ok, err := client.XGroupCreate("mystream", "mygroup", "0-0") +// if ok != "OK" || err != nil { +// // handle error +// } +// +// [valkey.io]: https://valkey.io/commands/xgroup-create/ +func (client *baseClient) XGroupCreate(key string, group string, id string) (string, error) { + return client.XGroupCreateWithOptions(key, group, id, options.NewXGroupCreateOptions()) +} + +// Creates a new consumer group uniquely identified by `groupname` for the stream stored at `key`. +// +// See [valkey.io] for details. +// +// Parameters: +// +// key - The key of the stream. +// group - The newly created consumer group name. +// id - Stream entry ID that specifies the last delivered entry in the stream from the new +// group's perspective. The special ID `"$"` can be used to specify the last entry in the stream. +// opts - The options for the command. See [options.XGroupCreateOptions] for details. +// +// Return value: +// +// `"OK"`. +// +// Example: +// +// opts := options.NewXGroupCreateOptions().SetMakeStream() +// ok, err := client.XGroupCreateWithOptions("mystream", "mygroup", "0-0", opts) +// if ok != "OK" || err != nil { +// // handle error +// } +// +// [valkey.io]: https://valkey.io/commands/xgroup-create/ +func (client *baseClient) XGroupCreateWithOptions( + key string, + group string, + id string, + opts *options.XGroupCreateOptions, +) (string, error) { + optionArgs, _ := opts.ToArgs() + args := append([]string{key, group, id}, optionArgs...) + result, err := client.executeCommand(C.XGroupCreate, args) + if err != nil { + return defaultStringResponse, err + } + return handleStringResponse(result) +} + func (client *baseClient) Restore(key string, ttl int64, value string) (Result[string], error) { return client.RestoreWithOptions(key, ttl, value, NewRestoreOptionsBuilder()) } diff --git a/go/api/options/stream_options.go b/go/api/options/stream_options.go index 4507b0478c..cb27269f3b 100644 --- a/go/api/options/stream_options.go +++ b/go/api/options/stream_options.go @@ -262,3 +262,43 @@ func (xpo *XPendingOptions) ToArgs() ([]string, error) { return args, nil } + +// Optional arguments for `XGroupCreate` in [StreamCommands] +type XGroupCreateOptions struct { + mkStream bool + entriesRead int64 +} + +// Create new empty `XGroupCreateOptions` +func NewXGroupCreateOptions() *XGroupCreateOptions { + return &XGroupCreateOptions{false, -1} +} + +// Once set and if the stream doesn't exist, creates a new stream with a length of `0`. +func (xgco *XGroupCreateOptions) SetMakeStream() *XGroupCreateOptions { + xgco.mkStream = true + return xgco +} + +// A value representing the number of stream entries already read by the group. +// +// Since Valkey version 7.0.0. +func (xgco *XGroupCreateOptions) SetEntriesRead(entriesRead int64) *XGroupCreateOptions { + xgco.entriesRead = entriesRead + return xgco +} + +func (xgco *XGroupCreateOptions) ToArgs() ([]string, error) { + var args []string + + // if minIdleTime is set, we need to add an `IDLE` argument along with the minIdleTime + if xgco.mkStream { + args = append(args, "MKSTREAM") + } + + if xgco.entriesRead > -1 { + args = append(args, "ENTRIESREAD", utils.IntToString(xgco.entriesRead)) + } + + return args, nil +} diff --git a/go/api/stream_commands.go b/go/api/stream_commands.go index 5005c47373..c212879d54 100644 --- a/go/api/stream_commands.go +++ b/go/api/stream_commands.go @@ -148,4 +148,8 @@ type StreamCommands interface { XPending(key string, group string) (XPendingSummary, error) XPendingWithOptions(key string, group string, options *options.XPendingOptions) ([]XPendingDetail, error) + + XGroupCreate(key string, group string, id string) (string, error) + + XGroupCreateWithOptions(key string, group string, id string, opts *options.XGroupCreateOptions) (string, error) } diff --git a/go/integTest/shared_commands_test.go b/go/integTest/shared_commands_test.go index 5a2f34050c..2e941aafb4 100644 --- a/go/integTest/shared_commands_test.go +++ b/go/integTest/shared_commands_test.go @@ -5865,15 +5865,13 @@ func (suite *GlideTestSuite) TestXPendingFailures() { consumer1 := "consumer-1-" + uuid.New().String() invalidConsumer := "invalid-consumer-" + uuid.New().String() - command := []string{"XGroup", "Create", key, groupName, zeroStreamId, "MKSTREAM"} + suite.verifyOK( + client.XGroupCreateWithOptions(key, groupName, zeroStreamId, options.NewXGroupCreateOptions().SetMakeStream()), + ) + command := []string{"XGroup", "CreateConsumer", key, groupName, consumer1} resp, err := client.CustomCommand(command) assert.NoError(suite.T(), err) - assert.Equal(suite.T(), "OK", resp.(string)) - - command = []string{"XGroup", "CreateConsumer", key, groupName, consumer1} - resp, err = client.CustomCommand(command) - assert.NoError(suite.T(), err) assert.True(suite.T(), resp.(bool)) _, err = client.XAdd(key, [][]string{{"field1", "value1"}}) @@ -6017,15 +6015,13 @@ func (suite *GlideTestSuite) TestXPendingFailures() { consumer1 := "consumer-1-" + uuid.New().String() invalidConsumer := "invalid-consumer-" + uuid.New().String() - command := []string{"XGroup", "Create", key, groupName, zeroStreamId, "MKSTREAM"} + suite.verifyOK( + client.XGroupCreateWithOptions(key, groupName, zeroStreamId, options.NewXGroupCreateOptions().SetMakeStream()), + ) + command := []string{"XGroup", "CreateConsumer", key, groupName, consumer1} resp, err := client.CustomCommand(command) assert.NoError(suite.T(), err) - assert.Equal(suite.T(), "OK", resp.Value().(string)) - - command = []string{"XGroup", "CreateConsumer", key, groupName, consumer1} - resp, err = client.CustomCommand(command) - assert.NoError(suite.T(), err) assert.True(suite.T(), resp.Value().(bool)) _, err = client.XAdd(key, [][]string{{"field1", "value1"}}) @@ -6173,6 +6169,49 @@ func (suite *GlideTestSuite) TestXPendingFailures() { }) } +// TODO add XGroupDestroy tests there +func (suite *GlideTestSuite) TestXGroupCreate_XGroupDestroy() { + suite.runWithDefaultClients(func(client api.BaseClient) { + key := uuid.NewString() + group1 := uuid.NewString() + group2 := uuid.NewString() + id := "0-1" + + // Stream not created results in error + _, err := client.XGroupCreate(key, group1, id) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + + // Stream with option to create creates stream & Group + opts := options.NewXGroupCreateOptions().SetMakeStream() + suite.verifyOK(client.XGroupCreateWithOptions(key, group1, id, opts)) + + // ...and again results in BUSYGROUP error, because group names must be unique + _, err = client.XGroupCreate(key, group1, id) + assert.ErrorContains(suite.T(), err, "BUSYGROUP") + assert.IsType(suite.T(), &api.RequestError{}, err) + + // TODO add XGroupDestroy tests there + + // ENTRIESREAD option was added in valkey 7.0.0 + opts = options.NewXGroupCreateOptions().SetEntriesRead(100) + if suite.serverVersion >= "7.0.0" { + suite.verifyOK(client.XGroupCreateWithOptions(key, group2, id, opts)) + } else { + _, err = client.XGroupCreateWithOptions(key, group2, id, opts) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + } + + // key is not a stream + key = uuid.NewString() + suite.verifyOK(client.Set(key, id)) + _, err = client.XGroupCreate(key, group1, id) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + }) +} + func (suite *GlideTestSuite) TestObjectEncoding() { suite.runWithDefaultClients(func(client api.BaseClient) { // Test 1: Check object encoding for embstr From 084a68b7b3fde6065a18a2570c05c71f26b8c664 Mon Sep 17 00:00:00 2001 From: Joseph Brinkman Date: Mon, 20 Jan 2025 13:50:43 -0500 Subject: [PATCH 2/5] Go: Add stream commands XGroupCreateConsumer/XGroupDelConsumer (#2975) * go xGroupCreateConsumer and XGroupDelConsumer Signed-off-by: jbrinkman Co-authored-by: Yury-Fridlyand --- go/api/base_client.go | 70 +++++++++++++++++ go/api/stream_commands.go | 4 + go/integTest/shared_commands_test.go | 112 +++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) diff --git a/go/api/base_client.go b/go/api/base_client.go index f7313e05d6..3c52edb79a 100644 --- a/go/api/base_client.go +++ b/go/api/base_client.go @@ -2870,3 +2870,73 @@ func (client *baseClient) SortStoreWithOptions( } return handleIntOrNilResponse(result) } + +// XGroupCreateConsumer creates a consumer named `consumer` in the consumer group `group` for the +// stream stored at `key`. +// +// See [valkey.io] for details. +// +// Parameters: +// +// key - The key of the stream. +// group - The consumer group name. +// consumer - The newly created consumer. +// +// Return value: +// +// Returns `true` if the consumer is created. Otherwise, returns `false`. +// +// Example: +// +// //Creates the consumer "myconsumer" in consumer group "mygroup" +// success, err := client.xgroupCreateConsumer("mystream", "mygroup", "myconsumer") +// if err == nil && success { +// fmt.Println("Consumer created") +// } +// +// [valkey.io]: https://valkey.io/commands/xgroup-createconsumer/ +func (client *baseClient) XGroupCreateConsumer( + key string, + group string, + consumer string, +) (bool, error) { + result, err := client.executeCommand(C.XGroupCreateConsumer, []string{key, group, consumer}) + if err != nil { + return false, err + } + return handleBoolResponse(result) +} + +// XGroupDelConsumer deletes a consumer named `consumer` in the consumer group `group`. +// +// See [valkey.io] for details. +// +// Parameters: +// +// key - The key of the stream. +// group - The consumer group name. +// consumer - The consumer to delete. +// +// Returns the number of pending messages the `consumer` had before it was deleted. +// +// Example: +// +// // Deletes the consumer "myconsumer" in consumer group "mygroup" +// pendingMsgCount, err := client.XGroupDelConsumer("mystream", "mygroup", "myconsumer") +// if err != nil { +// // handle error +// } +// fmt.Printf("Consumer 'myconsumer' had %d pending messages unclaimed.\n", pendingMsgCount) +// +// [valkey.io]: https://valkey.io/commands/xgroup-delconsumer/ +func (client *baseClient) XGroupDelConsumer( + key string, + group string, + consumer string, +) (int64, error) { + result, err := client.executeCommand(C.XGroupDelConsumer, []string{key, group, consumer}) + if err != nil { + return defaultIntResponse, err + } + return handleIntResponse(result) +} diff --git a/go/api/stream_commands.go b/go/api/stream_commands.go index c212879d54..b5febb245d 100644 --- a/go/api/stream_commands.go +++ b/go/api/stream_commands.go @@ -152,4 +152,8 @@ type StreamCommands interface { XGroupCreate(key string, group string, id string) (string, error) XGroupCreateWithOptions(key string, group string, id string, opts *options.XGroupCreateOptions) (string, error) + + XGroupCreateConsumer(key string, group string, consumer string) (bool, error) + + XGroupDelConsumer(key string, group string, consumer string) (int64, error) } diff --git a/go/integTest/shared_commands_test.go b/go/integTest/shared_commands_test.go index 2e941aafb4..28421c428e 100644 --- a/go/integTest/shared_commands_test.go +++ b/go/integTest/shared_commands_test.go @@ -6708,3 +6708,115 @@ func (suite *GlideTestSuite) TestSortStoreWithOptions_ByPattern() { assert.Equal(suite.T(), resultList, sortedValues) }) } + +func (suite *GlideTestSuite) TestXGroupStreamCommands() { + suite.runWithDefaultClients(func(client api.BaseClient) { + key := uuid.New().String() + stringKey := uuid.New().String() + groupName := "group" + uuid.New().String() + zeroStreamId := "0" + consumerName := "consumer-" + uuid.New().String() + + sendWithCustomCommand( + suite, + client, + []string{"xgroup", "create", key, groupName, zeroStreamId, "MKSTREAM"}, + "Can't send XGROUP CREATE as a custom command", + ) + respBool, err := client.XGroupCreateConsumer(key, groupName, consumerName) + assert.NoError(suite.T(), err) + assert.True(suite.T(), respBool) + + // create a consumer for a group that doesn't exist should result in a NOGROUP error + _, err = client.XGroupCreateConsumer(key, "non-existent-group", consumerName) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + assert.True(suite.T(), strings.Contains(err.Error(), "NOGROUP")) + + // create consumer that already exists should return false + respBool, err = client.XGroupCreateConsumer(key, groupName, consumerName) + assert.NoError(suite.T(), err) + assert.False(suite.T(), respBool) + + // Delete a consumer that hasn't been created should return 0 + respInt64, err := client.XGroupDelConsumer(key, groupName, "non-existent-consumer") + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(0), respInt64) + + // Add two stream entries + streamId1, err := client.XAdd(key, [][]string{{"field1", "value1"}}) + assert.NoError(suite.T(), err) + streamId2, err := client.XAdd(key, [][]string{{"field2", "value2"}}) + assert.NoError(suite.T(), err) + + // read the stream for the consumer and mark messages as pending + expectedGroup := map[string]map[string][][]string{ + key: {streamId1.Value(): {{"field1", "value1"}}, streamId2.Value(): {{"field2", "value2"}}}, + } + actualGroup, err := client.XReadGroup(groupName, consumerName, map[string]string{key: ">"}) + assert.NoError(suite.T(), err) + assert.True(suite.T(), reflect.DeepEqual(expectedGroup, actualGroup), + "Expected and actual results do not match", + ) + + // delete one of the streams using XDel + respInt64, err = client.XDel(key, []string{streamId1.Value()}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(1), respInt64) + + // xreadgroup should return one empty stream and one non-empty stream + resp, err := client.XReadGroup(groupName, consumerName, map[string]string{key: zeroStreamId}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), map[string]map[string][][]string{ + key: { + streamId1.Value(): nil, + streamId2.Value(): {{"field2", "value2"}}, + }, + }, resp) + + // add a new stream entry + streamId3, err := client.XAdd(key, [][]string{{"field3", "value3"}}) + assert.NoError(suite.T(), err) + assert.NotNil(suite.T(), streamId3) + + // xack that streamid1 and streamid2 have been processed + command := []string{"XAck", key, groupName, streamId1.Value(), streamId2.Value()} + sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + + // Delete the consumer group and expect 0 pending messages + respInt64, err = client.XGroupDelConsumer(key, groupName, consumerName) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(0), respInt64) + + // TODO: Use XAck when it is added to the Go client + // xack streamid_1, and streamid_2 already received returns 0L + command = []string{"XAck", key, groupName, streamId1.Value(), streamId2.Value()} + sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + + // Consume the last message with the previously deleted consumer (creates the consumer anew) + resp, err = client.XReadGroup(groupName, consumerName, map[string]string{key: ">"}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), 1, len(resp[key])) + + // TODO: Use XAck when it is added to the Go client + // Use non existent group, so xack streamid_3 returns 0 + command = []string{"XAck", key, "non-existent-group", streamId3.Value()} + sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + + // Delete the consumer group and expect 1 pending message + respInt64, err = client.XGroupDelConsumer(key, groupName, consumerName) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(1), respInt64) + + // Set a string key, and expect an error when you try to create or delete a consumer group + _, err = client.Set(stringKey, "test") + assert.NoError(suite.T(), err) + _, err = client.XGroupCreateConsumer(stringKey, groupName, consumerName) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + + _, err = client.XGroupDelConsumer(stringKey, groupName, consumerName) + assert.Error(suite.T(), err) + assert.IsType(suite.T(), &api.RequestError{}, err) + }) +} From b95fbbd078a44d7d40e2643335691456ad6844d5 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 20 Jan 2025 11:23:53 -0800 Subject: [PATCH 3/5] Go: Fix return types, part 6 (#2965) * Fix return types. Signed-off-by: Yury-Fridlyand --- go/api/base_client.go | 80 +++--- go/api/generic_base_commands.go | 20 +- go/api/hash_commands.go | 17 +- go/api/list_commands.go | 56 ++--- go/api/response_handlers.go | 50 ++-- go/api/sorted_set_commands.go | 2 +- go/integTest/shared_commands_test.go | 355 ++++++--------------------- 7 files changed, 183 insertions(+), 397 deletions(-) diff --git a/go/api/base_client.go b/go/api/base_client.go index 3c52edb79a..9d6a353c1e 100644 --- a/go/api/base_client.go +++ b/go/api/base_client.go @@ -258,7 +258,7 @@ func (client *baseClient) MGet(keys []string) ([]Result[string], error) { return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } func (client *baseClient) Incr(key string) (int64, error) { @@ -391,7 +391,7 @@ func (client *baseClient) HMGet(key string, fields []string) ([]Result[string], return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } func (client *baseClient) HSet(key string, values map[string]string) (int64, error) { @@ -430,7 +430,7 @@ func (client *baseClient) HLen(key string) (int64, error) { return handleIntResponse(result) } -func (client *baseClient) HVals(key string) ([]Result[string], error) { +func (client *baseClient) HVals(key string) ([]string, error) { result, err := client.executeCommand(C.HVals, []string{key}) if err != nil { return nil, err @@ -448,7 +448,7 @@ func (client *baseClient) HExists(key string, field string) (bool, error) { return handleBoolResponse(result) } -func (client *baseClient) HKeys(key string) ([]Result[string], error) { +func (client *baseClient) HKeys(key string) ([]string, error) { result, err := client.executeCommand(C.HKeys, []string{key}) if err != nil { return nil, err @@ -583,13 +583,13 @@ func (client *baseClient) LPop(key string) (Result[string], error) { return handleStringOrNilResponse(result) } -func (client *baseClient) LPopCount(key string, count int64) ([]Result[string], error) { +func (client *baseClient) LPopCount(key string, count int64) ([]string, error) { result, err := client.executeCommand(C.LPop, []string{key, utils.IntToString(count)}) if err != nil { return nil, err } - return handleStringArrayOrNullResponse(result) + return handleStringArrayOrNilResponse(result) } func (client *baseClient) LPos(key string, element string) (Result[int64], error) { @@ -610,7 +610,7 @@ func (client *baseClient) LPosWithOptions(key string, element string, options *L return handleIntOrNilResponse(result) } -func (client *baseClient) LPosCount(key string, element string, count int64) ([]Result[int64], error) { +func (client *baseClient) LPosCount(key string, element string, count int64) ([]int64, error) { result, err := client.executeCommand(C.LPos, []string{key, element, CountKeyword, utils.IntToString(count)}) if err != nil { return nil, err @@ -624,7 +624,7 @@ func (client *baseClient) LPosCountWithOptions( element string, count int64, options *LPosOptions, -) ([]Result[int64], error) { +) ([]int64, error) { result, err := client.executeCommand( C.LPos, append([]string{key, element, CountKeyword, utils.IntToString(count)}, options.toArgs()...), @@ -904,7 +904,7 @@ func (client *baseClient) SMove(source string, destination string, member string return handleBoolResponse(result) } -func (client *baseClient) LRange(key string, start int64, end int64) ([]Result[string], error) { +func (client *baseClient) LRange(key string, start int64, end int64) ([]string, error) { result, err := client.executeCommand(C.LRange, []string{key, utils.IntToString(start), utils.IntToString(end)}) if err != nil { return nil, err @@ -958,13 +958,13 @@ func (client *baseClient) RPop(key string) (Result[string], error) { return handleStringOrNilResponse(result) } -func (client *baseClient) RPopCount(key string, count int64) ([]Result[string], error) { +func (client *baseClient) RPopCount(key string, count int64) ([]string, error) { result, err := client.executeCommand(C.RPop, []string{key, utils.IntToString(count)}) if err != nil { return nil, err } - return handleStringArrayOrNullResponse(result) + return handleStringArrayOrNilResponse(result) } func (client *baseClient) LInsert( @@ -989,22 +989,22 @@ func (client *baseClient) LInsert( return handleIntResponse(result) } -func (client *baseClient) BLPop(keys []string, timeoutSecs float64) ([]Result[string], error) { +func (client *baseClient) BLPop(keys []string, timeoutSecs float64) ([]string, error) { result, err := client.executeCommand(C.BLPop, append(keys, utils.FloatToString(timeoutSecs))) if err != nil { return nil, err } - return handleStringArrayOrNullResponse(result) + return handleStringArrayOrNilResponse(result) } -func (client *baseClient) BRPop(keys []string, timeoutSecs float64) ([]Result[string], error) { +func (client *baseClient) BRPop(keys []string, timeoutSecs float64) ([]string, error) { result, err := client.executeCommand(C.BRPop, append(keys, utils.FloatToString(timeoutSecs))) if err != nil { return nil, err } - return handleStringArrayOrNullResponse(result) + return handleStringArrayOrNilResponse(result) } func (client *baseClient) RPushX(key string, elements []string) (int64, error) { @@ -1394,12 +1394,12 @@ func (client *baseClient) Unlink(keys []string) (int64, error) { return handleIntResponse(result) } -func (client *baseClient) Type(key string) (Result[string], error) { +func (client *baseClient) Type(key string) (string, error) { result, err := client.executeCommand(C.Type, []string{key}) if err != nil { - return CreateNilStringResult(), err + return defaultStringResponse, err } - return handleStringOrNilResponse(result) + return handleStringResponse(result) } func (client *baseClient) Touch(keys []string) (int64, error) { @@ -1411,12 +1411,12 @@ func (client *baseClient) Touch(keys []string) (int64, error) { return handleIntResponse(result) } -func (client *baseClient) Rename(key string, newKey string) (Result[string], error) { +func (client *baseClient) Rename(key string, newKey string) (string, error) { result, err := client.executeCommand(C.Rename, []string{key, newKey}) if err != nil { - return CreateNilStringResult(), err + return defaultStringResponse, err } - return handleStringOrNilResponse(result) + return handleStringResponse(result) } func (client *baseClient) Renamenx(key string, newKey string) (bool, error) { @@ -1838,16 +1838,15 @@ func (client *baseClient) BZPopMin(keys []string, timeoutSecs float64) (Result[K // result, err := client.ZRange("my_sorted_set", options.NewRangeByIndexQuery(0, -1)) // // // Retrieve members within a score range in descending order -// -// query := options.NewRangeByScoreQuery(options.NewScoreBoundary(3, false), -// options.NewInfiniteScoreBoundary(options.NegativeInfinity)). -// -// .SetReverse() +// query := options.NewRangeByScoreQuery( +// options.NewScoreBoundary(3, false), +// options.NewInfiniteScoreBoundary(options.NegativeInfinity)). +// SetReverse() // result, err := client.ZRange("my_sorted_set", query) // // `result` contains members which have scores within the range of negative infinity to 3, in descending order // // [valkey.io]: https://valkey.io/commands/zrange/ -func (client *baseClient) ZRange(key string, rangeQuery options.ZRangeQuery) ([]Result[string], error) { +func (client *baseClient) ZRange(key string, rangeQuery options.ZRangeQuery) ([]string, error) { args := make([]string, 0, 10) args = append(args, key) args = append(args, rangeQuery.ToArgs()...) @@ -1882,10 +1881,9 @@ func (client *baseClient) ZRange(key string, rangeQuery options.ZRangeQuery) ([] // result, err := client.ZRangeWithScores("my_sorted_set", options.NewRangeByIndexQuery(0, -1)) // // // Retrieve members within a score range in descending order -// -// query := options.NewRangeByScoreQuery(options.NewScoreBoundary(3, false), -// options.NewInfiniteScoreBoundary(options.NegativeInfinity)). -// +// query := options.NewRangeByScoreQuery( +// options.NewScoreBoundary(3, false), +// options.NewInfiniteScoreBoundary(options.NegativeInfinity)). // SetReverse() // result, err := client.ZRangeWithScores("my_sorted_set", query) // // `result` contains members with scores within the range of negative infinity to 3, in descending order @@ -2821,7 +2819,7 @@ func (client *baseClient) Sort(key string) ([]Result[string], error) { if err != nil { return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } func (client *baseClient) SortWithOptions(key string, options *options.SortOptions) ([]Result[string], error) { @@ -2830,7 +2828,7 @@ func (client *baseClient) SortWithOptions(key string, options *options.SortOptio if err != nil { return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } func (client *baseClient) SortReadOnly(key string) ([]Result[string], error) { @@ -2838,7 +2836,7 @@ func (client *baseClient) SortReadOnly(key string) ([]Result[string], error) { if err != nil { return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } func (client *baseClient) SortReadOnlyWithOptions(key string, options *options.SortOptions) ([]Result[string], error) { @@ -2847,28 +2845,28 @@ func (client *baseClient) SortReadOnlyWithOptions(key string, options *options.S if err != nil { return nil, err } - return handleStringArrayResponse(result) + return handleStringOrNilArrayResponse(result) } -func (client *baseClient) SortStore(key string, destination string) (Result[int64], error) { +func (client *baseClient) SortStore(key string, destination string) (int64, error) { result, err := client.executeCommand(C.Sort, []string{key, "STORE", destination}) if err != nil { - return CreateNilInt64Result(), err + return defaultIntResponse, err } - return handleIntOrNilResponse(result) + return handleIntResponse(result) } func (client *baseClient) SortStoreWithOptions( key string, destination string, options *options.SortOptions, -) (Result[int64], error) { +) (int64, error) { optionArgs := options.ToArgs() result, err := client.executeCommand(C.Sort, append([]string{key, "STORE", destination}, optionArgs...)) if err != nil { - return CreateNilInt64Result(), err + return defaultIntResponse, err } - return handleIntOrNilResponse(result) + return handleIntResponse(result) } // XGroupCreateConsumer creates a consumer named `consumer` in the consumer group `group` for the diff --git a/go/api/generic_base_commands.go b/go/api/generic_base_commands.go index 345bff2169..005d96fcf4 100644 --- a/go/api/generic_base_commands.go +++ b/go/api/generic_base_commands.go @@ -369,17 +369,17 @@ type GenericBaseCommands interface { // key - string // // Return value: - // If the key exists, the type of the stored value is returned. Otherwise, a none" string is returned. + // If the key exists, the type of the stored value is returned. Otherwise, a "none" string is returned. // // Example: // result, err := client.Type([]string{"key"}) // if err != nil { // // handle error // } - // fmt.Println(result.Value()) // Output: string + // fmt.Println(result) // Output: string // // [valkey.io]: Https://valkey.io/commands/type/ - Type(key string) (Result[string], error) + Type(key string) (string, error) // Renames key to new key. // If new Key already exists it is overwritten. @@ -399,10 +399,10 @@ type GenericBaseCommands interface { // if err != nil { // // handle error // } - // fmt.Println(result.Value()) // Output: OK + // fmt.Println(result) // Output: OK // // [valkey.io]: https://valkey.io/commands/rename/ - Rename(key string, newKey string) (Result[string], error) + Rename(key string, newKey string) (string, error) // Renames key to newkey if newKey does not yet exist. // @@ -613,11 +613,10 @@ type GenericBaseCommands interface { // Example: // // result, err := client.SortStore("key","destkey") - // result.Value(): 1 - // result.IsNil(): false + // result: 1 // // [valkey.io]: https://valkey.io/commands/sort/ - SortStore(key string, destination string) (Result[int64], error) + SortStore(key string, destination string) (int64, error) // Sorts the elements in the list, set, or sorted set at key and stores the result in // destination. The sort command can be used to sort elements based on @@ -648,11 +647,10 @@ type GenericBaseCommands interface { // // options := api.NewSortOptions().SetByPattern("weight_*").SetIsAlpha(false).AddGetPattern("object_*").AddGetPattern("#") // result, err := client.SortStore("key","destkey",options) - // result.Value(): 1 - // result.IsNil(): false + // result: 1 // // [valkey.io]: https://valkey.io/commands/sort/ - SortStoreWithOptions(key string, destination string, sortOptions *options.SortOptions) (Result[int64], error) + SortStoreWithOptions(key string, destination string, sortOptions *options.SortOptions) (int64, error) // Sorts the elements in the list, set, or sorted set at key and returns the result. // The sortReadOnly command can be used to sort elements based on different criteria and apply diff --git a/go/api/hash_commands.go b/go/api/hash_commands.go index 41e006cc04..ba2f248e8f 100644 --- a/go/api/hash_commands.go +++ b/go/api/hash_commands.go @@ -172,17 +172,14 @@ type HashCommands interface { // key - The key of the hash. // // Return value: - // A slice of Result[string]s containing all the values in the hash, or an empty slice when key does not exist. + // A slice containing all the values in the hash, or an empty slice when key does not exist. // // For example: // values, err := client.HVals("myHash") - // // value1 equals api.CreateStringResult("value1") - // // value2 equals api.CreateStringResult("value2") - // // value3 equals api.CreateStringResult("value3") - // // values equals []api.Result[string]{value1, value2, value3} + // values: []string{"value1", "value2", "value3"} // // [valkey.io]: https://valkey.io/commands/hvals/ - HVals(key string) ([]Result[string], error) + HVals(key string) ([]string, error) // HExists returns if field is an existing field in the hash stored at key. // @@ -215,16 +212,14 @@ type HashCommands interface { // key - The key of the hash. // // Return value: - // A slice of Result[string]s containing all the field names in the hash, or an empty slice when key does not exist. + // A slice containing all the field names in the hash, or an empty slice when key does not exist. // // For example: // names, err := client.HKeys("my_hash") - // // field1 equals api.CreateStringResult("field_1") - // // field2 equals api.CreateStringResult("field_2") - // // names equals []api.Result[string]{field1, field2} + // names: []string{"field1", "field2"} // // [valkey.io]: https://valkey.io/commands/hkeys/ - HKeys(key string) ([]Result[string], error) + HKeys(key string) ([]string, error) // HStrLen returns the string length of the value associated with field in the hash stored at key. // If the key or the field do not exist, 0 is returned. diff --git a/go/api/list_commands.go b/go/api/list_commands.go index 0c64012e6c..d1c1970dfd 100644 --- a/go/api/list_commands.go +++ b/go/api/list_commands.go @@ -71,7 +71,7 @@ type ListCommands interface { // result: nil // // [valkey.io]: https://valkey.io/commands/lpop/ - LPopCount(key string, count int64) ([]Result[string], error) + LPopCount(key string, count int64) ([]string, error) // Returns the index of the first occurrence of element inside the list specified by key. If no match is found, // [api.CreateNilInt64Result()] is returned. @@ -132,13 +132,12 @@ type ListCommands interface { // An array that holds the indices of the matching elements within the list. // // For example: - // result, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) + // _, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) // result, err := client.LPosCount("my_list", "e", int64(3)) - // result: []api.Result[int64]{api.CreateInt64Result(4), api.CreateInt64Result(5), api.CreateInt64Result(6)} - // + // result: []int64{ 4, 5, 6 } // // [valkey.io]: https://valkey.io/commands/lpos/ - LPosCount(key string, element string, count int64) ([]Result[int64], error) + LPosCount(key string, element string, count int64) ([]int64, error) // Returns an array of indices of matching elements within a list based on the given options. If no match is found, an // empty array is returned. @@ -155,21 +154,21 @@ type ListCommands interface { // An array that holds the indices of the matching elements within the list. // // For example: - // 1. result, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) + // 1. _, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) // result, err := client.LPosWithOptions("my_list", "e", int64(1), api.NewLPosOptionsBuilder().SetRank(2)) - // result: []api.Result[int64]{api.CreateInt64Result(5)} - // 2. result, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) + // result: []int64{ 5 } + // 2. _, err := client.RPush("my_list", []string{"a", "b", "c", "d", "e", "e", "e"}) // result, err := client.LPosWithOptions( // "my_list", // "e", // int64(3), // api.NewLPosOptionsBuilder().SetRank(2).SetMaxLen(1000), // ) - // result: []api.Result[int64]{api.CreateInt64Result(5), api.CreateInt64Result(6)} + // result: []int64{ 5, 6 } // // // [valkey.io]: https://valkey.io/commands/lpos/ - LPosCountWithOptions(key string, element string, count int64, options *LPosOptions) ([]Result[int64], error) + LPosCountWithOptions(key string, element string, count int64, options *LPosOptions) ([]int64, error) // Inserts all the specified values at the tail of the list stored at key. // elements are inserted one after the other to the tail of the list, from the leftmost element to the rightmost element. @@ -211,15 +210,14 @@ type ListCommands interface { // // For example: // 1. result, err := client.LRange("my_list", 0, 2) - // result: []api.Result[string]{api.CreateStringResult("value1"), api.CreateStringResult("value2"), - // api.CreateStringResult("value3")} + // result: []string{ "value1", "value2", "value3" } // 2. result, err := client.LRange("my_list", -2, -1) - // result: []api.Result[string]{api.CreateStringResult("value2"), api.CreateStringResult("value3")} + // result: []string{ "value2", "value3" } // 3. result, err := client.LRange("non_existent_key", 0, 2) - // result: []api.Result[string]{} + // result: []string{} // // [valkey.io]: https://valkey.io/commands/lrange/ - LRange(key string, start int64, end int64) ([]Result[string], error) + LRange(key string, start int64, end int64) ([]string, error) // Returns the element at index from the list stored at key. // The index is zero-based, so 0 means the first element, 1 the second element and so on. Negative indices can be used to @@ -357,7 +355,7 @@ type ListCommands interface { // result: nil // // [valkey.io]: https://valkey.io/commands/rpop/ - RPopCount(key string, count int64) ([]Result[string], error) + RPopCount(key string, count int64) ([]string, error) // Inserts element in the list at key either before or after the pivot. // @@ -397,17 +395,17 @@ type ListCommands interface { // timeoutSecs - The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. // // Return value: - // A two-element array of Result[string] containing the key from which the element was popped and the value of the popped + // A two-element array containing the key from which the element was popped and the value of the popped // element, formatted as [key, value]. - // If no element could be popped and the timeout expired, returns nil. + // If no element could be popped and the timeout expired, returns `nil`. // // For example: // result, err := client.BLPop("list1", "list2", 0.5) - // result: []api.Result[string]{api.CreateStringResult("list1"), api.CreateStringResult("element")} + // result: []string{ "list1", "element" } // // [valkey.io]: https://valkey.io/commands/blpop/ // [Blocking Commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands - BLPop(keys []string, timeoutSecs float64) ([]Result[string], error) + BLPop(keys []string, timeoutSecs float64) ([]string, error) // Pops an element from the tail of the first list that is non-empty, with the given keys being checked in the order that // they are given. @@ -424,17 +422,17 @@ type ListCommands interface { // timeoutSecs - The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. // // Return value: - // A two-element array of Result[string] containing the key from which the element was popped and the value of the popped + // A two-element array containing the key from which the element was popped and the value of the popped // element, formatted as [key, value]. - // If no element could be popped and the timeoutSecs expired, returns nil. + // If no element could be popped and the timeoutSecs expired, returns `nil`. // // For example: // result, err := client.BRPop("list1", "list2", 0.5) - // result: []api.Result[string]{api.CreateStringResult("list1"), api.CreateStringResult("element")} + // result: []string{ "list1", "element" } // // [valkey.io]: https://valkey.io/commands/brpop/ // [Blocking Commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands - BRPop(keys []string, timeoutSecs float64) ([]Result[string], error) + BRPop(keys []string, timeoutSecs float64) ([]string, error) // Inserts all the specified values at the tail of the list stored at key, only if key exists and holds a list. If key is // not a list, this performs no operation. @@ -632,9 +630,8 @@ type ListCommands interface { // result.Value(): "one" // updatedList1, err: client.LRange("my_list1", int64(0), int64(-1)) // updatedList2, err: client.LRange("my_list2", int64(0), int64(-1)) - // updatedList1: []api.Result[string]{api.CreateStringResult("two")} - // updatedList2: []api.Result[string]{api.CreateStringResult("one"), api.CreateStringResult("three"), - // api.CreateStringResult("four")} + // updatedList1: []string{ "two" } + // updatedList2: []string{ "one", "three", "four" } // // [valkey.io]: https://valkey.io/commands/lmove/ LMove(source string, destination string, whereFrom ListDirection, whereTo ListDirection) (Result[string], error) @@ -671,9 +668,8 @@ type ListCommands interface { // result.Value(): "one" // updatedList1, err: client.LRange("my_list1", int64(0), int64(-1)) // updatedList2, err: client.LRange("my_list2", int64(0), int64(-1)) - // updatedList1: []api.Result[string]{api.CreateStringResult("two")} - // updatedList2: []api.Result[string]{api.CreateStringResult("one"), api.CreateStringResult("three"), - // api.CreateStringResult("four")} + // updatedList1: []string{ "two" } + // updatedList2: []string{ "one", "three", "four" } // // [valkey.io]: https://valkey.io/commands/blmove/ // [Blocking Commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands diff --git a/go/api/response_handlers.go b/go/api/response_handlers.go index 48a7dc7509..98ba2713d2 100644 --- a/go/api/response_handlers.go +++ b/go/api/response_handlers.go @@ -168,7 +168,8 @@ func handleStringOrNilResponse(response *C.struct_CommandResponse) (Result[strin return convertCharArrayToString(response, true) } -func convertStringArray(response *C.struct_CommandResponse) ([]Result[string], error) { +// Fix after merging with https://github.com/valkey-io/valkey-glide/pull/2964 +func convertStringOrNilArray(response *C.struct_CommandResponse) ([]Result[string], error) { typeErr := checkResponseType(response, C.Array, false) if typeErr != nil { return nil, typeErr @@ -185,35 +186,46 @@ func convertStringArray(response *C.struct_CommandResponse) ([]Result[string], e return slice, nil } -func handleStringArrayResponse(response *C.struct_CommandResponse) ([]Result[string], error) { - defer C.free_command_response(response) - - return convertStringArray(response) -} - -func handleStringArrayOrNullResponse(response *C.struct_CommandResponse) ([]Result[string], error) { - defer C.free_command_response(response) - - typeErr := checkResponseType(response, C.Array, true) +// array could be nillable, but strings - aren't +func convertStringArray(response *C.struct_CommandResponse, isNilable bool) ([]string, error) { + typeErr := checkResponseType(response, C.Array, isNilable) if typeErr != nil { return nil, typeErr } - if response.response_type == C.Null { + if isNilable && response.array_value == nil { return nil, nil } - slice := make([]Result[string], 0, response.array_value_len) + slice := make([]string, 0, response.array_value_len) for _, v := range unsafe.Slice(response.array_value, response.array_value_len) { - res, err := convertCharArrayToString(&v, true) + res, err := convertCharArrayToString(&v, false) if err != nil { return nil, err } - slice = append(slice, res) + slice = append(slice, res.Value()) } return slice, nil } +func handleStringOrNilArrayResponse(response *C.struct_CommandResponse) ([]Result[string], error) { + defer C.free_command_response(response) + + return convertStringOrNilArray(response) +} + +func handleStringArrayResponse(response *C.struct_CommandResponse) ([]string, error) { + defer C.free_command_response(response) + + return convertStringArray(response, false) +} + +func handleStringArrayOrNilResponse(response *C.struct_CommandResponse) ([]string, error) { + defer C.free_command_response(response) + + return convertStringArray(response, true) +} + func handleIntResponse(response *C.struct_CommandResponse) (int64, error) { defer C.free_command_response(response) @@ -240,7 +252,7 @@ func handleIntOrNilResponse(response *C.struct_CommandResponse) (Result[int64], return CreateInt64Result(int64(response.int_value)), nil } -func handleIntArrayResponse(response *C.struct_CommandResponse) ([]Result[int64], error) { +func handleIntArrayResponse(response *C.struct_CommandResponse) ([]int64, error) { defer C.free_command_response(response) typeErr := checkResponseType(response, C.Array, false) @@ -248,13 +260,13 @@ func handleIntArrayResponse(response *C.struct_CommandResponse) ([]Result[int64] return nil, typeErr } - slice := make([]Result[int64], 0, response.array_value_len) + slice := make([]int64, 0, response.array_value_len) for _, v := range unsafe.Slice(response.array_value, response.array_value_len) { err := checkResponseType(&v, C.Int, false) if err != nil { return nil, err } - slice = append(slice, CreateInt64Result(int64(v.int_value))) + slice = append(slice, int64(v.int_value)) } return slice, nil } @@ -407,7 +419,7 @@ func handleStringToStringArrayMapOrNullResponse( if err != nil { return nil, err } - value, err := convertStringArray(v.map_value) + value, err := convertStringOrNilArray(v.map_value) if err != nil { return nil, err } diff --git a/go/api/sorted_set_commands.go b/go/api/sorted_set_commands.go index 47b505a558..4010d62d05 100644 --- a/go/api/sorted_set_commands.go +++ b/go/api/sorted_set_commands.go @@ -264,7 +264,7 @@ type SortedSetCommands interface { // [blocking commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands BZPopMin(keys []string, timeoutSecs float64) (Result[KeyWithMemberAndScore], error) - ZRange(key string, rangeQuery options.ZRangeQuery) ([]Result[string], error) + ZRange(key string, rangeQuery options.ZRangeQuery) ([]string, error) ZRangeWithScores(key string, rangeQuery options.ZRangeQueryWithScores) (map[Result[string]]Result[float64], error) diff --git a/go/integTest/shared_commands_test.go b/go/integTest/shared_commands_test.go index 28421c428e..4f83224e2f 100644 --- a/go/integTest/shared_commands_test.go +++ b/go/integTest/shared_commands_test.go @@ -922,11 +922,8 @@ func (suite *GlideTestSuite) TestHVals_WithExistingKey() { assert.Equal(suite.T(), int64(2), res1) res2, err := client.HVals(key) - value1 := api.CreateStringResult("value1") - value2 := api.CreateStringResult("value2") assert.Nil(suite.T(), err) - assert.Contains(suite.T(), res2, value1) - assert.Contains(suite.T(), res2, value2) + assert.ElementsMatch(suite.T(), []string{"value1", "value2"}, res2) }) } @@ -936,7 +933,7 @@ func (suite *GlideTestSuite) TestHVals_WithNotExistingKey() { res, err := client.HVals(key) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res) + assert.Empty(suite.T(), res) }) } @@ -990,11 +987,8 @@ func (suite *GlideTestSuite) TestHKeys_WithExistingKey() { assert.Equal(suite.T(), int64(2), res1) res2, err := client.HKeys(key) - field1 := api.CreateStringResult("field1") - field2 := api.CreateStringResult("field2") assert.Nil(suite.T(), err) - assert.Contains(suite.T(), res2, field1) - assert.Contains(suite.T(), res2, field2) + assert.ElementsMatch(suite.T(), []string{"field1", "field2"}, res2) }) } @@ -1004,7 +998,7 @@ func (suite *GlideTestSuite) TestHKeys_WithNotExistingKey() { res, err := client.HKeys(key) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res) + assert.Empty(suite.T(), res) }) } @@ -1295,10 +1289,9 @@ func (suite *GlideTestSuite) TestLPushLPop_WithExistingKey() { assert.Nil(suite.T(), err) assert.Equal(suite.T(), "value1", res2.Value()) - resultList := []api.Result[string]{api.CreateStringResult("value2"), api.CreateStringResult("value3")} res3, err := client.LPopCount(key, 2) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, res3) + assert.Equal(suite.T(), []string{"value2", "value3"}, res3) }) } @@ -1312,7 +1305,7 @@ func (suite *GlideTestSuite) TestLPop_nonExistingKey() { res2, err := client.LPopCount(key, 2) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res2) + assert.Nil(suite.T(), res2) }) } @@ -1327,7 +1320,7 @@ func (suite *GlideTestSuite) TestLPushLPop_typeError() { assert.IsType(suite.T(), &api.RequestError{}, err) res2, err := client.LPopCount(key, 2) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res2) + assert.Nil(suite.T(), res2) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -1412,33 +1405,29 @@ func (suite *GlideTestSuite) TestLPosCount() { assert.Nil(suite.T(), err) res2, err := client.LPosCount(key, "a", int64(2)) - assert.Equal(suite.T(), []api.Result[int64]{api.CreateInt64Result(0), api.CreateInt64Result(1)}, res2) + assert.Equal(suite.T(), []int64{0, 1}, res2) assert.Nil(suite.T(), err) res3, err := client.LPosCount(key, "a", int64(0)) - assert.Equal( - suite.T(), - []api.Result[int64]{api.CreateInt64Result(0), api.CreateInt64Result(1), api.CreateInt64Result(4)}, - res3, - ) + assert.Equal(suite.T(), []int64{0, 1, 4}, res3) assert.Nil(suite.T(), err) // invalid count value res4, err := client.LPosCount(key, "a", int64(-1)) - assert.Equal(suite.T(), ([]api.Result[int64])(nil), res4) + assert.Nil(suite.T(), res4) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) // non-existent key res5, err := client.LPosCount("non_existent_key", "a", int64(1)) - assert.Equal(suite.T(), []api.Result[int64]{}, res5) + assert.Empty(suite.T(), res5) assert.Nil(suite.T(), err) // wrong key data type keyString := uuid.NewString() suite.verifyOK(client.Set(keyString, "value")) res6, err := client.LPosCount(keyString, "a", int64(1)) - assert.Equal(suite.T(), ([]api.Result[int64])(nil), res6) + assert.Nil(suite.T(), res6) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -1453,24 +1442,16 @@ func (suite *GlideTestSuite) TestLPosCount_withOptions() { assert.Nil(suite.T(), err) res2, err := client.LPosCountWithOptions(key, "a", int64(0), api.NewLPosOptionsBuilder().SetRank(1)) - assert.Equal( - suite.T(), - []api.Result[int64]{api.CreateInt64Result(0), api.CreateInt64Result(1), api.CreateInt64Result(4)}, - res2, - ) + assert.Equal(suite.T(), []int64{0, 1, 4}, res2) assert.Nil(suite.T(), err) res3, err := client.LPosCountWithOptions(key, "a", int64(0), api.NewLPosOptionsBuilder().SetRank(2)) - assert.Equal(suite.T(), []api.Result[int64]{api.CreateInt64Result(1), api.CreateInt64Result(4)}, res3) + assert.Equal(suite.T(), []int64{1, 4}, res3) assert.Nil(suite.T(), err) // reverse traversal res4, err := client.LPosCountWithOptions(key, "a", int64(0), api.NewLPosOptionsBuilder().SetRank(-1)) - assert.Equal( - suite.T(), - []api.Result[int64]{api.CreateInt64Result(4), api.CreateInt64Result(1), api.CreateInt64Result(0)}, - res4, - ) + assert.Equal(suite.T(), []int64{4, 1, 0}, res4) assert.Nil(suite.T(), err) }) } @@ -2423,25 +2404,19 @@ func (suite *GlideTestSuite) TestLRange() { assert.Nil(suite.T(), err) assert.Equal(suite.T(), int64(4), res1) - resultList := []api.Result[string]{ - api.CreateStringResult("value1"), - api.CreateStringResult("value2"), - api.CreateStringResult("value3"), - api.CreateStringResult("value4"), - } res2, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, res2) + assert.Equal(suite.T(), []string{"value1", "value2", "value3", "value4"}, res2) res3, err := client.LRange("non_existing_key", int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res3) + assert.Empty(suite.T(), res3) key2 := uuid.NewString() suite.verifyOK(client.Set(key2, "value")) res4, err := client.LRange(key2, int64(0), int64(1)) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res4) + assert.Nil(suite.T(), res4) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -2493,13 +2468,13 @@ func (suite *GlideTestSuite) TestLTrim() { res2, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult("value1"), api.CreateStringResult("value2")}, res2) + assert.Equal(suite.T(), []string{"value1", "value2"}, res2) suite.verifyOK(client.LTrim(key, int64(4), int64(2))) res3, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res3) + assert.Empty(suite.T(), res3) key2 := uuid.NewString() suite.verifyOK(client.Set(key2, "value")) @@ -2552,29 +2527,21 @@ func (suite *GlideTestSuite) TestLRem() { assert.Equal(suite.T(), int64(2), res2) res3, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("value2"), - api.CreateStringResult("value2"), - api.CreateStringResult("value1"), - }, - res3, - ) + assert.Equal(suite.T(), []string{"value2", "value2", "value1"}, res3) res4, err := client.LRem(key, -1, "value2") assert.Nil(suite.T(), err) assert.Equal(suite.T(), int64(1), res4) res5, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult("value2"), api.CreateStringResult("value1")}, res5) + assert.Equal(suite.T(), []string{"value2", "value1"}, res5) res6, err := client.LRem(key, 0, "value2") assert.Nil(suite.T(), err) assert.Equal(suite.T(), int64(1), res6) res7, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult("value1")}, res7) + assert.Equal(suite.T(), []string{"value1"}, res7) res8, err := client.LRem("non_existing_key", 0, "value") assert.Nil(suite.T(), err) @@ -2598,14 +2565,14 @@ func (suite *GlideTestSuite) TestRPopAndRPopCount() { res3, err := client.RPopCount(key, int64(2)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult("value3"), api.CreateStringResult("value2")}, res3) + assert.Equal(suite.T(), []string{"value3", "value2"}, res3) res4, err := client.RPop("non_existing_key") assert.Nil(suite.T(), err) assert.Equal(suite.T(), api.CreateNilStringResult(), res4) res5, err := client.RPopCount("non_existing_key", int64(2)) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res5) + assert.Nil(suite.T(), res5) assert.Nil(suite.T(), err) key2 := uuid.NewString() @@ -2617,7 +2584,7 @@ func (suite *GlideTestSuite) TestRPopAndRPopCount() { assert.IsType(suite.T(), &api.RequestError{}, err) res7, err := client.RPopCount(key2, int64(2)) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res7) + assert.Nil(suite.T(), res7) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -2642,18 +2609,7 @@ func (suite *GlideTestSuite) TestLInsert() { res4, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("value1"), - api.CreateStringResult("value1.5"), - api.CreateStringResult("value2"), - api.CreateStringResult("value3"), - api.CreateStringResult("value3.5"), - api.CreateStringResult("value4"), - }, - res4, - ) + assert.Equal(suite.T(), []string{"value1", "value1.5", "value2", "value3", "value3.5", "value4"}, res4) res5, err := client.LInsert("non_existing_key", api.Before, "pivot", "elem") assert.Nil(suite.T(), err) @@ -2684,17 +2640,17 @@ func (suite *GlideTestSuite) TestBLPop() { res2, err := client.BLPop([]string{listKey1, listKey2}, float64(0.5)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult(listKey1), api.CreateStringResult("value2")}, res2) + assert.Equal(suite.T(), []string{listKey1, "value2"}, res2) res3, err := client.BLPop([]string{listKey2}, float64(1.0)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res3) + assert.Nil(suite.T(), res3) key := uuid.NewString() suite.verifyOK(client.Set(key, "value")) res4, err := client.BLPop([]string{key}, float64(1.0)) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res4) + assert.Nil(suite.T(), res4) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -2711,17 +2667,17 @@ func (suite *GlideTestSuite) TestBRPop() { res2, err := client.BRPop([]string{listKey1, listKey2}, float64(0.5)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{api.CreateStringResult(listKey1), api.CreateStringResult("value1")}, res2) + assert.Equal(suite.T(), []string{listKey1, "value1"}, res2) res3, err := client.BRPop([]string{listKey2}, float64(1.0)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res3) + assert.Nil(suite.T(), res3) key := uuid.NewString() suite.verifyOK(client.Set(key, "value")) res4, err := client.BRPop([]string{key}, float64(1.0)) - assert.Equal(suite.T(), ([]api.Result[string])(nil), res4) + assert.Nil(suite.T(), res4) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -2743,16 +2699,7 @@ func (suite *GlideTestSuite) TestRPushX() { res3, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("value1"), - api.CreateStringResult("value2"), - api.CreateStringResult("value3"), - api.CreateStringResult("value4"), - }, - res3, - ) + assert.Equal(suite.T(), []string{"value1", "value2", "value3", "value4"}, res3) res4, err := client.RPushX(key2, []string{"value1"}) assert.Nil(suite.T(), err) @@ -2760,7 +2707,7 @@ func (suite *GlideTestSuite) TestRPushX() { res5, err := client.LRange(key2, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res5) + assert.Empty(suite.T(), res5) suite.verifyOK(client.Set(key3, "value")) @@ -2792,16 +2739,7 @@ func (suite *GlideTestSuite) TestLPushX() { res3, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("value4"), - api.CreateStringResult("value3"), - api.CreateStringResult("value2"), - api.CreateStringResult("value1"), - }, - res3, - ) + assert.Equal(suite.T(), []string{"value4", "value3", "value2", "value1"}, res3) res4, err := client.LPushX(key2, []string{"value1"}) assert.Nil(suite.T(), err) @@ -2809,7 +2747,7 @@ func (suite *GlideTestSuite) TestLPushX() { res5, err := client.LRange(key2, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), []api.Result[string]{}, res5) + assert.Empty(suite.T(), res5) suite.verifyOK(client.Set(key3, "value")) @@ -2953,31 +2891,13 @@ func (suite *GlideTestSuite) TestLSet() { res5, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("zero"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - api.CreateStringResult("four"), - }, - res5, - ) + assert.Equal(suite.T(), []string{"zero", "two", "three", "four"}, res5) suite.verifyOK(client.LSet(key, int64(-1), "zero")) res7, err := client.LRange(key, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("zero"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - api.CreateStringResult("zero"), - }, - res7, - ) + assert.Equal(suite.T(), []string{"zero", "two", "three", "zero"}, res7) }) } @@ -3006,15 +2926,7 @@ func (suite *GlideTestSuite) TestLMove() { res4, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - }, - res4, - ) + assert.Equal(suite.T(), []string{"one", "two", "three"}, res4) // source and destination are the same, performing list rotation, "one" gets popped and added back res5, err := client.LMove(key1, key1, api.Left, api.Left) @@ -3023,15 +2935,7 @@ func (suite *GlideTestSuite) TestLMove() { res6, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - }, - res6, - ) + assert.Equal(suite.T(), []string{"one", "two", "three"}, res6) // normal use case, "three" gets popped and added to the left of destination res7, err := client.LPush(key2, []string{"six", "five", "four"}) assert.Nil(suite.T(), err) @@ -3043,26 +2947,10 @@ func (suite *GlideTestSuite) TestLMove() { res9, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - }, - res9, - ) + assert.Equal(suite.T(), []string{"one", "two"}, res9) res10, err := client.LRange(key2, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("three"), - api.CreateStringResult("four"), - api.CreateStringResult("five"), - api.CreateStringResult("six"), - }, - res10, - ) + assert.Equal(suite.T(), []string{"three", "four", "five", "six"}, res10) // source exists but is not a list type key suite.verifyOK(client.Set(nonListKey, "value")) @@ -3888,18 +3776,11 @@ func (suite *GlideTestSuite) TestSortStore_BasicSorting() { assert.Nil(suite.T(), err) assert.NotNil(suite.T(), result) - assert.Equal(suite.T(), int64(5), result.Value()) + assert.Equal(suite.T(), int64(5), result) sortedValues, err := client.LRange(sortedKey, 0, -1) - resultList := []api.Result[string]{ - api.CreateStringResult("1"), - api.CreateStringResult("2"), - api.CreateStringResult("4"), - api.CreateStringResult("5"), - api.CreateStringResult("10"), - } assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, sortedValues) + assert.Equal(suite.T(), []string{"1", "2", "4", "5", "10"}, sortedValues) }) } @@ -3908,7 +3789,7 @@ func (suite *GlideTestSuite) TestSortStore_ErrorHandling() { result, err := client.SortStore("{listKey}nonExistingKey", "{listKey}mydestinationKey") assert.Nil(suite.T(), err) - assert.Equal(suite.T(), int64(0), result.Value()) + assert.Equal(suite.T(), int64(0), result) }) } @@ -3923,18 +3804,11 @@ func (suite *GlideTestSuite) TestSortStoreWithOptions_DescendingOrder() { assert.Nil(suite.T(), err) assert.NotNil(suite.T(), result) - assert.Equal(suite.T(), int64(5), result.Value()) + assert.Equal(suite.T(), int64(5), result) sortedValues, err := client.LRange(sortedKey, 0, -1) - resultList := []api.Result[string]{ - api.CreateStringResult("50"), - api.CreateStringResult("40"), - api.CreateStringResult("30"), - api.CreateStringResult("20"), - api.CreateStringResult("10"), - } assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, sortedValues) + assert.Equal(suite.T(), []string{"50", "40", "30", "20", "10"}, sortedValues) }) } @@ -3949,16 +3823,10 @@ func (suite *GlideTestSuite) TestSortStoreWithOptions_AlphaSorting() { assert.Nil(suite.T(), err) assert.NotNil(suite.T(), result) - assert.Equal(suite.T(), int64(5), result.Value()) + assert.Equal(suite.T(), int64(5), result) sortedValues, err := client.LRange(sortedKey, 0, -1) - resultList := []api.Result[string]{ - api.CreateStringResult("apple"), - api.CreateStringResult("banana"), - api.CreateStringResult("cherry"), - api.CreateStringResult("date"), - api.CreateStringResult("elderberry"), - } + resultList := []string{"apple", "banana", "cherry", "date", "elderberry"} assert.Nil(suite.T(), err) assert.Equal(suite.T(), resultList, sortedValues) }) @@ -3975,16 +3843,11 @@ func (suite *GlideTestSuite) TestSortStoreWithOptions_Limit() { assert.Nil(suite.T(), err) assert.NotNil(suite.T(), result) - assert.Equal(suite.T(), int64(3), result.Value()) + assert.Equal(suite.T(), int64(3), result) sortedValues, err := client.LRange(sortedKey, 0, -1) - resultList := []api.Result[string]{ - api.CreateStringResult("20"), - api.CreateStringResult("30"), - api.CreateStringResult("40"), - } assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, sortedValues) + assert.Equal(suite.T(), []string{"20", "30", "40"}, sortedValues) }) } @@ -4057,15 +3920,7 @@ func (suite *GlideTestSuite) TestBLMove() { res4, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - }, - res4, - ) + assert.Equal(suite.T(), []string{"one", "two", "three"}, res4) // source and destination are the same, performing list rotation, "one" gets popped and added back res5, err := client.BLMove(key1, key1, api.Left, api.Left, float64(0.1)) @@ -4074,15 +3929,7 @@ func (suite *GlideTestSuite) TestBLMove() { res6, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - api.CreateStringResult("three"), - }, - res6, - ) + assert.Equal(suite.T(), []string{"one", "two", "three"}, res6) // normal use case, "three" gets popped and added to the left of destination res7, err := client.LPush(key2, []string{"six", "five", "four"}) assert.Nil(suite.T(), err) @@ -4094,26 +3941,11 @@ func (suite *GlideTestSuite) TestBLMove() { res9, err := client.LRange(key1, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("one"), - api.CreateStringResult("two"), - }, - res9, - ) + assert.Equal(suite.T(), []string{"one", "two"}, res9) + res10, err := client.LRange(key2, int64(0), int64(-1)) assert.Nil(suite.T(), err) - assert.Equal( - suite.T(), - []api.Result[string]{ - api.CreateStringResult("three"), - api.CreateStringResult("four"), - api.CreateStringResult("five"), - api.CreateStringResult("six"), - }, - res10, - ) + assert.Equal(suite.T(), []string{"three", "four", "five", "six"}, res10) // source exists but is not a list type key suite.verifyOK(client.Set(nonListKey, "value")) @@ -4170,7 +4002,7 @@ func (suite *GlideTestSuite) TestType() { suite.verifyOK(client.Set(keyName, initialValue)) result, err := client.Type(keyName) assert.Nil(suite.T(), err) - assert.IsType(suite.T(), result, api.CreateStringResult("string"), "Value is string") + assert.IsType(suite.T(), result, "string", "Value is string") // Test 2: Check if the value is list key1 := "{keylist}-1" + uuid.NewString() @@ -4179,7 +4011,7 @@ func (suite *GlideTestSuite) TestType() { assert.Nil(suite.T(), err) resultType, err := client.Type(key1) assert.Nil(suite.T(), err) - assert.IsType(suite.T(), resultType, api.CreateStringResult("list"), "Value is list") + assert.IsType(suite.T(), resultType, "list", "Value is list") }) } @@ -4231,7 +4063,7 @@ func (suite *GlideTestSuite) TestRename() { // Test 2 Check if the rename command return false if the key/newkey is invalid. key1 := "{keyName}" + uuid.NewString() res1, err := client.Rename(key1, "invalidKey") - assert.Equal(suite.T(), "", res1.Value()) + assert.Equal(suite.T(), "", res1) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -4932,21 +4764,12 @@ func (suite *GlideTestSuite) TestZRange() { assert.NoError(t, err) // index [0:1] res, err := client.ZRange(key, options.NewRangeByIndexQuery(0, 1)) - expected := []api.Result[string]{ - api.CreateStringResult("a"), - api.CreateStringResult("b"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"a", "b"}, res) // index [0:-1] (all) res, err = client.ZRange(key, options.NewRangeByIndexQuery(0, -1)) - expected = []api.Result[string]{ - api.CreateStringResult("a"), - api.CreateStringResult("b"), - api.CreateStringResult("c"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"a", "b", "c"}, res) // index [3:1] (none) res, err = client.ZRange(key, options.NewRangeByIndexQuery(3, 1)) assert.NoError(t, err) @@ -4957,48 +4780,31 @@ func (suite *GlideTestSuite) TestZRange() { options.NewInfiniteScoreBoundary(options.NegativeInfinity), options.NewScoreBoundary(3, true)) res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("a"), - api.CreateStringResult("b"), - api.CreateStringResult("c"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"a", "b", "c"}, res) // score [-inf:3) query = options.NewRangeByScoreQuery( options.NewInfiniteScoreBoundary(options.NegativeInfinity), options.NewScoreBoundary(3, false)) res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("a"), - api.CreateStringResult("b"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"a", "b"}, res) // score (3:-inf] reverse query = options.NewRangeByScoreQuery( options.NewScoreBoundary(3, false), options.NewInfiniteScoreBoundary(options.NegativeInfinity)). SetReverse() res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("b"), - api.CreateStringResult("a"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"b", "a"}, res) // score [-inf:+inf] limit 1 2 query = options.NewRangeByScoreQuery( options.NewInfiniteScoreBoundary(options.NegativeInfinity), options.NewInfiniteScoreBoundary(options.PositiveInfinity)). SetLimit(1, 2) res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("b"), - api.CreateStringResult("c"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"b", "c"}, res) // score [-inf:3) reverse (none) query = options.NewRangeByScoreQuery( options.NewInfiniteScoreBoundary(options.NegativeInfinity), @@ -5019,36 +4825,24 @@ func (suite *GlideTestSuite) TestZRange() { options.NewInfiniteLexBoundary(options.NegativeInfinity), options.NewLexBoundary("c", false)) res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("a"), - api.CreateStringResult("b"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"a", "b"}, res) // lex [+:-] reverse limit 1 2 query = options.NewRangeByLexQuery( options.NewInfiniteLexBoundary(options.PositiveInfinity), options.NewInfiniteLexBoundary(options.NegativeInfinity)). SetReverse().SetLimit(1, 2) res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("b"), - api.CreateStringResult("a"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"b", "a"}, res) // lex (c:-] reverse query = options.NewRangeByLexQuery( options.NewLexBoundary("c", false), options.NewInfiniteLexBoundary(options.NegativeInfinity)). SetReverse() res, err = client.ZRange(key, query) - expected = []api.Result[string]{ - api.CreateStringResult("b"), - api.CreateStringResult("a"), - } assert.NoError(t, err) - assert.Equal(t, expected, res) + assert.Equal(t, []string{"b", "a"}, res) // lex [+:c] (none) query = options.NewRangeByLexQuery( options.NewInfiniteLexBoundary(options.PositiveInfinity), @@ -6694,18 +6488,11 @@ func (suite *GlideTestSuite) TestSortStoreWithOptions_ByPattern() { assert.Nil(suite.T(), err) assert.NotNil(suite.T(), result) - assert.Equal(suite.T(), int64(5), result.Value()) + assert.Equal(suite.T(), int64(5), result) sortedValues, err := client.LRange(sortedKey, 0, -1) - resultList := []api.Result[string]{ - api.CreateStringResult("d"), - api.CreateStringResult("b"), - api.CreateStringResult("c"), - api.CreateStringResult("e"), - api.CreateStringResult("a"), - } assert.Nil(suite.T(), err) - assert.Equal(suite.T(), resultList, sortedValues) + assert.Equal(suite.T(), []string{"d", "b", "c", "e", "a"}, sortedValues) }) } From 502a8d7734d83515affd94696f12e7631c8ce6cf Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 20 Jan 2025 12:01:29 -0800 Subject: [PATCH 4/5] Go: Fix return types, parn 5 (#2964) Fix return types Signed-off-by: Yury-Fridlyand --- go/api/base_client.go | 36 ++-- go/api/glide_client.go | 2 +- go/api/hash_commands.go | 8 +- go/api/list_commands.go | 16 +- go/api/response_handlers.go | 99 +++++---- go/api/server_management_commands.go | 6 +- go/api/set_commands.go | 44 ++-- go/api/sorted_set_commands.go | 18 +- go/integTest/shared_commands_test.go | 253 +++++++++-------------- go/integTest/standalone_commands_test.go | 8 +- 10 files changed, 206 insertions(+), 284 deletions(-) diff --git a/go/api/base_client.go b/go/api/base_client.go index 9d6a353c1e..c0a79dfdac 100644 --- a/go/api/base_client.go +++ b/go/api/base_client.go @@ -376,7 +376,7 @@ func (client *baseClient) HGet(key string, field string) (Result[string], error) return handleStringOrNilResponse(result) } -func (client *baseClient) HGetAll(key string) (map[Result[string]]Result[string], error) { +func (client *baseClient) HGetAll(key string) (map[string]string, error) { result, err := client.executeCommand(C.HGetAll, []string{key}) if err != nil { return nil, err @@ -672,7 +672,7 @@ func (client *baseClient) SUnionStore(destination string, keys []string) (int64, return handleIntResponse(result) } -func (client *baseClient) SMembers(key string) (map[Result[string]]struct{}, error) { +func (client *baseClient) SMembers(key string) (map[string]struct{}, error) { result, err := client.executeCommand(C.SMembers, []string{key}) if err != nil { return nil, err @@ -699,7 +699,7 @@ func (client *baseClient) SIsMember(key string, member string) (bool, error) { return handleBoolResponse(result) } -func (client *baseClient) SDiff(keys []string) (map[Result[string]]struct{}, error) { +func (client *baseClient) SDiff(keys []string) (map[string]struct{}, error) { result, err := client.executeCommand(C.SDiff, keys) if err != nil { return nil, err @@ -717,7 +717,7 @@ func (client *baseClient) SDiffStore(destination string, keys []string) (int64, return handleIntResponse(result) } -func (client *baseClient) SInter(keys []string) (map[Result[string]]struct{}, error) { +func (client *baseClient) SInter(keys []string) (map[string]struct{}, error) { result, err := client.executeCommand(C.SInter, keys) if err != nil { return nil, err @@ -782,7 +782,7 @@ func (client *baseClient) SMIsMember(key string, members []string) ([]bool, erro return handleBoolArrayResponse(result) } -func (client *baseClient) SUnion(keys []string) (map[Result[string]]struct{}, error) { +func (client *baseClient) SUnion(keys []string) (map[string]struct{}, error) { result, err := client.executeCommand(C.SUnion, keys) if err != nil { return nil, err @@ -1025,7 +1025,7 @@ func (client *baseClient) LPushX(key string, elements []string) (int64, error) { return handleIntResponse(result) } -func (client *baseClient) LMPop(keys []string, listDirection ListDirection) (map[Result[string]][]Result[string], error) { +func (client *baseClient) LMPop(keys []string, listDirection ListDirection) (map[string][]string, error) { listDirectionStr, err := listDirection.toString() if err != nil { return nil, err @@ -1046,14 +1046,14 @@ func (client *baseClient) LMPop(keys []string, listDirection ListDirection) (map return nil, err } - return handleStringToStringArrayMapOrNullResponse(result) + return handleStringToStringArrayMapOrNilResponse(result) } func (client *baseClient) LMPopCount( keys []string, listDirection ListDirection, count int64, -) (map[Result[string]][]Result[string], error) { +) (map[string][]string, error) { listDirectionStr, err := listDirection.toString() if err != nil { return nil, err @@ -1074,14 +1074,14 @@ func (client *baseClient) LMPopCount( return nil, err } - return handleStringToStringArrayMapOrNullResponse(result) + return handleStringToStringArrayMapOrNilResponse(result) } func (client *baseClient) BLMPop( keys []string, listDirection ListDirection, timeoutSecs float64, -) (map[Result[string]][]Result[string], error) { +) (map[string][]string, error) { listDirectionStr, err := listDirection.toString() if err != nil { return nil, err @@ -1102,7 +1102,7 @@ func (client *baseClient) BLMPop( return nil, err } - return handleStringToStringArrayMapOrNullResponse(result) + return handleStringToStringArrayMapOrNilResponse(result) } func (client *baseClient) BLMPopCount( @@ -1110,7 +1110,7 @@ func (client *baseClient) BLMPopCount( listDirection ListDirection, count int64, timeoutSecs float64, -) (map[Result[string]][]Result[string], error) { +) (map[string][]string, error) { listDirectionStr, err := listDirection.toString() if err != nil { return nil, err @@ -1131,7 +1131,7 @@ func (client *baseClient) BLMPopCount( return nil, err } - return handleStringToStringArrayMapOrNullResponse(result) + return handleStringToStringArrayMapOrNilResponse(result) } func (client *baseClient) LSet(key string, index int64, element string) (string, error) { @@ -1754,7 +1754,7 @@ func (client *baseClient) ZIncrBy(key string, increment float64, member string) return handleFloatResponse(result) } -func (client *baseClient) ZPopMin(key string) (map[Result[string]]Result[float64], error) { +func (client *baseClient) ZPopMin(key string) (map[string]float64, error) { result, err := client.executeCommand(C.ZPopMin, []string{key}) if err != nil { return nil, err @@ -1762,7 +1762,7 @@ func (client *baseClient) ZPopMin(key string) (map[Result[string]]Result[float64 return handleStringDoubleMapResponse(result) } -func (client *baseClient) ZPopMinWithCount(key string, count int64) (map[Result[string]]Result[float64], error) { +func (client *baseClient) ZPopMinWithCount(key string, count int64) (map[string]float64, error) { result, err := client.executeCommand(C.ZPopMin, []string{key, utils.IntToString(count)}) if err != nil { return nil, err @@ -1770,7 +1770,7 @@ func (client *baseClient) ZPopMinWithCount(key string, count int64) (map[Result[ return handleStringDoubleMapResponse(result) } -func (client *baseClient) ZPopMax(key string) (map[Result[string]]Result[float64], error) { +func (client *baseClient) ZPopMax(key string) (map[string]float64, error) { result, err := client.executeCommand(C.ZPopMax, []string{key}) if err != nil { return nil, err @@ -1778,7 +1778,7 @@ func (client *baseClient) ZPopMax(key string) (map[Result[string]]Result[float64 return handleStringDoubleMapResponse(result) } -func (client *baseClient) ZPopMaxWithCount(key string, count int64) (map[Result[string]]Result[float64], error) { +func (client *baseClient) ZPopMaxWithCount(key string, count int64) (map[string]float64, error) { result, err := client.executeCommand(C.ZPopMax, []string{key, utils.IntToString(count)}) if err != nil { return nil, err @@ -1892,7 +1892,7 @@ func (client *baseClient) ZRange(key string, rangeQuery options.ZRangeQuery) ([] func (client *baseClient) ZRangeWithScores( key string, rangeQuery options.ZRangeQueryWithScores, -) (map[Result[string]]Result[float64], error) { +) (map[string]float64, error) { args := make([]string, 0, 10) args = append(args, key) args = append(args, rangeQuery.ToArgs()...) diff --git a/go/api/glide_client.go b/go/api/glide_client.go index a90575c767..51ea9ef4b4 100644 --- a/go/api/glide_client.go +++ b/go/api/glide_client.go @@ -51,7 +51,7 @@ func (client *glideClient) ConfigSet(parameters map[string]string) (string, erro return handleStringResponse(result) } -func (client *glideClient) ConfigGet(args []string) (map[Result[string]]Result[string], error) { +func (client *glideClient) ConfigGet(args []string) (map[string]string, error) { res, err := client.executeCommand(C.ConfigGet, args) if err != nil { return nil, err diff --git a/go/api/hash_commands.go b/go/api/hash_commands.go index ba2f248e8f..730e70aa46 100644 --- a/go/api/hash_commands.go +++ b/go/api/hash_commands.go @@ -46,14 +46,10 @@ type HashCommands interface { // // For example: // fieldValueMap, err := client.HGetAll("my_hash") - // // field1 equals api.CreateStringResult("field1") - // // value1 equals api.CreateStringResult("value1") - // // field2 equals api.CreateStringResult("field2") - // // value2 equals api.CreateStringResult("value2") - // // fieldValueMap equals map[api.Result[string]]api.Result[string]{field1: value1, field2: value2} + // // fieldValueMap equals map[string]string{field1: value1, field2: value2} // // [valkey.io]: https://valkey.io/commands/hgetall/ - HGetAll(key string) (map[Result[string]]Result[string], error) + HGetAll(key string) (map[string]string, error) // HMGet returns the values associated with the specified fields in the hash stored at key. // diff --git a/go/api/list_commands.go b/go/api/list_commands.go index d1c1970dfd..1d2942e5ae 100644 --- a/go/api/list_commands.go +++ b/go/api/list_commands.go @@ -491,10 +491,10 @@ type ListCommands interface { // For example: // result, err := client.LPush("my_list", []string{"one", "two", "three"}) // result, err := client.LMPop([]string{"my_list"}, api.Left) - // result[api.CreateStringResult("my_list")] = []api.Result[string]{api.CreateStringResult("three")} + // result["my_list"] = []string{"three"} // // [valkey.io]: https://valkey.io/commands/lmpop/ - LMPop(keys []string, listDirection ListDirection) (map[Result[string]][]Result[string], error) + LMPop(keys []string, listDirection ListDirection) (map[string][]string, error) // Pops one or more elements from the first non-empty list from the provided keys. // @@ -514,10 +514,10 @@ type ListCommands interface { // For example: // result, err := client.LPush("my_list", []string{"one", "two", "three"}) // result, err := client.LMPopCount([]string{"my_list"}, api.Left, int64(1)) - // result[api.CreateStringResult("my_list")] = []api.Result[string]{api.CreateStringResult("three")} + // result["my_list"] = []string{"three"} // // [valkey.io]: https://valkey.io/commands/lmpop/ - LMPopCount(keys []string, listDirection ListDirection, count int64) (map[Result[string]][]Result[string], error) + LMPopCount(keys []string, listDirection ListDirection, count int64) (map[string][]string, error) // Blocks the connection until it pops one element from the first non-empty list from the provided keys. BLMPop is the // blocking variant of [api.LMPop]. @@ -544,11 +544,11 @@ type ListCommands interface { // For example: // result, err := client.LPush("my_list", []string{"one", "two", "three"}) // result, err := client.BLMPop([]string{"my_list"}, api.Left, float64(0.1)) - // result[api.CreateStringResult("my_list")] = []api.Result[string]{api.CreateStringResult("three")} + // result["my_list"] = []string{"three"} // // [valkey.io]: https://valkey.io/commands/blmpop/ // [Blocking Commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands - BLMPop(keys []string, listDirection ListDirection, timeoutSecs float64) (map[Result[string]][]Result[string], error) + BLMPop(keys []string, listDirection ListDirection, timeoutSecs float64) (map[string][]string, error) // Blocks the connection until it pops one or more elements from the first non-empty list from the provided keys. // BLMPopCount is the blocking variant of [api.LMPopCount]. @@ -576,7 +576,7 @@ type ListCommands interface { // For example: // result, err: client.LPush("my_list", []string{"one", "two", "three"}) // result, err := client.BLMPopCount([]string{"my_list"}, api.Left, int64(1), float64(0.1)) - // result[api.CreateStringResult("my_list")] = []api.Result[string]{api.CreateStringResult("three")} + // result["my_list"] = []string{"three"} // // [valkey.io]: https://valkey.io/commands/blmpop/ // [Blocking Commands]: https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#blocking-commands @@ -585,7 +585,7 @@ type ListCommands interface { listDirection ListDirection, count int64, timeoutSecs float64, - ) (map[Result[string]][]Result[string], error) + ) (map[string][]string, error) // Sets the list element at index to element. // The index is zero-based, so 0 means the first element,1 the second element and so on. Negative indices can be used to diff --git a/go/api/response_handlers.go b/go/api/response_handlers.go index 98ba2713d2..dd7fbe2712 100644 --- a/go/api/response_handlers.go +++ b/go/api/response_handlers.go @@ -351,7 +351,7 @@ func handleBoolArrayResponse(response *C.struct_CommandResponse) ([]bool, error) return slice, nil } -func handleStringDoubleMapResponse(response *C.struct_CommandResponse) (map[Result[string]]Result[float64], error) { +func handleStringDoubleMapResponse(response *C.struct_CommandResponse) (map[string]float64, error) { defer C.free_command_response(response) typeErr := checkResponseType(response, C.Map, false) @@ -359,23 +359,26 @@ func handleStringDoubleMapResponse(response *C.struct_CommandResponse) (map[Resu return nil, typeErr } - m := make(map[Result[string]]Result[float64], response.array_value_len) - for _, v := range unsafe.Slice(response.array_value, response.array_value_len) { - key, err := convertCharArrayToString(v.map_key, true) - if err != nil { - return nil, err - } - typeErr := checkResponseType(v.map_value, C.Float, false) - if typeErr != nil { - return nil, typeErr - } - value := CreateFloat64Result(float64(v.map_value.float_value)) - m[key] = value + data, err := parseMap(response) + if err != nil { + return nil, err + } + aMap := data.(map[string]interface{}) + + converted, err := mapConverter[float64]{ + nil, false, + }.convert(aMap) + if err != nil { + return nil, err + } + result, ok := converted.(map[string]float64) + if !ok { + return nil, &RequestError{fmt.Sprintf("unexpected type of map: %T", converted)} } - return m, nil + return result, nil } -func handleStringToStringMapResponse(response *C.struct_CommandResponse) (map[Result[string]]Result[string], error) { +func handleStringToStringMapResponse(response *C.struct_CommandResponse) (map[string]string, error) { defer C.free_command_response(response) typeErr := checkResponseType(response, C.Map, false) @@ -383,25 +386,28 @@ func handleStringToStringMapResponse(response *C.struct_CommandResponse) (map[Re return nil, typeErr } - m := make(map[Result[string]]Result[string], response.array_value_len) - for _, v := range unsafe.Slice(response.array_value, response.array_value_len) { - key, err := convertCharArrayToString(v.map_key, true) - if err != nil { - return nil, err - } - value, err := convertCharArrayToString(v.map_value, true) - if err != nil { - return nil, err - } - m[key] = value + data, err := parseMap(response) + if err != nil { + return nil, err } + aMap := data.(map[string]interface{}) - return m, nil + converted, err := mapConverter[string]{ + nil, false, + }.convert(aMap) + if err != nil { + return nil, err + } + result, ok := converted.(map[string]string) + if !ok { + return nil, &RequestError{fmt.Sprintf("unexpected type of map: %T", converted)} + } + return result, nil } -func handleStringToStringArrayMapOrNullResponse( +func handleStringToStringArrayMapOrNilResponse( response *C.struct_CommandResponse, -) (map[Result[string]][]Result[string], error) { +) (map[string][]string, error) { defer C.free_command_response(response) typeErr := checkResponseType(response, C.Map, true) @@ -413,23 +419,28 @@ func handleStringToStringArrayMapOrNullResponse( return nil, nil } - m := make(map[Result[string]][]Result[string], response.array_value_len) - for _, v := range unsafe.Slice(response.array_value, response.array_value_len) { - key, err := convertCharArrayToString(v.map_key, true) - if err != nil { - return nil, err - } - value, err := convertStringOrNilArray(v.map_value) - if err != nil { - return nil, err - } - m[key] = value + data, err := parseMap(response) + if err != nil { + return nil, err + } + + converters := mapConverter[[]string]{ + arrayConverter[string]{}, + false, } - return m, nil + res, err := converters.convert(data) + if err != nil { + return nil, err + } + if result, ok := res.(map[string][]string); ok { + return result, nil + } + + return nil, &RequestError{fmt.Sprintf("unexpected type received: %T", res)} } -func handleStringSetResponse(response *C.struct_CommandResponse) (map[Result[string]]struct{}, error) { +func handleStringSetResponse(response *C.struct_CommandResponse) (map[string]struct{}, error) { defer C.free_command_response(response) typeErr := checkResponseType(response, C.Sets, false) @@ -437,13 +448,13 @@ func handleStringSetResponse(response *C.struct_CommandResponse) (map[Result[str return nil, typeErr } - slice := make(map[Result[string]]struct{}, response.sets_value_len) + slice := make(map[string]struct{}, response.sets_value_len) for _, v := range unsafe.Slice(response.sets_value, response.sets_value_len) { res, err := convertCharArrayToString(&v, true) if err != nil { return nil, err } - slice[res] = struct{}{} + slice[res.Value()] = struct{}{} } return slice, nil diff --git a/go/api/server_management_commands.go b/go/api/server_management_commands.go index 37954f543a..3653f17903 100644 --- a/go/api/server_management_commands.go +++ b/go/api/server_management_commands.go @@ -37,11 +37,11 @@ type ServerManagementCommands interface { // // For example: // result, err := client.ConfigGet([]string{"timeout" , "maxmemory"}) - // result[api.CreateStringResult("timeout")] = api.CreateStringResult("1000") - // result[api.CreateStringResult"maxmemory")] = api.CreateStringResult("1GB") + // // result["timeout"] = "1000" + // // result["maxmemory"] = "1GB" // // [valkey.io]: https://valkey.io/commands/config-get/ - ConfigGet(args []string) (map[Result[string]]Result[string], error) + ConfigGet(args []string) (map[string]string, error) // Sets configuration parameters to the specified values. // diff --git a/go/api/set_commands.go b/go/api/set_commands.go index 5d2315ae74..bed1d65200 100644 --- a/go/api/set_commands.go +++ b/go/api/set_commands.go @@ -54,20 +54,16 @@ type SetCommands interface { // key - The key from which to retrieve the set members. // // Return value: - // A map[Result[string]]struct{} containing all members of the set. - // Returns an empty map if key does not exist. + // A `map[string]struct{}` containing all members of the set. + // Returns an empty collection if key does not exist. // // For example: // // Assume set "my_set" contains: "member1", "member2" // result, err := client.SMembers("my_set") - // // result equals: - // // map[Result[string]]struct{}{ - // // api.CreateStringResult("member1"): {}, - // // api.CreateStringResult("member2"): {} - // // } + // // result: map[string]struct{}{ "member1": {}, "member2": {} } // // [valkey.io]: https://valkey.io/commands/smembers/ - SMembers(key string) (map[Result[string]]struct{}, error) + SMembers(key string) (map[string]struct{}, error) // SCard retrieves the set cardinality (number of elements) of the set stored at key. // @@ -119,19 +115,16 @@ type SetCommands interface { // keys - The keys of the sets to diff. // // Return value: - // A map[Result[string]]struct{} representing the difference between the sets. + // A `map[string]struct{}` representing the difference between the sets. // If a key does not exist, it is treated as an empty set. // // Example: // result, err := client.SDiff([]string{"set1", "set2"}) - // // result might contain: - // // map[Result[string]]struct{}{ - // // api.CreateStringResult("element"): {}, - // // } + // // result: map[string]struct{}{ "element": {} } // // Indicates that "element" is present in "set1", but missing in "set2" // // [valkey.io]: https://valkey.io/commands/sdiff/ - SDiff(keys []string) (map[Result[string]]struct{}, error) + SDiff(keys []string) (map[string]struct{}, error) // SDiffStore stores the difference between the first set and all the successive sets in keys // into a new set at destination. @@ -165,20 +158,16 @@ type SetCommands interface { // keys - The keys of the sets to intersect. // // Return value: - // A map[Result[string]]struct{} containing members which are present in all given sets. - // If one or more sets do not exist, an empty map will be returned. - // + // A `map[string]struct{}` containing members which are present in all given sets. + // If one or more sets do not exist, an empty collection will be returned. // // Example: // result, err := client.SInter([]string{"set1", "set2"}) - // // result might contain: - // // map[Result[string]]struct{}{ - // // api.CreateStringResult("element"): {}, - // // } + // // result: map[string]struct{}{ "element": {} } // // Indicates that "element" is present in both "set1" and "set2" // // [valkey.io]: https://valkey.io/commands/sinter/ - SInter(keys []string) (map[Result[string]]struct{}, error) + SInter(keys []string) (map[string]struct{}, error) // Stores the members of the intersection of all given sets specified by `keys` into a new set at `destination` // @@ -353,9 +342,8 @@ type SetCommands interface { // keys - The keys of the sets. // // Return value: - // A map[Result[string]]struct{} of members which are present in at least one of the given sets. - // If none of the sets exist, an empty map will be returned. - // + // A `map[string]struct{}` of members which are present in at least one of the given sets. + // If none of the sets exist, an empty collection will be returned. // // Example: // result1, err := client.SAdd("my_set1", []string {"member1", "member2"}) @@ -367,15 +355,15 @@ type SetCommands interface { // // result.IsNil(): false // // result3, err := client.SUnion([]string {"my_set1", "my_set2"}) - // // result3.Value(): "{'member1', 'member2', 'member3'}" + // // result3: "{'member1', 'member2', 'member3'}" // // err: nil // // result4, err := client.SUnion([]string {"my_set1", "non_existing_set"}) - // // result4.Value(): "{'member1', 'member2'}" + // // result4: "{'member1', 'member2'}" // // err: nil // // [valkey.io]: https://valkey.io/commands/sunion/ - SUnion(keys []string) (map[Result[string]]struct{}, error) + SUnion(keys []string) (map[string]struct{}, error) SScan(key string, cursor string) (string, []string, error) diff --git a/go/api/sorted_set_commands.go b/go/api/sorted_set_commands.go index 4010d62d05..62d06091bd 100644 --- a/go/api/sorted_set_commands.go +++ b/go/api/sorted_set_commands.go @@ -127,10 +127,10 @@ type SortedSetCommands interface { // // Example: // res, err := client.zpopmin("mySortedSet") - // fmt.Println(res.Value()) // Output: map["member1":5.0] + // fmt.Println(res) // Output: map["member1": 5.0] // // [valkey.io]: https://valkey.io/commands/zpopmin/ - ZPopMin(key string) (map[Result[string]]Result[float64], error) + ZPopMin(key string) (map[string]float64, error) // Removes and returns up to `count` members with the lowest scores from the sorted set // stored at the specified `key`. @@ -148,10 +148,10 @@ type SortedSetCommands interface { // // Example: // res, err := client.ZPopMinWithCount("mySortedSet", 2) - // fmt.Println(res.Value()) // Output: map["member1":5.0, "member2":6.0] + // fmt.Println(res) // Output: map["member1": 5.0, "member2": 6.0] // // [valkey.io]: https://valkey.io/commands/zpopmin/ - ZPopMinWithCount(key string, count int64) (map[Result[string]]Result[float64], error) + ZPopMinWithCount(key string, count int64) (map[string]float64, error) // Removes and returns the member with the highest score from the sorted set stored at the // specified `key`. @@ -168,10 +168,10 @@ type SortedSetCommands interface { // // Example: // res, err := client.zpopmax("mySortedSet") - // fmt.Println(res.Value()) // Output: map["member2":8.0] + // fmt.Println(res) // Output: map["member2": 8.0] // // [valkey.io]: https://valkey.io/commands/zpopmin/ - ZPopMax(key string) (map[Result[string]]Result[float64], error) + ZPopMax(key string) (map[string]float64, error) // Removes and returns up to `count` members with the highest scores from the sorted set // stored at the specified `key`. @@ -189,10 +189,10 @@ type SortedSetCommands interface { // // Example: // res, err := client.ZPopMaxWithCount("mySortedSet", 2) - // fmt.Println(res.Value()) // Output: map["member1":5.0, "member2":6.0] + // fmt.Println(res) // Output: map["member1": 5.0, "member2": 6.0] // // [valkey.io]: https://valkey.io/commands/zpopmin/ - ZPopMaxWithCount(key string, count int64) (map[Result[string]]Result[float64], error) + ZPopMaxWithCount(key string, count int64) (map[string]float64, error) // Removes the specified members from the sorted set stored at `key`. // Specified members that are not a member of this set are ignored. @@ -266,7 +266,7 @@ type SortedSetCommands interface { ZRange(key string, rangeQuery options.ZRangeQuery) ([]string, error) - ZRangeWithScores(key string, rangeQuery options.ZRangeQueryWithScores) (map[Result[string]]Result[float64], error) + ZRangeWithScores(key string, rangeQuery options.ZRangeQueryWithScores) (map[string]float64, error) // Returns the rank of `member` in the sorted set stored at `key`, with // scores ordered from low to high, starting from `0`. diff --git a/go/integTest/shared_commands_test.go b/go/integTest/shared_commands_test.go index 4f83224e2f..cba42181b0 100644 --- a/go/integTest/shared_commands_test.go +++ b/go/integTest/shared_commands_test.go @@ -635,9 +635,14 @@ func (suite *GlideTestSuite) TestHSet_WithExistingKey() { func (suite *GlideTestSuite) TestHSet_byteString() { suite.runWithDefaultClients(func(client api.BaseClient) { + field1 := string([]byte{0xFF, 0x00, 0xAA}) + value1 := string([]byte{0xDE, 0xAD, 0xBE, 0xEF}) + field2 := string([]byte{0x01, 0x02, 0x03, 0xFE}) + value2 := string([]byte{0xCA, 0xFE, 0xBA, 0xBE}) + fields := map[string]string{ - string([]byte{0xFF, 0x00, 0xAA}): string([]byte{0xDE, 0xAD, 0xBE, 0xEF}), - string([]byte{0x01, 0x02, 0x03, 0xFE}): string([]byte{0xCA, 0xFE, 0xBA, 0xBE}), + field1: value1, + field2: value2, } key := string([]byte{0x01, 0x02, 0x03, 0xFE}) @@ -646,16 +651,8 @@ func (suite *GlideTestSuite) TestHSet_byteString() { assert.Equal(suite.T(), int64(2), res1) res2, err := client.HGetAll(key) - key1 := api.CreateStringResult(string([]byte{0xFF, 0x00, 0xAA})) - value1 := api.CreateStringResult(string([]byte{0xDE, 0xAD, 0xBE, 0xEF})) - key2 := api.CreateStringResult(string([]byte{0x01, 0x02, 0x03, 0xFE})) - value2 := api.CreateStringResult(string([]byte{0xCA, 0xFE, 0xBA, 0xBE})) - fieldsResult := map[api.Result[string]]api.Result[string]{ - key1: value1, - key2: value2, - } assert.Nil(suite.T(), err) - assert.Equal(suite.T(), fieldsResult, res2) + assert.Equal(suite.T(), fields, res2) }) } @@ -728,14 +725,9 @@ func (suite *GlideTestSuite) TestHGetAll_WithExistingKey() { assert.Nil(suite.T(), err) assert.Equal(suite.T(), int64(2), res1) - field1 := api.CreateStringResult("field1") - value1 := api.CreateStringResult("value1") - field2 := api.CreateStringResult("field2") - value2 := api.CreateStringResult("value2") - fieldsResult := map[api.Result[string]]api.Result[string]{field1: value1, field2: value2} res2, err := client.HGetAll(key) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), fieldsResult, res2) + assert.Equal(suite.T(), fields, res2) }) } @@ -818,10 +810,8 @@ func (suite *GlideTestSuite) TestHSetNX_WithNotExistingKey() { assert.True(suite.T(), res1) res2, err := client.HGetAll(key) - field1 := api.CreateStringResult("field1") - value1 := api.CreateStringResult("value1") assert.Nil(suite.T(), err) - assert.Equal(suite.T(), map[api.Result[string]]api.Result[string]{field1: value1}, res2) + assert.Equal(suite.T(), map[string]string{"field1": "value1"}, res2) }) } @@ -1568,21 +1558,21 @@ func (suite *GlideTestSuite) TestSUnionStore() { memberArray1 := []string{"a", "b", "c"} memberArray2 := []string{"c", "d", "e"} memberArray3 := []string{"e", "f", "g"} - expected1 := map[api.Result[string]]struct{}{ - api.CreateStringResult("a"): {}, - api.CreateStringResult("b"): {}, - api.CreateStringResult("c"): {}, - api.CreateStringResult("d"): {}, - api.CreateStringResult("e"): {}, + expected1 := map[string]struct{}{ + "a": {}, + "b": {}, + "c": {}, + "d": {}, + "e": {}, } - expected2 := map[api.Result[string]]struct{}{ - api.CreateStringResult("a"): {}, - api.CreateStringResult("b"): {}, - api.CreateStringResult("c"): {}, - api.CreateStringResult("d"): {}, - api.CreateStringResult("e"): {}, - api.CreateStringResult("f"): {}, - api.CreateStringResult("g"): {}, + expected2 := map[string]struct{}{ + "a": {}, + "b": {}, + "c": {}, + "d": {}, + "e": {}, + "f": {}, + "g": {}, } t := suite.T() @@ -1771,9 +1761,7 @@ func (suite *GlideTestSuite) TestSDiff() { result, err := client.SDiff([]string{key1, key2}) assert.Nil(suite.T(), err) - assert.Len(suite.T(), result, 2) - assert.Contains(suite.T(), result, api.CreateStringResult("a")) - assert.Contains(suite.T(), result, api.CreateStringResult("b")) + assert.Equal(suite.T(), map[string]struct{}{"a": {}, "b": {}}, result) }) } @@ -1799,10 +1787,7 @@ func (suite *GlideTestSuite) TestSDiff_WithSingleKeyExist() { res2, err := client.SDiff([]string{key1, key2}) assert.Nil(suite.T(), err) - assert.Len(suite.T(), res2, 3) - assert.Contains(suite.T(), res2, api.CreateStringResult("a")) - assert.Contains(suite.T(), res2, api.CreateStringResult("b")) - assert.Contains(suite.T(), res2, api.CreateStringResult("c")) + assert.Equal(suite.T(), map[string]struct{}{"a": {}, "b": {}, "c": {}}, res2) }) } @@ -1826,9 +1811,7 @@ func (suite *GlideTestSuite) TestSDiffStore() { members, err := client.SMembers(key3) assert.Nil(suite.T(), err) - assert.Len(suite.T(), members, 2) - assert.Contains(suite.T(), members, api.CreateStringResult("a")) - assert.Contains(suite.T(), members, api.CreateStringResult("b")) + assert.Equal(suite.T(), map[string]struct{}{"a": {}, "b": {}}, members) }) } @@ -1863,9 +1846,7 @@ func (suite *GlideTestSuite) TestSinter() { members, err := client.SInter([]string{key1, key2}) assert.Nil(suite.T(), err) - assert.Len(suite.T(), members, 2) - assert.Contains(suite.T(), members, api.CreateStringResult("c")) - assert.Contains(suite.T(), members, api.CreateStringResult("d")) + assert.Equal(suite.T(), map[string]struct{}{"c": {}, "d": {}}, members) }) } @@ -1906,10 +1887,7 @@ func (suite *GlideTestSuite) TestSinterStore() { res4, err := client.SMembers(key3) assert.NoError(t, err) - assert.Len(t, res4, 1) - for key := range res4 { - assert.Equal(t, key.Value(), "c") - } + assert.Equal(t, map[string]struct{}{"c": {}}, res4) // overwrite existing set, which is also a source set res5, err := client.SInterStore(key2, []string{key1, key2}) @@ -1918,10 +1896,7 @@ func (suite *GlideTestSuite) TestSinterStore() { res6, err := client.SMembers(key2) assert.NoError(t, err) - assert.Len(t, res6, 1) - for key := range res6 { - assert.Equal(t, key.Value(), "c") - } + assert.Equal(t, map[string]struct{}{"c": {}}, res6) // source set is the same as the existing set res7, err := client.SInterStore(key1, []string{key2}) @@ -1930,10 +1905,7 @@ func (suite *GlideTestSuite) TestSinterStore() { res8, err := client.SMembers(key2) assert.NoError(t, err) - assert.Len(t, res8, 1) - for key := range res8 { - assert.Equal(t, key.Value(), "c") - } + assert.Equal(t, map[string]struct{}{"c": {}}, res8) // intersection with non-existing key res9, err := client.SInterStore(key1, []string{key2, nonExistingKey}) @@ -1968,10 +1940,7 @@ func (suite *GlideTestSuite) TestSinterStore() { // check that the key is now empty res13, err := client.SMembers(stringKey) assert.NoError(t, err) - assert.Len(t, res13, 1) - for key := range res13 { - assert.Equal(t, key.Value(), "c") - } + assert.Equal(t, map[string]struct{}{"c": {}}, res13) }) } @@ -2119,17 +2088,17 @@ func (suite *GlideTestSuite) TestSUnion() { nonSetKey := uuid.NewString() memberList1 := []string{"a", "b", "c"} memberList2 := []string{"b", "c", "d", "e"} - expected1 := map[api.Result[string]]struct{}{ - api.CreateStringResult("a"): {}, - api.CreateStringResult("b"): {}, - api.CreateStringResult("c"): {}, - api.CreateStringResult("d"): {}, - api.CreateStringResult("e"): {}, + expected1 := map[string]struct{}{ + "a": {}, + "b": {}, + "c": {}, + "d": {}, + "e": {}, } - expected2 := map[api.Result[string]]struct{}{ - api.CreateStringResult("a"): {}, - api.CreateStringResult("b"): {}, - api.CreateStringResult("c"): {}, + expected2 := map[string]struct{}{ + "a": {}, + "b": {}, + "c": {}, } res1, err := client.SAdd(key1, memberList1) @@ -2146,7 +2115,7 @@ func (suite *GlideTestSuite) TestSUnion() { res4, err := client.SUnion([]string{key3}) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), map[api.Result[string]]struct{}{}, res4) + assert.Empty(suite.T(), res4) res5, err := client.SUnion([]string{key1, key3}) assert.Nil(suite.T(), err) @@ -2191,20 +2160,11 @@ func (suite *GlideTestSuite) TestSMove() { res4, err := client.SMembers(key1) assert.NoError(t, err) - expectedSet := map[api.Result[string]]struct{}{ - api.CreateStringResult("2"): {}, - api.CreateStringResult("3"): {}, - } - assert.True(t, reflect.DeepEqual(expectedSet, res4)) + assert.Equal(suite.T(), map[string]struct{}{"2": {}, "3": {}}, res4) res5, err := client.SMembers(key2) assert.NoError(t, err) - expectedSet = map[api.Result[string]]struct{}{ - api.CreateStringResult("1"): {}, - api.CreateStringResult("2"): {}, - api.CreateStringResult("3"): {}, - } - assert.True(t, reflect.DeepEqual(expectedSet, res5)) + assert.Equal(suite.T(), map[string]struct{}{"1": {}, "2": {}, "3": {}}, res5) // moved element already exists in the destination set res6, err := client.SMove(key2, key1, "2") @@ -2213,19 +2173,11 @@ func (suite *GlideTestSuite) TestSMove() { res7, err := client.SMembers(key1) assert.NoError(t, err) - expectedSet = map[api.Result[string]]struct{}{ - api.CreateStringResult("2"): {}, - api.CreateStringResult("3"): {}, - } - assert.True(t, reflect.DeepEqual(expectedSet, res7)) + assert.Equal(suite.T(), map[string]struct{}{"2": {}, "3": {}}, res7) res8, err := client.SMembers(key2) assert.NoError(t, err) - expectedSet = map[api.Result[string]]struct{}{ - api.CreateStringResult("1"): {}, - api.CreateStringResult("3"): {}, - } - assert.True(t, reflect.DeepEqual(expectedSet, res8)) + assert.Equal(suite.T(), map[string]struct{}{"1": {}, "3": {}}, res8) // attempt to move from a non-existing key res9, err := client.SMove(nonExistingKey, key1, "4") @@ -2234,11 +2186,7 @@ func (suite *GlideTestSuite) TestSMove() { res10, err := client.SMembers(key1) assert.NoError(t, err) - expectedSet = map[api.Result[string]]struct{}{ - api.CreateStringResult("2"): {}, - api.CreateStringResult("3"): {}, - } - assert.True(t, reflect.DeepEqual(expectedSet, res10)) + assert.Equal(suite.T(), map[string]struct{}{"2": {}, "3": {}}, res10) // move to a new set res11, err := client.SMove(key1, key3, "2") @@ -2247,13 +2195,11 @@ func (suite *GlideTestSuite) TestSMove() { res12, err := client.SMembers(key1) assert.NoError(t, err) - assert.Len(t, res12, 1) - assert.Contains(t, res12, api.CreateStringResult("3")) + assert.Equal(suite.T(), map[string]struct{}{"3": {}}, res12) res13, err := client.SMembers(key3) assert.NoError(t, err) - assert.Len(t, res13, 1) - assert.Contains(t, res13, api.CreateStringResult("2")) + assert.Equal(suite.T(), map[string]struct{}{"2": {}}, res13) // attempt to move a missing element res14, err := client.SMove(key1, key3, "42") @@ -2262,13 +2208,11 @@ func (suite *GlideTestSuite) TestSMove() { res12, err = client.SMembers(key1) assert.NoError(t, err) - assert.Len(t, res12, 1) - assert.Contains(t, res12, api.CreateStringResult("3")) + assert.Equal(suite.T(), map[string]struct{}{"3": {}}, res12) res13, err = client.SMembers(key3) assert.NoError(t, err) - assert.Len(t, res13, 1) - assert.Contains(t, res13, api.CreateStringResult("2")) + assert.Equal(suite.T(), map[string]struct{}{"2": {}}, res13) // moving missing element to missing key res15, err := client.SMove(key1, nonExistingKey, "42") @@ -2277,8 +2221,7 @@ func (suite *GlideTestSuite) TestSMove() { res12, err = client.SMembers(key1) assert.NoError(t, err) - assert.Len(t, res12, 1) - assert.Contains(t, res12, api.CreateStringResult("3")) + assert.Equal(suite.T(), map[string]struct{}{"3": {}}, res12) // key exists but is not contain a set _, err = client.Set(stringKey, "value") @@ -2774,11 +2717,11 @@ func (suite *GlideTestSuite) TestLMPopAndLMPopCount() { res1, err := client.LMPop([]string{key1}, api.Left) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res1) + assert.Nil(suite.T(), res1) res2, err := client.LMPopCount([]string{key1}, api.Left, int64(1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res2) + assert.Nil(suite.T(), res2) res3, err := client.LPush(key1, []string{"one", "two", "three", "four", "five"}) assert.Nil(suite.T(), err) @@ -2791,7 +2734,7 @@ func (suite *GlideTestSuite) TestLMPopAndLMPopCount() { assert.Nil(suite.T(), err) assert.Equal( suite.T(), - map[api.Result[string]][]api.Result[string]{api.CreateStringResult(key1): {api.CreateStringResult("five")}}, + map[string][]string{key1: {"five"}}, res5, ) @@ -2799,8 +2742,8 @@ func (suite *GlideTestSuite) TestLMPopAndLMPopCount() { assert.Nil(suite.T(), err) assert.Equal( suite.T(), - map[api.Result[string]][]api.Result[string]{ - api.CreateStringResult(key2): {api.CreateStringResult("one"), api.CreateStringResult("two")}, + map[string][]string{ + key2: {"one", "two"}, }, res6, ) @@ -2808,12 +2751,12 @@ func (suite *GlideTestSuite) TestLMPopAndLMPopCount() { suite.verifyOK(client.Set(key3, "value")) res7, err := client.LMPop([]string{key3}, api.Left) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res7) + assert.Nil(suite.T(), res7) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) res8, err := client.LMPop([]string{key3}, "Invalid") - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res8) + assert.Nil(suite.T(), res8) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -2830,11 +2773,11 @@ func (suite *GlideTestSuite) TestBLMPopAndBLMPopCount() { res1, err := client.BLMPop([]string{key1}, api.Left, float64(0.1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res1) + assert.Nil(suite.T(), res1) res2, err := client.BLMPopCount([]string{key1}, api.Left, int64(1), float64(0.1)) assert.Nil(suite.T(), err) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res2) + assert.Nil(suite.T(), res2) res3, err := client.LPush(key1, []string{"one", "two", "three", "four", "five"}) assert.Nil(suite.T(), err) @@ -2847,7 +2790,7 @@ func (suite *GlideTestSuite) TestBLMPopAndBLMPopCount() { assert.Nil(suite.T(), err) assert.Equal( suite.T(), - map[api.Result[string]][]api.Result[string]{api.CreateStringResult(key1): {api.CreateStringResult("five")}}, + map[string][]string{key1: {"five"}}, res5, ) @@ -2855,8 +2798,8 @@ func (suite *GlideTestSuite) TestBLMPopAndBLMPopCount() { assert.Nil(suite.T(), err) assert.Equal( suite.T(), - map[api.Result[string]][]api.Result[string]{ - api.CreateStringResult(key2): {api.CreateStringResult("one"), api.CreateStringResult("two")}, + map[string][]string{ + key2: {"one", "two"}, }, res6, ) @@ -2864,7 +2807,7 @@ func (suite *GlideTestSuite) TestBLMPopAndBLMPopCount() { suite.verifyOK(client.Set(key3, "value")) res7, err := client.BLMPop([]string{key3}, api.Left, float64(0.1)) - assert.Equal(suite.T(), (map[api.Result[string]][]api.Result[string])(nil), res7) + assert.Nil(suite.T(), res7) assert.NotNil(suite.T(), err) assert.IsType(suite.T(), &api.RequestError{}, err) }) @@ -4662,14 +4605,11 @@ func (suite *GlideTestSuite) TestZPopMin() { res2, err := client.ZPopMin(key1) assert.Nil(suite.T(), err) - assert.Len(suite.T(), res2, 1) - assert.Equal(suite.T(), float64(1.0), res2[api.CreateStringResult("one")].Value()) + assert.Equal(suite.T(), map[string]float64{"one": float64(1)}, res2) res3, err := client.ZPopMinWithCount(key1, 2) assert.Nil(suite.T(), err) - assert.Len(suite.T(), res3, 2) - assert.Equal(suite.T(), float64(2.0), res3[api.CreateStringResult("two")].Value()) - assert.Equal(suite.T(), float64(3.0), res3[api.CreateStringResult("three")].Value()) + assert.Equal(suite.T(), map[string]float64{"two": float64(2), "three": float64(3)}, res3) // non sorted set key _, err = client.Set(key2, "test") @@ -4696,14 +4636,11 @@ func (suite *GlideTestSuite) TestZPopMax() { res2, err := client.ZPopMax(key1) assert.Nil(suite.T(), err) - assert.Len(suite.T(), res2, 1) - assert.Equal(suite.T(), float64(3.0), res2[api.CreateStringResult("three")].Value()) + assert.Equal(suite.T(), map[string]float64{"three": float64(3)}, res2) res3, err := client.ZPopMaxWithCount(key1, 2) assert.Nil(suite.T(), err) - assert.Len(suite.T(), res3, 2) - assert.Equal(suite.T(), float64(2.0), res3[api.CreateStringResult("two")].Value()) - assert.Equal(suite.T(), float64(1.0), res3[api.CreateStringResult("one")].Value()) + assert.Equal(suite.T(), map[string]float64{"two": float64(2), "one": float64(1)}, res3) // non sorted set key _, err = client.Set(key2, "test") @@ -4866,18 +4803,18 @@ func (suite *GlideTestSuite) TestZRangeWithScores() { assert.NoError(t, err) // index [0:1] res, err := client.ZRangeWithScores(key, options.NewRangeByIndexQuery(0, 1)) - expected := map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("a"): api.CreateFloat64Result(1.0), - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), + expected := map[string]float64{ + "a": float64(1.0), + "b": float64(2.0), } assert.NoError(t, err) assert.Equal(t, expected, res) // index [0:-1] (all) res, err = client.ZRangeWithScores(key, options.NewRangeByIndexQuery(0, -1)) - expected = map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("a"): api.CreateFloat64Result(1.0), - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), - api.CreateStringResult("c"): api.CreateFloat64Result(3.0), + expected = map[string]float64{ + "a": float64(1.0), + "b": float64(2.0), + "c": float64(3.0), } assert.NoError(t, err) assert.Equal(t, expected, res) @@ -4890,10 +4827,10 @@ func (suite *GlideTestSuite) TestZRangeWithScores() { options.NewInfiniteScoreBoundary(options.NegativeInfinity), options.NewScoreBoundary(3, true)) res, err = client.ZRangeWithScores(key, query) - expected = map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("a"): api.CreateFloat64Result(1.0), - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), - api.CreateStringResult("c"): api.CreateFloat64Result(3.0), + expected = map[string]float64{ + "a": float64(1.0), + "b": float64(2.0), + "c": float64(3.0), } assert.NoError(t, err) assert.Equal(t, expected, res) @@ -4902,9 +4839,9 @@ func (suite *GlideTestSuite) TestZRangeWithScores() { options.NewInfiniteScoreBoundary(options.NegativeInfinity), options.NewScoreBoundary(3, false)) res, err = client.ZRangeWithScores(key, query) - expected = map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("a"): api.CreateFloat64Result(1.0), - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), + expected = map[string]float64{ + "a": float64(1.0), + "b": float64(2.0), } assert.NoError(t, err) assert.Equal(t, expected, res) @@ -4914,9 +4851,9 @@ func (suite *GlideTestSuite) TestZRangeWithScores() { options.NewInfiniteScoreBoundary(options.NegativeInfinity)). SetReverse() res, err = client.ZRangeWithScores(key, query) - expected = map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), - api.CreateStringResult("a"): api.CreateFloat64Result(1.0), + expected = map[string]float64{ + "b": float64(2.0), + "a": float64(1.0), } assert.NoError(t, err) assert.Equal(t, expected, res) @@ -4926,9 +4863,9 @@ func (suite *GlideTestSuite) TestZRangeWithScores() { options.NewInfiniteScoreBoundary(options.PositiveInfinity)). SetLimit(1, 2) res, err = client.ZRangeWithScores(key, query) - expected = map[api.Result[string]]api.Result[float64]{ - api.CreateStringResult("b"): api.CreateFloat64Result(2.0), - api.CreateStringResult("c"): api.CreateFloat64Result(3.0), + expected = map[string]float64{ + "b": float64(2.0), + "c": float64(3.0), } assert.NoError(t, err) assert.Equal(t, expected, res) @@ -6296,12 +6233,9 @@ func (suite *GlideTestSuite) TestObjectIdleTime() { "maxmemory-policy": "noeviction", } suite.verifyOK(defaultClient.ConfigSet(keyValueMap)) - key1 := api.CreateStringResult("maxmemory-policy") - value1 := api.CreateStringResult("noeviction") - resultConfigMap := map[api.Result[string]]api.Result[string]{key1: value1} resultConfig, err := defaultClient.ConfigGet([]string{"maxmemory-policy"}) assert.Nil(t, err, "Failed to get configuration") - assert.Equal(t, resultConfigMap, resultConfig, "Configuration mismatch for maxmemory-policy") + assert.Equal(t, keyValueMap, resultConfig, "Configuration mismatch for maxmemory-policy") resultGet, err := defaultClient.Get(key) assert.Nil(t, err) assert.Equal(t, value, resultGet.Value()) @@ -6338,12 +6272,9 @@ func (suite *GlideTestSuite) TestObjectFreq() { "maxmemory-policy": "volatile-lfu", } suite.verifyOK(defaultClient.ConfigSet(keyValueMap)) - key1 := api.CreateStringResult("maxmemory-policy") - value1 := api.CreateStringResult("volatile-lfu") - resultConfigMap := map[api.Result[string]]api.Result[string]{key1: value1} resultConfig, err := defaultClient.ConfigGet([]string{"maxmemory-policy"}) assert.Nil(t, err, "Failed to get configuration") - assert.Equal(t, resultConfigMap, resultConfig, "Configuration mismatch for maxmemory-policy") + assert.Equal(t, keyValueMap, resultConfig, "Configuration mismatch for maxmemory-policy") sleepSec := int64(5) time.Sleep(time.Duration(sleepSec) * time.Second) resultGet, err := defaultClient.Get(key) diff --git a/go/integTest/standalone_commands_test.go b/go/integTest/standalone_commands_test.go index 3c298f1ee6..2d4a0ec31c 100644 --- a/go/integTest/standalone_commands_test.go +++ b/go/integTest/standalone_commands_test.go @@ -180,11 +180,7 @@ func (suite *GlideTestSuite) TestConfigSetAndGet_multipleArgs() { suite.T().Skip("This feature is added in version 7") } configMap := map[string]string{"timeout": "1000", "maxmemory": "1GB"} - key1 := api.CreateStringResult("timeout") - value1 := api.CreateStringResult("1000") - key2 := api.CreateStringResult("maxmemory") - value2 := api.CreateStringResult("1073741824") - resultConfigMap := map[api.Result[string]]api.Result[string]{key1: value1, key2: value2} + resultConfigMap := map[string]string{"timeout": "1000", "maxmemory": "1073741824"} suite.verifyOK(client.ConfigSet(configMap)) result2, err := client.ConfigGet([]string{"timeout", "maxmemory"}) @@ -217,7 +213,7 @@ func (suite *GlideTestSuite) TestConfigSetAndGet_invalidArgs() { assert.IsType(suite.T(), &api.RequestError{}, err) result2, err := client.ConfigGet([]string{"time"}) - assert.Equal(suite.T(), map[api.Result[string]]api.Result[string]{}, result2) + assert.Equal(suite.T(), map[string]string{}, result2) assert.Nil(suite.T(), err) } From 4050baf0a296deb2f46815f866ce34a067fd3955 Mon Sep 17 00:00:00 2001 From: prateek-kumar-improving Date: Mon, 20 Jan 2025 16:27:27 -0800 Subject: [PATCH 5/5] Go xack command new (#2982) * Go: Add XAck command Signed-off-by: Prateek Kumar --- go/api/base_client.go | 31 ++++++++++++++++++++++++++++ go/api/stream_commands.go | 2 ++ go/integTest/shared_commands_test.go | 17 ++++++++------- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/go/api/base_client.go b/go/api/base_client.go index c0a79dfdac..b05528fbcb 100644 --- a/go/api/base_client.go +++ b/go/api/base_client.go @@ -2938,3 +2938,34 @@ func (client *baseClient) XGroupDelConsumer( } return handleIntResponse(result) } + +// Returns the number of messages that were successfully acknowledged by the consumer group member +// of a stream. This command should be called on a pending message so that such message does not +// get processed again. +// +// See [valkey.io] for details. +// +// Parameters: +// +// key - The key of the stream. +// group - he consumer group name. +// ids - Stream entry IDs to acknowledge and purge messages. +// +// Return value: +// +// The number of messages that were successfully acknowledged. +// +// Example: +// +// // Assuming streamId1 and streamId2 already exist. +// xackResult, err := client.XAck("key", "groupName", []string{"streamId1", "streamId2"}) +// fmt.Println(xackResult) // 2 +// +// [valkey.io]: https://valkey.io/commands/xack/ +func (client *baseClient) XAck(key string, group string, ids []string) (int64, error) { + result, err := client.executeCommand(C.XAck, append([]string{key, group}, ids...)) + if err != nil { + return defaultIntResponse, err + } + return handleIntResponse(result) +} diff --git a/go/api/stream_commands.go b/go/api/stream_commands.go index b5febb245d..c5c62e8a13 100644 --- a/go/api/stream_commands.go +++ b/go/api/stream_commands.go @@ -156,4 +156,6 @@ type StreamCommands interface { XGroupCreateConsumer(key string, group string, consumer string) (bool, error) XGroupDelConsumer(key string, group string, consumer string) (int64, error) + + XAck(key string, group string, ids []string) (int64, error) } diff --git a/go/integTest/shared_commands_test.go b/go/integTest/shared_commands_test.go index cba42181b0..adc95558a0 100644 --- a/go/integTest/shared_commands_test.go +++ b/go/integTest/shared_commands_test.go @@ -6498,28 +6498,29 @@ func (suite *GlideTestSuite) TestXGroupStreamCommands() { assert.NotNil(suite.T(), streamId3) // xack that streamid1 and streamid2 have been processed - command := []string{"XAck", key, groupName, streamId1.Value(), streamId2.Value()} - sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + xackResult, err := client.XAck(key, groupName, []string{streamId1.Value(), streamId2.Value()}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(2), xackResult) // Delete the consumer group and expect 0 pending messages respInt64, err = client.XGroupDelConsumer(key, groupName, consumerName) assert.NoError(suite.T(), err) assert.Equal(suite.T(), int64(0), respInt64) - // TODO: Use XAck when it is added to the Go client // xack streamid_1, and streamid_2 already received returns 0L - command = []string{"XAck", key, groupName, streamId1.Value(), streamId2.Value()} - sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + xackResult, err = client.XAck(key, groupName, []string{streamId1.Value(), streamId2.Value()}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(0), xackResult) // Consume the last message with the previously deleted consumer (creates the consumer anew) resp, err = client.XReadGroup(groupName, consumerName, map[string]string{key: ">"}) assert.NoError(suite.T(), err) assert.Equal(suite.T(), 1, len(resp[key])) - // TODO: Use XAck when it is added to the Go client // Use non existent group, so xack streamid_3 returns 0 - command = []string{"XAck", key, "non-existent-group", streamId3.Value()} - sendWithCustomCommand(suite, client, command, "Can't send XACK as a custom command") + xackResult, err = client.XAck(key, "non-existent-group", []string{streamId3.Value()}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), int64(0), xackResult) // Delete the consumer group and expect 1 pending message respInt64, err = client.XGroupDelConsumer(key, groupName, consumerName)