Skip to content

Commit

Permalink
added support for RANDOMKEY
Browse files Browse the repository at this point in the history
  • Loading branch information
karthick committed Aug 11, 2024
1 parent c25c000 commit 65ddeb8
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
7 changes: 7 additions & 0 deletions core/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,12 @@ var (
Arity: 3,
KeySpecs: KeySpecs{BeginIndex: 1},
}
randomKeyCmdMeta = DiceCmdMeta{
Name: "RANDOMKEY",
Info: "Return a random key",
Eval: evalRandomKey,
Arity: 1,
}
)

func init() {
Expand Down Expand Up @@ -570,4 +576,5 @@ func init() {
diceCmds["GETDEL"] = getDelCmdMeta
diceCmds["DECRBY"] = decrByCmdMeta
diceCmds["RENAME"] = renameCmdMeta
diceCmds["RANDOMKEY"] = randomKeyCmdMeta
}
11 changes: 11 additions & 0 deletions core/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,17 @@ func evalEXISTS(args []string) []byte {

return Encode(count, false)
}
func evalRandomKey(args []string) []byte {
if len(args) != 0 {
return Encode(errors.New("ERR wrong number of arguments for RANDOMKEY command"), false)
}

key := RandomKey()
if key == "" {
return RESP_NIL
}
return Encode(key, false)
}

func executeCommand(cmd *RedisCmd, c *Client) []byte {
diceCmd, ok := diceCmds[cmd.Cmd]
Expand Down
16 changes: 16 additions & 0 deletions core/store.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"math/rand"
"path"
"sync"
"time"
Expand Down Expand Up @@ -328,3 +329,18 @@ func delByPtr(ptr unsafe.Pointer) bool {
}
return false
}

func RandomKey() string {
if len(keypool) == 0 {
return ""
}
index := rand.Intn(len(keypool))
currentIndex := 0
for key := range keypool {
if currentIndex == index {
return key
}
currentIndex++
}
return ""
}
60 changes: 60 additions & 0 deletions tests/commands_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package tests

import (
"testing"

"gotest.tools/v3/assert"
)

func TestCommandRandomKey(t *testing.T) {
var randomKeyTestCases = []struct {
name string
inCmd []string
expected []interface{}
}{
{
name: "Try to get RandomKey with 0 keys in map",
inCmd: []string{"RANDOMKEY"},
expected: []interface{}{"(nil)"},
},
{
name: "Set a key and get a RandomKey",
inCmd: []string{"set Key hello", "RANDOMKEY"},
expected: []interface{}{"OK", "Key"},
},
{
name: "Set another two keys and check the RandomKey",
inCmd: []string{"set Key2 hello2", "set Key3 hello3", "RANDOMKEY"},
expected: []interface{}{"OK", "OK"},
},
}

conn := getLocalConnection()
defer conn.Close()

for _, tc := range randomKeyTestCases {
t.Run(tc.name, func(t *testing.T) {
var actual []interface{}
for _, cmd := range tc.inCmd {
result := fireCommand(conn, cmd)
actual = append(actual, result)
}

if tc.name == "Set another two keys and check the RandomKey" {
// Manually check if the last result is one of the expected keys
lastResult := actual[len(actual)-1]
expectedKeys := []string{"Key", "Key2", "Key3"}
found := false
for _, key := range expectedKeys {
if lastResult == key {
found = true
break
}
}
assert.Assert(t, found, "Expected one of %v, but got %v", expectedKeys, lastResult)
} else {
assert.DeepEqual(t, tc.expected, actual)
}
})
}
}

0 comments on commit 65ddeb8

Please sign in to comment.