Repository: etcd-io/etcd
File: server/etcdserver/api/membership/cluster.go (Go)

Code before:
	}

	if id == c.localID {
		isLearner.Set(0)
	}

	if c.be != nil {
		m := c.members[id]
		if shouldApplyV3 {
			m.RaftAttributes.IsLearner = false
			c.updateMembershipMetric(id, true)
			c.be.MustSaveMemberToBackend(m)

			c.lg.Info(
				"promote member",
				zap.String("cluster-id", c.cid.String()),
				zap.String("local-member-id", c.localID.String()),
				zap.String("promoted-member-id", id.String()),
			)
		} else {
			// Workaround the issues which have already been affected by
			// https://github.com/etcd-io/etcd/issues/19557. The learner
			// promotion request had been applied to v3store, but not saved
			// to v2snapshot yet when in 3.5. Once upgrading to 3.6, the
			// patch here ensure the issue can be automatically fixed.
			if m != nil && m.IsLearner {
				m.RaftAttributes.IsLearner = false
				c.lg.Info("Forcibly apply member promotion request", zap.String("member", fmt.Sprintf("%+v", *m)))
				c.be.MustHackySaveMemberToBackend(m)
			} else {
				c.lg.Info(
					"ignore already promoted member",
					zap.String("cluster-id", c.cid.String()),
					zap.String("local-member-id", c.localID.String()),
				)
			}
		}
	} else {
		c.lg.Info(
			"ignore already promoted member due to backend being nil",
			zap.String("cluster-id", c.cid.String()),
			zap.String("local-member-id", c.localID.String()),
		)
	}
}

// SyncLearnerPromotionIfNeeded provides a workaround solution to fix the issues
// which have already been affected by https://github.com/etcd-io/etcd/issues/19557.
func (c *RaftCluster) SyncLearnerPromotionIfNeeded() {
	c.Lock()
	defer c.Unlock()

Review comment (suggestion):
Technically message `"ignore already promoted member"` should be different.


Code after:
	}

	if id == c.localID {
		isLearner.Set(0)
	}

	if c.be != nil {
		m := c.members[id]
		if shouldApplyV3 {
			m.RaftAttributes.IsLearner = false
			c.updateMembershipMetric(id, true)
			c.be.MustSaveMemberToBackend(m)

			c.lg.Info(
				"promote member",
				zap.String("cluster-id", c.cid.String()),
				zap.String("local-member-id", c.localID.String()),
				zap.String("promoted-member-id", id.String()),
			)
		} else {
			// Workaround the issues which have already been affected by
			// https://github.com/etcd-io/etcd/issues/19557. The learner
			// promotion request had been applied to v3store, but not saved
			// to v2snapshot yet when in 3.5. Once upgrading to 3.6, the
			// patch here ensure the issue can be automatically fixed.
			if m == nil {
				c.lg.Info(
					"Skipped forcibly promoting non-existent member in v3store",
					zap.String("cluster-id", c.cid.String()),
					zap.String("local-member-id", c.localID.String()),
					zap.String("promoted-member-id", id.String()),
				)
			} else if m.IsLearner {
				m.RaftAttributes.IsLearner = false
				c.lg.Info("Forcibly apply member promotion request in v3store", zap.String("member", fmt.Sprintf("%+v", *m)))
				c.be.MustHackySaveMemberToBackend(m)
			} else {
				c.lg.Info(
					"ignore already promoted member in v3store",
					zap.String("cluster-id", c.cid.String()),
					zap.String("local-member-id", c.localID.String()),
					zap.String("promoted-member-id", id.String()),
				)
			}
		}
	} else {
		c.lg.Info(
			"ignore already promoted member due to backend being nil",
			zap.String("cluster-id", c.cid.String()),
			zap.String("local-member-id", c.localID.String()),
			zap.String("promoted-member-id", id.String()),