Repository: go-kratos/kratos
Pull request #2177 (2022-07-09 16:38:30)

fix(transport): fix transport early listening


Patch:
diff --git a/api/metadata/server.go b/api/metadata/server.go
index 445ddeb6..3438d132 100644
--- a/api/metadata/server.go
+++ b/api/metadata/server.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"compress/gzip"
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"sync"
@@ -76,6 +77,10 @@ func (s *Server) load() error {
 			}
 			fdps, e := allDependency(fdp)
 			if e != nil {
+				if errors.Is(e, protoregistry.NotFound) {
+					// Skip this service if one of its dependencies is not found.
+					continue
+				}
 				err = e
 				return false
 			}
diff --git a/contrib/registry/kubernetes/go.mod b/contrib/registry/kubernetes/go.mod
index 8d77a4af..2d01cbaf 100644
--- a/contrib/registry/kubernetes/go.mod
+++ b/contrib/registry/kubernetes/go.mod
@@ -7,7 +7,7 @@ require (
 	github.com/json-iterator/go v1.1.12
 	k8s.io/api v0.24.2
 	k8s.io/apimachinery v0.24.2
-	k8s.io/client-go v0.24.1
+	k8s.io/client-go v0.24.2
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/registry/kubernetes/go.sum b/contrib/registry/kubernetes/go.sum
index 559f0670..368dd5d5 100644
--- a/contrib/registry/kubernetes/go.sum
+++ b/contrib/registry/kubernetes/go.sum
@@ -653,14 +653,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
 k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI=
 k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=
-k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
 k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM=
 k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
-k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
-k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
+k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA=
+k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
diff --git a/errors/errors.go b/errors/errors.go
index a18f5512..e6bebbf8 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -106,6 +106,9 @@ func Reason(err error) string {
 
 // Clone deep clone error to a new error.
 func Clone(err *Error) *Error {
+	if err == nil {
+		return nil
+	}
 	metadata := make(map[string]string, len(err.Metadata))
 	for k, v := range err.Metadata {
 		metadata[k] = v
diff --git a/transport/grpc/server.go b/transport/grpc/server.go
index 31c03f75..0131692e 100644
--- a/transport/grpc/server.go
+++ b/transport/grpc/server.go
@@ -156,8 +156,6 @@ func NewServer(opts ...ServerOption) *Server {
 	}
 	srv.Server = grpc.NewServer(grpcOpts...)
 	srv.metadata = apimd.NewServer(srv.Server)
-	// listen and endpoint
-	srv.err = srv.listenAndEndpoint()
 	// internal register
 	grpc_health_v1.RegisterHealthServer(srv.Server, srv.health)
 	apimd.RegisterMetadataServer(srv.Server, srv.metadata)
@@ -169,7 +167,7 @@ func NewServer(opts ...ServerOption) *Server {
 // examples:
 //   grpc://127.0.0.1:9000?isSecure=false
 func (s *Server) Endpoint() (*url.URL, error) {
-	if s.err != nil {
+	if err := s.listenAndEndpoint(); err != nil {
 		return nil, s.err
 	}
 	return s.endpoint, nil
@@ -177,7 +175,7 @@ func (s *Server) Endpoint() (*url.URL, error) {
 
 // Start start the gRPC server.
 func (s *Server) Start(ctx context.Context) error {
-	if s.err != nil {
+	if err := s.listenAndEndpoint(); err != nil {
 		return s.err
 	}
 	s.baseCtx = ctx
@@ -198,15 +196,17 @@ func (s *Server) listenAndEndpoint() error {
 	if s.lis == nil {
 		lis, err := net.Listen(s.network, s.address)
 		if err != nil {
+			s.err = err
+			return err
+		}
+		addr, err := host.Extract(s.address, lis)
+		if err != nil {
+			_ = s.lis.Close()
+			s.err = err
 			return err
 		}
 		s.lis = lis
+		s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("grpc", s.tlsConf != nil), addr)
 	}
-	addr, err := host.Extract(s.address, s.lis)
-	if err != nil {
-		_ = s.lis.Close()
-		return err
-	}
-	s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("grpc", s.tlsConf != nil), addr)
-	return nil
+	return s.err
 }
diff --git a/transport/http/server.go b/transport/http/server.go
index c45a7269..637ef72a 100644
--- a/transport/http/server.go
+++ b/transport/http/server.go
@@ -227,16 +227,16 @@ func (s *Server) filter() mux.MiddlewareFunc {
 //   https://127.0.0.1:8000
 //   Legacy: http://127.0.0.1:8000?isSecure=false
 func (s *Server) Endpoint() (*url.URL, error) {
-	if s.err != nil {
-		return nil, s.err
+	if err := s.listenAndEndpoint(); err != nil {
+		return nil, err
 	}
 	return s.endpoint, nil
 }
 
 // Start start the HTTP server.
 func (s *Server) Start(ctx context.Context) error {
-	if s.err != nil {
-		return s.err
+	if err := s.listenAndEndpoint(); err != nil {
+		return err
 	}
 	s.BaseContext = func(net.Listener) context.Context {
 		return ctx
@@ -264,15 +264,17 @@ func (s *Server) listenAndEndpoint() error {
 	if s.lis == nil {
 		lis, err := net.Listen(s.network, s.address)
 		if err != nil {
+			s.err = err
+			return err
+		}
+		addr, err := host.Extract(s.address, lis)
+		if err != nil {
+			_ = s.lis.Close()
+			s.err = err
 			return err
 		}
 		s.lis = lis
+		s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("http", s.tlsConf != nil), addr)
 	}
-	addr, err := host.Extract(s.address, s.lis)
-	if err != nil {
-		_ = s.lis.Close()
-		return err
-	}
-	s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("http", s.tlsConf != nil), addr)
-	return nil
+	return s.err
 }


Test patch:
diff --git a/errors/errors_test.go b/errors/errors_test.go
index f76d5151..5196d0b6 100644
--- a/errors/errors_test.go
+++ b/errors/errors_test.go
@@ -114,20 +114,37 @@ func TestCause(t *testing.T) {
 }
 
 func TestOther(t *testing.T) {
+	err := Errorf(10001, "test code 10001", "message")
+	// Code
 	if !reflect.DeepEqual(Code(nil), 200) {
 		t.Errorf("Code(nil) = %v, want %v", Code(nil), 200)
 	}
 	if !reflect.DeepEqual(Code(errors.New("test")), UnknownCode) {
 		t.Errorf(`Code(errors.New("test")) = %v, want %v`, Code(nil), 200)
 	}
-	if !reflect.DeepEqual(Reason(errors.New("test")), UnknownReason) {
-		t.Errorf(`Reason(errors.New("test")) = %v, want %v`, Reason(nil), UnknownReason)
-	}
-	err := Errorf(10001, "test code 10001", "message")
 	if !reflect.DeepEqual(Code(err), 10001) {
 		t.Errorf(`Code(err) = %v, want %v`, Code(err), 10001)
 	}
+	// Reason
+	if !reflect.DeepEqual(Reason(nil), UnknownReason) {
+		t.Errorf(`Reason(nil) = %v, want %v`, Reason(nil), UnknownReason)
+	}
+	if !reflect.DeepEqual(Reason(errors.New("test")), UnknownReason) {
+		t.Errorf(`Reason(errors.New("test")) = %v, want %v`, Reason(nil), UnknownReason)
+	}
 	if !reflect.DeepEqual(Reason(err), "test code 10001") {
 		t.Errorf(`Reason(err) = %v, want %v`, Reason(err), "test code 10001")
 	}
+	// Clone
+	err400 := Newf(http.StatusBadRequest, "BAD_REQUEST", "param invalid")
+	err400.Metadata = map[string]string{
+		"key1": "val1",
+		"key2": "val2",
+	}
+	if cerr := Clone(err400); cerr == nil || cerr.Error() != err400.Error() {
+		t.Errorf("Clone(err) = %v, want %v", Clone(err400), err400)
+	}
+	if cerr := Clone(nil); cerr != nil {
+		t.Errorf("Clone(nil) = %v, want %v", Clone(err400), err400)
+	}
 }