-
Notifications
You must be signed in to change notification settings - Fork 183
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
panic
when we try to get the redis result as some specific datatype
#366
Comments
panic
when we try to get the result as some specific datatypepanic
when we try to get the redis result as some specific datatype
Hi @smit245, As you mentioned, using functions like |
I was also burned by this multiple times. Often, this happens in DoMulti calls where the order of the results is important. Testing doesn't help much because mocked rueidis is controlled by the programmer. It might return wrong result types that happen to match the expectations of the code you're testing. I think this should be changed to returning an error. It is a programming mistake, but it happens at runtime and causes outages in the worst case if panic is not recovered. At least with errors it allows code to continue to run and defers the problem to metrics/logs to notify the user about buggy behaviour. And it's simply not idiomatic. Library code should panic only in very rare cases. It makes sense to panic in constructors to terminate the application before it even launches. Standard library even does this and it's ok usually. But panicking later is bad practice in almost all cases. |
Hi @creker,
Could you provide more details on this? I thought the order of commands should not affect their response types.
That's true currently. So, I think we now have a chance to improve the rueidis mock by bounding commands with their response types in the mocked implementation, so that you will be more confident with code tested with mock. In general, I would recommend testing with a real redis, while rueidis mock is still useful when it is hard for you to do so for any reason.
Not everyone agrees on this. Someone who prefers fail-fast will claim deferring a programming mistake will often lead to an even larger problem. Yet, I understand that some people don't like this panic behavior. I also think It would be nice if the behavior is configurable. |
I've also run into issues with panics during development, where I wasn't sure what type method to use on RedisResult values. I do think the panic's shouldn't be too bad of a problem once you figure it out in development and I personally wouldn't rely on this proposal. type RedisResult struct {
err error
val RedisMessage
noPanic bool
} add a NP (No Panic) method to RedisResult that sets the noPanic value to true func (r RedisResult) NP() RedisResult {
r.noPanic = true
return r
} a handle panic method that can be put into any RedisResult method that panics func (r RedisResult) handlePanic(err error) error {
if e := recover(); e != nil {
err = e.(error)
}
return err
} Example of its potential usage in ToArray // ToArray delegates to RedisMessage.ToArray
func (r RedisResult) ToArray() (v []RedisMessage, err error) {
if r.err != nil {
err = r.err
} else {
v, err = r.val.ToArray()
}
if r.noPanic {
err = r.handlePanic(err)
}
return
} And then finally, in application code we can do this. This will ensure the error is recovered from the panic and returned in the err value values, err := c.Do(ctx, c.B().Mget().Key("k1", "k2").Build()).NP().ToArray() Does this seem like a workable solution to prevent panics while not having to break existing behavior with current users? It would be opt-in for anyone that wants to use the |
Hi @kevinxmorales, thank you for the proposal. But I think it will be better to use a global environment variable to toggle the behavior instead, since people may not want to change their code and wait for recompilation when it panics on production because of this. |
To summarize, we have three proposals now:
In addition, we can also enhance the rueidis mock to assert return types according to the cmds passed in. |
What about just adding new option to |
I thought about that too, but I realized that it also requires code changes to toggle the behavior if users know nothing about the option before being bitten. |
The 1st one is good because it is backward compatible and easily usable. |
|
Hi @knadh, Prefixing func MustBool() bool However, we still need errors to be returned here, such as redis errors and IO errors. Having a function with a func MustBool() (bool, error) |
After considering on this for several months, I now tend to adapt the original proposal: return an error instead of panic. The proposal indeed simplifies everything. |
Solved by #555 |
I am looking into this library to use it in one of my projects and i found that when we do
client.Do
operation and it returnsRedisResult
and when we useredisResult.AsBool()
this return bool value of the result or error but when i looked into the method i found that when result is not actually bool the program will panic as i found at message.go#615.I found this and i found it is a bad practice.
The method is already sending the error so we can easily return error why panic?
Is there any reason?
I also looked at the Command Response Cheatsheet but still, mistakes happen and for that program should not panic instead error should be returned and it will be handled by the library user and then he will find out that response of redis is not in the data type they wished for.
Please answer if it's a valid question
Otherwise i found this package amazing and loved the command builder you guys have provided also looking into other features
The text was updated successfully, but these errors were encountered: