Description
Expected Behavior
Using a method named Do
on a Pipeliner
object we expect to 'do' said Pipeliner instead of 'add new command'
Without reading the source, the impression, when seeing the prototype of the method and its name, is that it will produce a Cmd
interface representing the Pipeliner.
The alternative expected behavior would be that if no arguments are given,
Do
would return an error command.
This way the user knows he is misusing the Pipeliner
object.
Current Behavior
Currently if given no arguments it creates a nop command, adds it to the list of commands and returns that nop command.
If the user tried to use .Result()
on that command he will get an empty response.
Possible Solution
- Rename
Do
intoCreate
. TechnicallyDo
does nothing - If args is empty, create a new Cmd, use SetError on it and return it
Steps to Reproduce
p := redisClient.Pipeline()
cmd := redisClient.Exists(context.Background(), "someKey")
if err := p.Process(context.Background(), cmd); err != nil {
panic(err)
}
if _, err := p.Do(ctx).Result(); err != nil {
panic(err)
}
rsp, err := cmd.Result()
if err != nil {
panic(err)
}
Context (Environment)
A similar piece of code turned in production for many months and only discovered after a week of investigation.
None of the reviewers caught the issue during the review process.
Detailed Description
Possible Implementation
If renaming is too much of a pain:
func (c *Pipeline) Do(ctx context.Context, args ...interface{}) *Cmd {
cmd := NewCmd(ctx, args...)
if len(args) == 0 {
cmd.SetErr(errors.New(...)) //error that highlights miss-using of Pipeliners' `Do`
}
_ = c.Process(ctx, cmd)
return cmd
}