mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #11640 from ereslibre/fix-learner-promotion
Fix quorum calculation when promoting a learner member
This commit is contained in:
commit
8c1a820a10
@ -597,8 +597,8 @@ func (c *RaftCluster) IsReadyToRemoveVotingMember(id uint64) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *RaftCluster) IsReadyToPromoteMember(id uint64) bool {
|
func (c *RaftCluster) IsReadyToPromoteMember(id uint64) bool {
|
||||||
nmembers := 1
|
nmembers := 1 // We count the learner to be promoted for the future quorum
|
||||||
nstarted := 0
|
nstarted := 1 // and we also count it as started.
|
||||||
|
|
||||||
for _, member := range c.VotingMembers() {
|
for _, member := range c.VotingMembers() {
|
||||||
if member.IsStarted() {
|
if member.IsStarted() {
|
||||||
|
@ -857,3 +857,90 @@ func TestIsReadyToRemoveVotingMember(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsReadyToPromoteMember(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
members []*Member
|
||||||
|
promoteID uint64
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// 1/1 members ready, should succeed (quorum = 1, new quorum = 2)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMemberAsLearner(2, nil, "2", nil),
|
||||||
|
},
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 0/1 members ready, should fail (quorum = 1)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "", nil),
|
||||||
|
newTestMemberAsLearner(2, nil, "2", nil),
|
||||||
|
},
|
||||||
|
2,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 2/2 members ready, should succeed (quorum = 2)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMember(2, nil, "2", nil),
|
||||||
|
newTestMemberAsLearner(3, nil, "3", nil),
|
||||||
|
},
|
||||||
|
3,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 1/2 members ready, should succeed (quorum = 2)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMember(2, nil, "", nil),
|
||||||
|
newTestMemberAsLearner(3, nil, "3", nil),
|
||||||
|
},
|
||||||
|
3,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 1/3 members ready, should fail (quorum = 2)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMember(2, nil, "", nil),
|
||||||
|
newTestMember(3, nil, "", nil),
|
||||||
|
newTestMemberAsLearner(4, nil, "4", nil),
|
||||||
|
},
|
||||||
|
4,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 2/3 members ready, should succeed (quorum = 2, new quorum = 3)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMember(2, nil, "2", nil),
|
||||||
|
newTestMember(3, nil, "", nil),
|
||||||
|
newTestMemberAsLearner(4, nil, "4", nil),
|
||||||
|
},
|
||||||
|
4,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 2/4 members ready, should succeed (quorum = 3)
|
||||||
|
[]*Member{
|
||||||
|
newTestMember(1, nil, "1", nil),
|
||||||
|
newTestMember(2, nil, "2", nil),
|
||||||
|
newTestMember(3, nil, "", nil),
|
||||||
|
newTestMember(4, nil, "", nil),
|
||||||
|
newTestMemberAsLearner(5, nil, "5", nil),
|
||||||
|
},
|
||||||
|
5,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, tt := range tests {
|
||||||
|
c := newTestCluster(tt.members)
|
||||||
|
if got := c.IsReadyToPromoteMember(tt.promoteID); got != tt.want {
|
||||||
|
t.Errorf("%d: isReadyToPromoteMember returned %t, want %t", i, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user