Repository: cloudwego/kitex
File: server/server.go (Go)

Code before:
		rpcStats := rpcinfo.AsMutableRPCStats(rpcinfo.NewRPCStats())
		if s.opt.StatsLevel != nil {
			rpcStats.SetLevel(*s.opt.StatsLevel)
		}

		// Export read-only views to external users and keep a mapping for internal users.
		ri = rpcinfo.NewRPCInfo(
			rpcinfo.EmptyEndpointInfo(),
			rpcinfo.FromBasicInfo(s.opt.Svr),
			rpcinfo.NewServerInvocation(),
			rpcinfo.AsMutableRPCConfig(s.opt.Configs).Clone().ImmutableView(),
			rpcStats.ImmutableView(),
		)
		rpcinfo.AsMutableEndpointInfo(ri.From()).SetAddress(rAddr)
		return ri
	}
}

func (s *server) buildInvokeChain() {
	innerHandlerEp := s.invokeHandleEndpoint()
	s.eps = endpoint.Chain(s.mws...)(innerHandlerEp)
}

// RegisterService should not be called by users directly.
func (s *server) RegisterService(svcInfo *serviceinfo.ServiceInfo, handler interface{}) error {
	if s.isStarted {
		panic("service cannot be registered while server is running")
	}
	if svcInfo == nil {
		panic("svcInfo is nil. please specify non-nil svcInfo")
	}
	if handler == nil || reflect.ValueOf(handler).IsNil() {
		panic("handler is nil. please specify non-nil handler")
	}
	if s.svcs.getService(svcInfo.ServiceName) != nil {
		panic(fmt.Sprintf("Service[%s] is already defined", svcInfo.ServiceName))
	}

	s.Lock()
	defer s.Unlock()
	s.svcs.addService(svcInfo, handler)
	return nil
}

func (s *server) GetServiceInfos() map[string]*serviceinfo.ServiceInfo {
	return s.svcs.getSvcInfoMap()
}

// Run runs the server.
func (s *server) Run() (err error) {
	if err = s.check(); err != nil {

Review comment (suggestion):
The whole RegisterService should add the lock, and rename `isStarted` to `isRun` is better, because we set `isRun` to true once we call Run()

Code after:
		rpcStats := rpcinfo.AsMutableRPCStats(rpcinfo.NewRPCStats())
		if s.opt.StatsLevel != nil {
			rpcStats.SetLevel(*s.opt.StatsLevel)
		}

		// Export read-only views to external users and keep a mapping for internal users.
		ri = rpcinfo.NewRPCInfo(
			rpcinfo.EmptyEndpointInfo(),
			rpcinfo.FromBasicInfo(s.opt.Svr),
			rpcinfo.NewServerInvocation(),
			rpcinfo.AsMutableRPCConfig(s.opt.Configs).Clone().ImmutableView(),
			rpcStats.ImmutableView(),
		)
		rpcinfo.AsMutableEndpointInfo(ri.From()).SetAddress(rAddr)
		return ri
	}
}

func (s *server) buildInvokeChain() {
	innerHandlerEp := s.invokeHandleEndpoint()
	s.eps = endpoint.Chain(s.mws...)(innerHandlerEp)
}

// RegisterService should not be called by users directly.
func (s *server) RegisterService(svcInfo *serviceinfo.ServiceInfo, handler interface{}) error {
	s.Lock()
	defer s.Unlock()
	if s.isRun {
		panic("service cannot be registered while server is running")
	}
	if svcInfo == nil {
		panic("svcInfo is nil. please specify non-nil svcInfo")
	}
	if handler == nil || reflect.ValueOf(handler).IsNil() {
		panic("handler is nil. please specify non-nil handler")
	}
	if s.svcs.getService(svcInfo.ServiceName) != nil {
		panic(fmt.Sprintf("Service[%s] is already defined", svcInfo.ServiceName))
	}

	s.svcs.addService(svcInfo, handler)
	return nil
}

func (s *server) GetServiceInfos() map[string]*serviceinfo.ServiceInfo {
	return s.svcs.getSvcInfoMap()
}

// Run runs the server.
func (s *server) Run() (err error) {
	s.Lock()