Repository: etcd-io/etcd
File: server/storage/wal/version.go (Go)

Code before:

func visitEntry(ent raftpb.Entry, visitor Visitor) error {
	err := visitMessage(proto.MessageReflect(&ent), visitor)
	if err != nil {
		return err
	}
	return visitEntryData(ent.Type, ent.Data, visitor)
}

func visitEntryData(entryType raftpb.EntryType, data []byte, visitor Visitor) error {
	var msg protoreflect.Message
	switch entryType {
	case raftpb.EntryNormal:
		var raftReq etcdserverpb.InternalRaftRequest
		if err := pbutil.Unmarshaler(&raftReq).Unmarshal(data); err != nil {
			// try V2 Request
			var r etcdserverpb.Request
			if pbutil.Unmarshaler(&r).Unmarshal(data) != nil {
				// return original error
				return err
			}
			msg = proto.MessageReflect(&r)
			break
		}
		msg = proto.MessageReflect(&raftReq)
		if raftReq.ClusterVersionSet != nil {
			_, err := semver.NewVersion(raftReq.ClusterVersionSet.Ver)
			if err != nil {
				return err
			}
			// ClusterVersionSet was introduced in 3.5.
			err = visitor(msg.Descriptor().FullName(), &version.V3_5)
			if err != nil {
				return err
			}
		}
	case raftpb.EntryConfChange:
		var confChange raftpb.ConfChange
		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
		if err != nil {
			return nil
		}
		msg = proto.MessageReflect(&confChange)
		return visitor(msg.Descriptor().FullName(), &version.V3_0)
	case raftpb.EntryConfChangeV2:
		var confChange raftpb.ConfChangeV2
		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
		if err != nil {
			return nil
		}
		msg = proto.MessageReflect(&confChange)

Review comment (suggestion):
I think you can remove the whole block for `ClusterVersionSet` and just move the call `return visitMessage(msg, visitor)` from line 145 here.

Code after:

func visitEntry(ent raftpb.Entry, visitor Visitor) error {
	err := visitMessage(proto.MessageReflect(&ent), visitor)
	if err != nil {
		return err
	}
	return visitEntryData(ent.Type, ent.Data, visitor)
}

func visitEntryData(entryType raftpb.EntryType, data []byte, visitor Visitor) error {
	var msg protoreflect.Message
	switch entryType {
	case raftpb.EntryNormal:
		var raftReq etcdserverpb.InternalRaftRequest
		if err := pbutil.Unmarshaler(&raftReq).Unmarshal(data); err != nil {
			// try V2 Request
			var r etcdserverpb.Request
			if pbutil.Unmarshaler(&r).Unmarshal(data) != nil {
				// return original error
				return err
			}
			msg = proto.MessageReflect(&r)
			break
		}
		msg = proto.MessageReflect(&raftReq)
	case raftpb.EntryConfChange:
		var confChange raftpb.ConfChange
		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
		if err != nil {
			return nil
		}
		msg = proto.MessageReflect(&confChange)
		return visitor(msg.Descriptor().FullName(), &version.V3_0)
	case raftpb.EntryConfChangeV2:
		var confChange raftpb.ConfChangeV2
		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
		if err != nil {
			return nil
		}
		msg = proto.MessageReflect(&confChange)
		return visitor(msg.Descriptor().FullName(), &version.V3_4)
	default:
		panic("unhandled")
	}
	return visitMessage(msg, visitor)
}

func visitMessageDescriptor(md protoreflect.MessageDescriptor, visitor Visitor) error {
	err := visitDescriptor(md, visitor)
	if err != nil {
		return err