diff --git a/server/schedule/operator/builder.go b/server/schedule/operator/builder.go index 2d40a711d58..c5a7efb6dd6 100644 --- a/server/schedule/operator/builder.go +++ b/server/schedule/operator/builder.go @@ -57,7 +57,6 @@ type Builder struct { skipOriginJointStateCheck bool // build flags - allowDemote bool useJointConsensus bool lightWeight bool forceTargetLeader bool @@ -147,7 +146,6 @@ func NewBuilder(desc string, cluster opt.Cluster, region *core.RegionInfo, opts b.unhealthyPeers = unhealthyPeers b.originLeaderStoreID = originLeaderStoreID b.targetPeers = originPeers.Copy() - b.allowDemote = supportJointConsensus b.useJointConsensus = supportJointConsensus && cluster.GetOpts().IsUseJointConsensus() b.err = err return b @@ -354,7 +352,7 @@ func (b *Builder) prepareBuild() (string, error) { } // Diff `originPeers` and `targetPeers` to initialize `toAdd`, `toRemove`, `toPromote`, `toDemote`. - // Note: Use `toDemote` only when `allowDemote` is true. Otherwise use `toAdd`, `toRemove` instead. + // Note: Use `toDemote` only when `useJointConsensus` is true. Otherwise use `toAdd`, `toRemove` instead. for _, o := range b.originPeers { n := b.targetPeers[o.GetStoreId()] if n == nil { @@ -372,27 +370,25 @@ func (b *Builder) prepareBuild() (string, error) { } } - if core.IsLearner(o) { - if !core.IsLearner(n) { - // learner -> voter - b.toPromote.Set(n) - } - } else { - if core.IsLearner(n) { - // voter -> learner - if b.allowDemote { - b.toDemote.Set(n) - } else { - b.toRemove.Set(o) - // Need to add `b.toAdd.Set(n)` in the later targetPeers loop - } + isOriginPeerLearner := core.IsLearner(o) + isTargetPeerLearner := core.IsLearner(n) + if isOriginPeerLearner && !isTargetPeerLearner { + // learner -> voter + b.toPromote.Set(n) + } else if !isOriginPeerLearner && isTargetPeerLearner { + // voter -> learner + if b.useJointConsensus { + b.toDemote.Set(n) + } else { + b.toRemove.Set(o) + // the targetPeers loop below will add `b.toAdd.Set(n)` } } } for _, n := range b.targetPeers { // old peer not exists, or target is learner while old one is voter. o := b.originPeers[n.GetStoreId()] - if o == nil || (!b.allowDemote && !core.IsLearner(o) && core.IsLearner(n)) { + if o == nil || (!b.useJointConsensus && !core.IsLearner(o) && core.IsLearner(n)) { if n.GetId() == 0 { // Allocate peer ID if need. id, err := b.cluster.AllocID() @@ -424,8 +420,8 @@ func (b *Builder) prepareBuild() (string, error) { } } - if len(b.toAdd)+len(b.toRemove)+len(b.toPromote)+len(b.toDemote) <= 1 { - // If only one peer changed, joint consensus is not used. + if len(b.toAdd)+len(b.toRemove)+len(b.toPromote) <= 1 && len(b.toDemote) == 0 { + // if only one peer changed and the change type is not demote, joint consensus is not used b.useJointConsensus = false } @@ -607,9 +603,6 @@ func (b *Builder) buildStepsWithoutJointConsensus(kind OpKind) (OpKind, error) { b.execTransferLeader(plan.leaderBeforeRemove) kind |= OpLeader } - if plan.demote != nil { - b.execDemoteFollower(plan.demote) - } if plan.remove != nil { b.execRemovePeer(plan.remove) kind |= OpRegion @@ -643,12 +636,6 @@ func (b *Builder) execPromoteLearner(peer *metapb.Peer) { delete(b.toPromote, peer.GetStoreId()) } -func (b *Builder) execDemoteFollower(peer *metapb.Peer) { - b.steps = append(b.steps, DemoteFollower{ToStore: peer.GetStoreId(), PeerID: peer.GetId()}) - b.currentPeers.Set(peer) - delete(b.toDemote, peer.GetStoreId()) -} - func (b *Builder) execAddPeer(peer *metapb.Peer) { if b.lightWeight { b.steps = append(b.steps, AddLearner{ToStore: peer.GetStoreId(), PeerID: peer.GetId(), IsLightWeight: b.lightWeight}) @@ -676,6 +663,17 @@ func (b *Builder) execRemovePeer(peer *metapb.Peer) { } func (b *Builder) execChangePeerV2(needEnter bool, needTransferLeader bool) { + if len(b.toPromote)+len(b.toDemote) == 0 { + // No need to add empty enter / leave joint consensus step if no peer in `toPromote` and `toDemote` + + // Transfer Leader + if needTransferLeader && b.originLeaderStoreID != b.targetLeaderStoreID { + b.execTransferLeader(b.targetLeaderStoreID) + } + + return + } + // Enter step := ChangePeerV2Enter{ PromoteLearners: make([]PromoteLearner, 0, len(b.toPromote)), @@ -699,12 +697,16 @@ func (b *Builder) execChangePeerV2(needEnter bool, needTransferLeader bool) { if needEnter { b.steps = append(b.steps, step) } + // Transfer Leader if needTransferLeader && b.originLeaderStoreID != b.targetLeaderStoreID { b.execTransferLeader(b.targetLeaderStoreID) } - // Leave - b.steps = append(b.steps, ChangePeerV2Leave(step)) + + // TiKV will handle leave step if only single peer change in promote and demote when enter step is bypassed + if !(needEnter && len(step.PromoteLearners)+len(step.DemoteVoters) == 1) { + b.steps = append(b.steps, ChangePeerV2Leave(step)) + } } // check if the peer is allowed to become the leader. diff --git a/server/schedule/operator/builder_test.go b/server/schedule/operator/builder_test.go index c6b29c918b0..f79aff8d68f 100644 --- a/server/schedule/operator/builder_test.go +++ b/server/schedule/operator/builder_test.go @@ -149,7 +149,6 @@ func (s *testBuilderSuite) TestPrepareBuild(c *C) { 4: {StoreId: 4, Id: 14}, 5: {StoreId: 5, Role: metapb.PeerRole_Learner}, }) - builder.allowDemote = false builder.useJointConsensus = false _, err = builder.prepareBuild() c.Assert(err, IsNil) @@ -169,7 +168,7 @@ func (s *testBuilderSuite) TestPrepareBuild(c *C) { func (s *testBuilderSuite) TestBuild(c *C) { type testCase struct { - allowDemote bool + name string useJointConsensus bool originPeers []*metapb.Peer // first is leader targetPeers []*metapb.Peer // first is leader @@ -177,36 +176,41 @@ func (s *testBuilderSuite) TestBuild(c *C) { steps []OpStep // empty means error } cases := []testCase{ - { // empty step - false, false, + { + "(disable JointConcensus) empty step", + false, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, 0, []OpStep{}, }, - { // empty step - true, true, + { + "(enable JointConcensus) empty step", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, 0, []OpStep{}, }, - { // no valid leader - false, false, + { + "(disable JointConcensus) no valid leader", + false, []*metapb.Peer{{Id: 1, StoreId: 1}}, []*metapb.Peer{{Id: 10, StoreId: 10}}, 0, []OpStep{}, }, - { // no valid leader - true, true, + { + "(enable JointConcensus) no valid leader", + true, []*metapb.Peer{{Id: 1, StoreId: 1}}, []*metapb.Peer{{Id: 10, StoreId: 10}}, 0, []OpStep{}, }, - { // promote learner - false, false, + { + "(disable JointConcensus) promote 1 learner and transfer leader", + false, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 2, StoreId: 2}, {Id: 1, StoreId: 1}}, OpLeader, @@ -215,8 +219,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { TransferLeader{FromStore: 1, ToStore: 2}, }, }, - { // promote learner - true, true, + { + "(enable JointConcensus) promote 1 learner and transfer leader", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 2, StoreId: 2}, {Id: 1, StoreId: 1}}, OpLeader, @@ -225,8 +230,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { TransferLeader{FromStore: 1, ToStore: 2}, }, }, - { // not use joint consensus: prefer replace - false, false, + { + "(disable JointConcensus) prefer replace", + false, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{StoreId: 4}, {StoreId: 5, Role: metapb.PeerRole_Learner}}, OpLeader | OpRegion, @@ -240,8 +246,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 1}, }, }, - { // use joint consensus: transfer leader in joint state - true, true, + { + "(enable JointConcensus) transfer leader in joint state", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{StoreId: 4}, {StoreId: 5, Role: metapb.PeerRole_Learner}}, OpLeader | OpRegion, @@ -262,8 +269,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 3}, }, }, - { // not use joint consensus: transfer leader before remove leader - false, false, + { + "(disable JointConcensus) transfer leader before remove leader", + false, []*metapb.Peer{{Id: 1, StoreId: 1}}, []*metapb.Peer{{StoreId: 2}}, OpLeader | OpRegion, @@ -274,8 +282,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 1}, }, }, - { // use joint consensus: transfer leader in joint state - true, true, + { + "(enable JointConcensus) transfer leader in joint state", + true, []*metapb.Peer{{Id: 1, StoreId: 1}}, []*metapb.Peer{{StoreId: 2}}, OpLeader | OpRegion, @@ -293,8 +302,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 1}, }, }, - { // not use joint consensus: replace voter with learner - false, false, + { + "(disable JointConcensus) replace voter with learner", + false, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, OpRegion, @@ -303,18 +313,22 @@ func (s *testBuilderSuite) TestBuild(c *C) { AddLearner{ToStore: 2}, }, }, - { // use joint consensus: demote directly - true, true, + { + "(enable JointConcensus) demote 1 peer directly", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, []*metapb.Peer{{StoreId: 1}, {StoreId: 2, Role: metapb.PeerRole_Learner}}, 0, // Note that there is no OpRegion here []OpStep{ - DemoteFollower{ToStore: 2}, + ChangePeerV2Enter{ + PromoteLearners: []PromoteLearner{}, + DemoteVoters: []DemoteVoter{{ToStore: 2}}, + }, }, }, - // not use joint consensus - { // prefer replace with nearest peer - false, false, + { + "(disable JointConcensus) prefer replace with nearest peer", + false, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 6, StoreId: 6}, {Id: 8, StoreId: 8}}, // z1,h1 z1,h2 z2,h1 []*metapb.Peer{{StoreId: 9}, {StoreId: 7}, {StoreId: 10}}, @@ -338,20 +352,23 @@ func (s *testBuilderSuite) TestBuild(c *C) { TransferLeader{FromStore: 7, ToStore: 9}, }, }, - { // promote learner + demote voter - true, false, + { + "(disable JointConcensus) promote learner + demote voter + add learner", + false, []*metapb.Peer{{Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 2, StoreId: 2, Role: metapb.PeerRole_Voter}, {Id: 1, StoreId: 1, Role: metapb.PeerRole_Learner}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, OpLeader | OpRegion, []OpStep{ + AddLearner{ToStore: 3}, PromoteLearner{ToStore: 2}, TransferLeader{FromStore: 1, ToStore: 2}, - DemoteFollower{ToStore: 1}, - AddLearner{ToStore: 3}, + RemovePeer{FromStore: 1}, + AddLearner{ToStore: 1}, }, }, - { // add learner + promote learner + remove voter - false, false, + { + "(disable JointConcensus) add learner + promote learner + remove voter", + false, []*metapb.Peer{{Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 2, StoreId: 2, Role: metapb.PeerRole_Voter}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, OpLeader | OpRegion, @@ -362,8 +379,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 1}, }, }, - { // add voter + demote voter + remove learner. - true, false, + { + "(disable JointConcensus) add voter + demote voter + remove learner", + false, []*metapb.Peer{{Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, {Id: 1, StoreId: 1, Role: metapb.PeerRole_Learner}}, OpLeader | OpRegion, @@ -371,13 +389,14 @@ func (s *testBuilderSuite) TestBuild(c *C) { AddLearner{ToStore: 3}, PromoteLearner{ToStore: 3}, TransferLeader{FromStore: 1, ToStore: 3}, - DemoteFollower{ToStore: 1}, + RemovePeer{FromStore: 1}, + AddLearner{ToStore: 1}, RemovePeer{FromStore: 2}, }, }, - // use joint consensus - { // transfer leader before entering joint state - true, true, + { + "(enable JointConcensus) transfer leader before entering joint state", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 2, StoreId: 2}, {Id: 3, StoreId: 3}}, OpLeader | OpRegion, @@ -394,8 +413,9 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 1}, }, }, - { // transfer leader after leaving joint state - true, true, + { + "(enable JointConcensus) transfer leader after leaving joint state", + true, []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, []*metapb.Peer{{Id: 3, StoreId: 3}, {Id: 1, StoreId: 1}}, OpLeader | OpRegion, @@ -412,12 +432,77 @@ func (s *testBuilderSuite) TestBuild(c *C) { RemovePeer{FromStore: 2}, }, }, + { + "(enable JointConcensus) add 1 peer(learner) should always build steps without joint consensus state", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, + OpRegion, + []OpStep{ + AddLearner{ToStore: 3}, + }, + }, + { + "(enable JointConcensus) remove 1 peer(learner) should always build steps without joint consensus state", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}, {Id: 3, StoreId: 3}}, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 3, StoreId: 3}}, + OpRegion, + []OpStep{ + RemovePeer{FromStore: 2}, + }, + }, + { + "(enable JointConcensus) add 1+ learners should not enter joint consensus state", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}}, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, + OpRegion, + []OpStep{ + AddLearner{ToStore: 2}, + AddLearner{ToStore: 3}, + }, + }, + { + "(enable JointConcensus) remove 1+ learners should not enter joint consensus state", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, + []*metapb.Peer{{Id: 1, StoreId: 1}}, + OpRegion, + []OpStep{ + RemovePeer{FromStore: 2}, + RemovePeer{FromStore: 3}, + }, + }, + { + "(enable JointConcensus) demote 1 voter should enter JointConcensus, and TiKV will handle the leave step", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3}}, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, + 0, + []OpStep{ + ChangePeerV2Enter{ + PromoteLearners: []PromoteLearner{}, + DemoteVoters: []DemoteVoter{{ToStore: 3}}, + }, + }, + }, + { + "(enable JointConcensus) add 1 learner should goto to buildStepsWithoutJointConsensus", + true, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}}, + []*metapb.Peer{{Id: 1, StoreId: 1}, {Id: 2, StoreId: 2}, {Id: 3, StoreId: 3, Role: metapb.PeerRole_Learner}}, + OpRegion, + []OpStep{ + AddLearner{ToStore: 3}, + }, + }, } for _, tc := range cases { + c.Log(tc.name) region := core.NewRegionInfo(&metapb.Region{Id: 1, Peers: tc.originPeers}, tc.originPeers[0]) builder := NewBuilder("test", s.cluster, region) - builder.allowDemote = tc.allowDemote builder.useJointConsensus = tc.useJointConsensus m := make(map[uint64]*metapb.Peer) for _, p := range tc.targetPeers { @@ -445,8 +530,6 @@ func (s *testBuilderSuite) TestBuild(c *C) { c.Assert(step.ToStore, Equals, tc.steps[i].(AddLearner).ToStore) case PromoteLearner: c.Assert(step.ToStore, Equals, tc.steps[i].(PromoteLearner).ToStore) - case DemoteFollower: - c.Assert(step.ToStore, Equals, tc.steps[i].(DemoteFollower).ToStore) case ChangePeerV2Enter: c.Assert(len(step.PromoteLearners), Equals, len(tc.steps[i].(ChangePeerV2Enter).PromoteLearners)) c.Assert(len(step.DemoteVoters), Equals, len(tc.steps[i].(ChangePeerV2Enter).DemoteVoters)) diff --git a/server/schedule/operator/step.go b/server/schedule/operator/step.go index 42240296480..f8773cd41e1 100644 --- a/server/schedule/operator/step.go +++ b/server/schedule/operator/step.go @@ -361,47 +361,6 @@ func (sr SplitRegion) CheckSafety(region *core.RegionInfo) error { return nil } -// DemoteFollower is an OpStep that demotes a region follower peer to learner. -type DemoteFollower struct { - ToStore, PeerID uint64 -} - -func (df DemoteFollower) String() string { - return fmt.Sprintf("demote follower peer %v on store %v to learner", df.PeerID, df.ToStore) -} - -// ConfVerChanged returns the delta value for version increased by this step. -func (df DemoteFollower) ConfVerChanged(region *core.RegionInfo) uint64 { - peer := region.GetStoreLearner(df.ToStore) - return typeutil.BoolToUint64(peer.GetId() == df.PeerID) -} - -// IsFinish checks if current step is finished. -func (df DemoteFollower) IsFinish(region *core.RegionInfo) bool { - if peer := region.GetStoreLearner(df.ToStore); peer != nil { - if peer.GetId() != df.PeerID { - log.Warn("obtain unexpected peer", zap.String("expect", df.String()), zap.Uint64("obtain-learner", peer.GetId())) - } - return peer.GetId() == df.PeerID - } - return false -} - -// CheckSafety checks if the step meets the safety properties. -func (df DemoteFollower) CheckSafety(region *core.RegionInfo) error { - peer := region.GetStorePeer(df.ToStore) - if peer.GetId() != df.PeerID { - return errors.New("peer does not exist") - } - if peer.GetId() == region.GetLeader().GetId() { - return errors.New("cannot demote leader peer") - } - return nil -} - -// Influence calculates the store difference that current step makes. -func (df DemoteFollower) Influence(opInfluence OpInfluence, region *core.RegionInfo) {} - // DemoteVoter is very similar to DemoteFollower. But it allows Demote Leader. // Note: It is not an OpStep, only a sub step in ChangePeerV2Enter and ChangePeerV2Leave. type DemoteVoter struct { diff --git a/server/schedule/operator/step_test.go b/server/schedule/operator/step_test.go index 2f5b7f5a844..2ce796cab13 100644 --- a/server/schedule/operator/step_test.go +++ b/server/schedule/operator/step_test.go @@ -31,73 +31,6 @@ type testCase struct { CheckSafety Checker } -func (s *testStepSuite) TestDemoteFollower(c *C) { - df := DemoteFollower{ToStore: 2, PeerID: 2} - cases := []testCase{ - { // before step - []*metapb.Peer{ - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 2, StoreId: 2, Role: metapb.PeerRole_Voter}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 0, - false, - IsNil, - }, - { // after step - []*metapb.Peer{ - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 2, StoreId: 2, Role: metapb.PeerRole_Learner}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 1, - true, - IsNil, - }, - { // miss peer id - []*metapb.Peer{ - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 4, StoreId: 2, Role: metapb.PeerRole_Voter}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 0, - false, - NotNil, - }, - { // miss store id - []*metapb.Peer{ - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 2, StoreId: 4, Role: metapb.PeerRole_Voter}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 0, - false, - NotNil, - }, - { // miss peer id - []*metapb.Peer{ - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 4, StoreId: 2, Role: metapb.PeerRole_Learner}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 0, - false, - NotNil, - }, - { // demote leader - []*metapb.Peer{ - {Id: 2, StoreId: 2, Role: metapb.PeerRole_Voter}, - {Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter}, - {Id: 3, StoreId: 3, Role: metapb.PeerRole_Voter}, - }, - 0, - false, - NotNil, - }, - } - s.check(c, df, "demote follower peer 2 on store 2 to learner", cases) -} - func (s *testStepSuite) TestChangePeerV2Enter(c *C) { cpe := ChangePeerV2Enter{ PromoteLearners: []PromoteLearner{{PeerID: 3, ToStore: 3}, {PeerID: 4, ToStore: 4}}, diff --git a/server/schedule/operator_controller.go b/server/schedule/operator_controller.go index e8c6c4e4db6..5e3bd7624f2 100644 --- a/server/schedule/operator_controller.go +++ b/server/schedule/operator_controller.go @@ -196,7 +196,7 @@ func (oc *OperatorController) checkStaleOperator(op *operator.Operator, step ope func (oc *OperatorController) getNextPushOperatorTime(step operator.OpStep, now time.Time) time.Time { nextTime := slowNotifyInterval switch step.(type) { - case operator.TransferLeader, operator.PromoteLearner, operator.DemoteFollower, operator.ChangePeerV2Enter, operator.ChangePeerV2Leave: + case operator.TransferLeader, operator.PromoteLearner, operator.ChangePeerV2Enter, operator.ChangePeerV2Leave: nextTime = fastNotifyInterval } return now.Add(nextTime) @@ -659,8 +659,6 @@ func (oc *OperatorController) SendScheduleCommand(region *core.RegionInfo, step cmd = addLearnerNode(st.PeerID, st.ToStore) case operator.PromoteLearner: cmd = addNode(st.PeerID, st.ToStore) - case operator.DemoteFollower: - cmd = addLearnerNode(st.PeerID, st.ToStore) case operator.RemovePeer: cmd = &pdpb.RegionHeartbeatResponse{ ChangePeer: &pdpb.ChangePeer{