Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Added support for GET option in SET command #322

Closed
wants to merge 0 commits into from

Conversation

yaten2302
Copy link

@yaten2302 yaten2302 commented Aug 15, 2024

Fixes #207

Copy link
Collaborator

@JyotinderSingh JyotinderSingh left a comment

Choose a reason for hiding this comment

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

Thanks for the changes @yaten2302, have left a few comments.

core/eval.go Outdated Show resolved Hide resolved
core/eval.go Outdated Show resolved Hide resolved
core/eval.go Outdated Show resolved Hide resolved
core/eval.go Outdated Show resolved Hide resolved
core/eval.go Outdated
Comment on lines 213 to 215
} else {
return RespNIL
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

You still need to Put() the key even if it did not previously exist when using the GET option.

refer: https://redis.io/docs/latest/commands/set/

core/eval.go Outdated
@@ -193,6 +197,23 @@ func evalSET(args []string) []byte {
}
case constants.KEEPTTL, constants.Keepttl:
keepttl = true
case "GET":
// Get the key from the hash table
obj := Get(key)
Copy link
Collaborator

Choose a reason for hiding this comment

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

An error is returned and SET aborted if the value stored at key is not a string.

refer: https://redis.io/docs/latest/commands/set/

Copy link
Author

Choose a reason for hiding this comment

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

@JyotinderSingh , I've a doubt, that by default dice stores everything as a string only, right? Then why this error is being shown?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The behavior should be correct from the implementation perspective. So we should do the check on our side.

Copy link
Author

Choose a reason for hiding this comment

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

Oh! Okay 👍
BTW @JyotinderSingh , I wanted to ask that could you please provide a sample test case like when the test is failing? like I've a doubt that how can I set the value to int or something else (anything other than string)?

If possible, may I give it a try please, which is causing this problem! (like if the value is not string and then it's creating a problem). Like, if anyone else is already working on it, then I can collaborate with them 🙏 ?

@@ -113,6 +113,11 @@ func TestSetWithOptions(t *testing.T) {
commands: []string{"SET k v XX EX 1", "GET k", "SLEEP 2", "GET k", "SET k v XX EX 1", "GET k"},
expected: []interface{}{"(nil)", "(nil)", "OK", "(nil)", "(nil)", "(nil)"},
},
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add test cases for the following:

  1. Validate that SET succeeds with GET option even if the key does not exist.
  2. Validate error is returned when using SET with GET option if the previously stored value was not a string.
  3. Validate previous value is returned when using SET with the GET option.

Copy link
Author

Choose a reason for hiding this comment

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

Sure, I'll add these test cases 👍

Copy link
Author

Choose a reason for hiding this comment

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

@JyotinderSingh , actually, I've some doubts:

  1. like for the 1st one, in redis it's given that if the key doesn't exists, then it should return (nil)?
    image

  2. Also, could you please guide that how can I validate that if the previous values was a string or not? Because dice stores everything as string, am I right? Like 2 will be stored as "2"?

  3. I've got the 3rd point. I'll add that 👍

Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Even though it returns nil, the key is still set in the background. You return nil since there was no existing value, however, the new value will still be set.
  2. Add the validation regardless.

Copy link
Contributor

@lucifercr07 lucifercr07 left a comment

Choose a reason for hiding this comment

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

I remember there were few comments had posted on last PR for the same issue, can you please mention if they've been fixed?

@AshwinKul28
Copy link
Contributor

Linter is still failing :( will look into it.

@yaten2302
Copy link
Author

yaten2302 commented Aug 16, 2024

@lucifercr07 , yes, I've made all the changes in the PR which were suggested previously, but I haven't made this change, because the tests were failing if I remove the else block.

@lucifercr07
Copy link
Contributor

@lucifercr07 , yes, I've made all the changes in the PR which were suggested previously, but I haven't made this change, because the tests were failing if I remove the else block.

Can you detail on why it's failing? Any reasons

@yaten2302
Copy link
Author

Sure @lucifercr07 , here is the error on removing the else blocks:

image

image

@lucifercr07
Copy link
Contributor

lucifercr07 commented Aug 16, 2024

Sure @lucifercr07 , here is the error on removing the else blocks:

We need to remove the else block but not the code inside it.

if XXoption {
				if obj == nil {
					return RespNIL
				} 
				
                                 Put(key, NewObj(value, exDurationMs, oType, oEnc))
			} else {
				if obj == nil {
					return Put(key, NewObj(value, exDurationMs, oType, oEnc))
				}
				
                                 return RespNIL
}

@yaten2302
Copy link
Author

@lucifercr07 , @JyotinderSingh , I've pushed some changes. could you please review those 👍
Also, @AshwinKul28 , could you please guide that is the linter failing due to some issues from my side? or it's something else?

@JyotinderSingh
Copy link
Collaborator

@lucifercr07 , @JyotinderSingh , I've pushed some changes. could you please review those 👍

Also, @AshwinKul28 , could you please guide that is the linter failing due to some issues from my side? or it's something else?

Lint checks are passing now since you merged with master.

core/eval.go Outdated
@@ -193,6 +197,23 @@ func evalSET(args []string) []byte {
}
case constants.KEEPTTL, constants.Keepttl:
keepttl = true
case "GET":
// Get the key from the hash table
obj := Get(key)
Copy link
Collaborator

Choose a reason for hiding this comment

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

The behavior should be correct from the implementation perspective. So we should do the check on our side.

@@ -113,6 +113,11 @@ func TestSetWithOptions(t *testing.T) {
commands: []string{"SET k v XX EX 1", "GET k", "SLEEP 2", "GET k", "SET k v XX EX 1", "GET k"},
expected: []interface{}{"(nil)", "(nil)", "OK", "(nil)", "(nil)", "(nil)"},
},
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Even though it returns nil, the key is still set in the background. You return nil since there was no existing value, however, the new value will still be set.
  2. Add the validation regardless.

core/eval.go Outdated
} else if nxOption {
//store.Put(key, store.NewObj(value, exDurationMs, oType, oEnc))
if obj == nil {
return Encode(obj.Value, false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this return RespNIL?
If key k doesn't exit and you fire SET k v NX GET the result will be (nil).

redis> SET k v NX GET
(nil)

Also, add a test for this once fixed.

core/eval.go Outdated
return Encode(obj.Value, false)
}

return RespNIL
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the object is not nil, you should return obj.Value.

redis> SET k v1
"OK"
redis> SET k v2 NX GET
"v1"

@JyotinderSingh
Copy link
Collaborator

Please rebase the PR, we just had a large change go in which might've introduced conflicts.

@arpitbbhayani
Copy link
Contributor

@yaten2302 can you rebase this? we would like to close this as soon as possible. Do you need any help?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for GET in SET command
5 participants