From 0960371c07a81e5b061dbc84247869475df13fb0 Mon Sep 17 00:00:00 2001 From: xanish Date: Thu, 17 Oct 2024 01:34:08 +0530 Subject: [PATCH] Add best effort mechanism to return non-expired randomkey in 128 tries --- internal/eval/eval.go | 24 ++++++++++++++++++------ internal/eval/eval_test.go | 7 +++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/internal/eval/eval.go b/internal/eval/eval.go index 1b4dfe62c2..604e0c9acd 100644 --- a/internal/eval/eval.go +++ b/internal/eval/eval.go @@ -5147,13 +5147,25 @@ func evalRANDOMKEY(args []string, store *dstore.Store) *EvalResponse { } if len(availKeys) > 0 { - randKeyIdx, err := rand.Int(rand.Reader, big.NewInt(int64(len(availKeys)))) - if err != nil { - return &EvalResponse{Result: nil, - Error: errors.New(string(diceerrors.NewErrWithMessage("could not generate a random key seed")))} - } + maxIters := 128 + for range maxIters { + randKeyIdx, err := rand.Int(rand.Reader, big.NewInt(int64(len(availKeys)))) + if err != nil { + continue + } - return &EvalResponse{Result: availKeys[randKeyIdx.Uint64()], Error: nil} + randKey := availKeys[randKeyIdx.Uint64()] + keyObj := store.Get(randKey) + if keyObj == nil { + continue + } + + currTimeMs := uint64(utils.GetCurrentTime().UnixMilli()) + expireTimeMs, isExpirySet := dstore.GetExpiry(keyObj, store) + if (isExpirySet && expireTimeMs > currTimeMs) || !isExpirySet { + return &EvalResponse{Result: clientio.Encode(randKey, false), Error: nil} + } + } } return &EvalResponse{Result: clientio.RespNIL, Error: nil} diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 689707d53e..327c49b1a1 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -1166,11 +1166,14 @@ func testEvalRANDOMKEY(t *testing.T, store *dstore.Store) { results := make(map[string]int) for i := 0; i < 10000; i++ { result := evalRANDOMKEY([]string{}, store) - results[result.Result.(string)]++ + if res, ok := result.Result.([]byte); ok { + results[string(res)]++ + } } for key, _ := range data { - if results[key] == 0 { + returnedKey := clientio.Encode(key, false) + if results[string(returnedKey)] == 0 { t.Errorf("key %s was never returned", key) } }