Add retry logic of connection lifetime to cluster client and sentinel client#833
Conversation
|
Wow. You are lightning fast, but we still need some test cases for this. |
|
@rueian Sure, I'll add the tests. I’m not familiar to cluster and sentinel client, so I wanted to check whether my understanding is correct about what you said. |
|
Yes, I think you are on the right track. |
db71c0d to
34ba5cf
Compare
e2204df to
232c933
Compare
232c933 to
3c7632f
Compare
2238fd7 to
4f57123
Compare
| ncc := c.redirectOrNew(addr, cc, cmd.Slot(), mode) | ||
| resp = ncc.Do(ctx, cmd) | ||
| if resp.Error() == errConnExpired { | ||
| goto retry |
There was a problem hiding this comment.
Shouldn't this go back to L526?
| case RedirectAsk: | ||
| results := c.redirectOrNew(addr, cc, cmd.Slot(), mode).DoMulti(ctx, cmds.AskingCmd, cmd) | ||
| ncc := c.redirectOrNew(addr, cc, cmd.Slot(), mode) | ||
| results := c.doMulti(ctx, ncc, cmds.AskingCmd, cmd) |
There was a problem hiding this comment.
ASKING can't be handled this way. It must be sent in every retry.
There was a problem hiding this comment.
@rueian Does it mean that ASKING needs at head of cmds when retrying due to errConnExpired
There was a problem hiding this comment.
Yes, ASKING is only effective in the same connection and applied only to the next command; therefore, we need to re-send ASKING before the target cmd if errConnExpired happens.
There was a problem hiding this comment.
I see. I will also fix askingMulti and askingMultiCache as same.
| if i > 0 && commands[i-1] == cmds.AskingCmd { | ||
| ml = commands[i-1:] | ||
| } else { | ||
| ml = commands[i:] |
There was a problem hiding this comment.
This reminds me that we need to handle the MULTI EXEC pattern correctly: If errConnExpired occurs during the MULTI EXEC, we should retry the entire MULTI EXEC block. This applies to the single client as well, which we overlooked in the previous PR.
There was a problem hiding this comment.
Yes, the draft looks good to me.
There was a problem hiding this comment.
I missed response of Multi command of test data.
I'm writing tests for askingMulti() but I'm not sure why multi has the following commands when calling that method. Any idea?
// Call for unit testing
multi := []Completed{
client.B().Get().Key("1{t}").Build(),
client.B().Multi().Build(),
client.B().Incr().Key("2{t}").Build(),
client.B().Incr().Key("3{t}").Build(),
client.B().Exec().Build(),
client.B().Get().Key("4{t}").Build(),
}
resps := client.DoMulti(context.Background(), multi...)
// multi in askingMulti(). I don't know why there is no [GET 2{t}] [Get 3{t}].
[ASKING]
[GET 1{t}]
[ASKING]
[MULTI]
[EXEC]
[ASKING]
[GET 4{t}]
| var ml []Completed | ||
| recover: | ||
| ml = ml[:0] | ||
| for i, resp := range resps.s { |
There was a problem hiding this comment.
Here, we can advance the i by 6 in every iteration and only check the Error of the ExecCmd.
|
Thanks @terut! |
|
@rueian Thank you for great help for couple of months 😄 |
This is follow-up PR regarding #727 .
See #727 (comment).