diff --git a/clients/naming_client/naming_client.go b/clients/naming_client/naming_client.go index a2257e1a..285f22cc 100644 --- a/clients/naming_client/naming_client.go +++ b/clients/naming_client/naming_client.go @@ -193,7 +193,7 @@ func (sc *NamingClient) GetService(param vo.GetServiceParam) (service model.Serv var ok bool clusters := strings.Join(param.Clusters, ",") service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters) - if !ok { + if !ok || !sc.serviceProxy.IsSubscribed(param.ServiceName, param.GroupName, clusters) { service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters) } return service, err @@ -229,7 +229,7 @@ func (sc *NamingClient) SelectAllInstances(param vo.SelectAllInstancesParam) ([] ) service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters) - if !ok { + if !ok || !sc.serviceProxy.IsSubscribed(param.ServiceName, param.GroupName, clusters) { service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters) } if err != nil || service.Hosts == nil || len(service.Hosts) == 0 { @@ -250,7 +250,7 @@ func (sc *NamingClient) SelectInstances(param vo.SelectInstancesParam) ([]model. ) clusters := strings.Join(param.Clusters, ",") service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters) - if !ok { + if !ok || !sc.serviceProxy.IsSubscribed(param.ServiceName, param.GroupName, clusters) { service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters) if err != nil { return nil, err @@ -286,7 +286,7 @@ func (sc *NamingClient) SelectOneHealthyInstance(param vo.SelectOneHealthInstanc ) clusters := strings.Join(param.Clusters, ",") service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters) - if !ok { + if !ok || !sc.serviceProxy.IsSubscribed(param.ServiceName, param.GroupName, clusters) { service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters) if err != nil { return nil, err diff --git a/clients/naming_client/naming_client_test.go b/clients/naming_client/naming_client_test.go index 58ac40e6..5ae9b78d 100644 --- a/clients/naming_client/naming_client_test.go +++ b/clients/naming_client/naming_client_test.go @@ -17,6 +17,7 @@ package naming_client import ( + "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_cache" "testing" "github.com/nacos-group/nacos-sdk-go/v2/common/http_agent" @@ -26,6 +27,9 @@ import ( "github.com/nacos-group/nacos-sdk-go/v2/model" "github.com/nacos-group/nacos-sdk-go/v2/vo" "github.com/stretchr/testify/assert" + + . "github.com/agiledragon/gomonkey/v2" + . "github.com/smartystreets/goconvey/convey" ) var clientConfigTest = *constant.NewClientConfig( @@ -37,6 +41,7 @@ var clientConfigTest = *constant.NewClientConfig( var serverConfigTest = *constant.NewServerConfig("127.0.0.1", 80, constant.WithContextPath("/nacos")) type MockNamingProxy struct { + subscribed bool } func (m *MockNamingProxy) RegisterInstance(serviceName string, groupName string, instance model.Instance) (bool, error) { @@ -71,6 +76,10 @@ func (m *MockNamingProxy) Unsubscribe(serviceName, groupName, clusters string) e return nil } +func (m *MockNamingProxy) IsSubscribed(serviceName, groupName, clusters string) bool { + return m.subscribed +} + func (m *MockNamingProxy) CloseClient() {} func NewTestNamingClient() *NamingClient { @@ -382,6 +391,66 @@ func TestNamingClient_GetAllServicesInfo(t *testing.T) { assert.Nil(t, err) } +func TestAutoSubscribeWhenSelect(t *testing.T) { + Convey("when already subscribed, it do nothing", t, func() { + var mockServiceInfoHolder *naming_cache.ServiceInfoHolder + var mockProxy *NamingProxyDelegate + client := &NamingClient{} + client.serviceProxy = mockProxy + client.serviceInfoHolder = mockServiceInfoHolder + patches := ApplyMethod(mockServiceInfoHolder, "GetServiceInfo", func(*naming_cache.ServiceInfoHolder, string, string, string) (model.Service, bool) { + return model.Service{}, true + }) + defer patches.Reset() + + patches.ApplyMethod(mockProxy, "IsSubscribed", func(*NamingProxyDelegate, string, string, string) bool { + return true + }) + called := false + patches.ApplyMethod(mockProxy, "Subscribe", func(*NamingProxyDelegate, string, string, string) (model.Service, error) { + called = true + return model.Service{}, nil + }) + + _, _ = client.SelectInstances(vo.SelectInstancesParam{}) + So(called, ShouldBeFalse) + }) + Convey("it will call subscribe func when it isn't subscribed", t, func() { + var mockServiceInfoHolder *naming_cache.ServiceInfoHolder + var mockProxy *NamingProxyDelegate + client := &NamingClient{} + client.serviceProxy = mockProxy + client.serviceInfoHolder = mockServiceInfoHolder + patches := ApplyMethod(mockServiceInfoHolder, "GetServiceInfo", func(*naming_cache.ServiceInfoHolder, string, string, string) (model.Service, bool) { + return model.Service{}, true + }) + defer patches.Reset() + + patches.ApplyMethod(mockProxy, "IsSubscribed", func(*NamingProxyDelegate, string, string, string) bool { + return false + }) + called := false + patches.ApplyMethod(mockProxy, "Subscribe", func(*NamingProxyDelegate, string, string, string) (model.Service, error) { + called = true + return model.Service{}, nil + }) + _, _ = client.SelectInstances(vo.SelectInstancesParam{}) + So(called, ShouldBeTrue) + + called = false + _, _ = client.SelectAllInstances(vo.SelectAllInstancesParam{}) + So(called, ShouldBeTrue) + + called = false + _, _ = client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{}) + So(called, ShouldBeTrue) + + called = false + _, _ = client.GetService(vo.GetServiceParam{}) + So(called, ShouldBeTrue) + }) +} + func BenchmarkNamingClient_SelectOneHealthyInstances(b *testing.B) { services := model.Service{ Name: "DEFAULT_GROUP@@DEMO", diff --git a/clients/naming_client/naming_grpc/naming_grpc_proxy.go b/clients/naming_client/naming_grpc/naming_grpc_proxy.go index adee904c..775abb69 100644 --- a/clients/naming_client/naming_grpc/naming_grpc_proxy.go +++ b/clients/naming_client/naming_grpc/naming_grpc_proxy.go @@ -18,6 +18,7 @@ package naming_grpc import ( "context" + "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_proxy" "time" "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_cache" @@ -33,6 +34,8 @@ import ( "github.com/nacos-group/nacos-sdk-go/v2/util" ) +var _ naming_proxy.INamingProxy = (*NamingGrpcProxy)(nil) + // NamingGrpcProxy ... type NamingGrpcProxy struct { clientConfig constant.ClientConfig diff --git a/clients/naming_client/naming_http/naming_http_proxy.go b/clients/naming_client/naming_http/naming_http_proxy.go index f6f2ad5c..51ca0202 100644 --- a/clients/naming_client/naming_http/naming_http_proxy.go +++ b/clients/naming_client/naming_http/naming_http_proxy.go @@ -18,6 +18,7 @@ package naming_http import ( "context" + "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_proxy" "net/http" "strconv" "time" @@ -34,6 +35,8 @@ import ( "github.com/nacos-group/nacos-sdk-go/v2/util" ) +var _ naming_proxy.INamingProxy = (*NamingHttpProxy)(nil) + // NamingHttpProxy ... type NamingHttpProxy struct { clientConfig constant.ClientConfig @@ -213,6 +216,10 @@ func (proxy *NamingHttpProxy) Unsubscribe(serviceName, groupName, clusters strin return nil } +func (proxy *NamingHttpProxy) IsSubscribed(serviceName, groupName, clusters string) bool { + panic("not implement it in NamingHttpProxy") +} + func (proxy *NamingHttpProxy) CloseClient() { } diff --git a/clients/naming_client/naming_proxy/proxy_interface.go b/clients/naming_client/naming_proxy/proxy_interface.go index dea2b0b1..ca909077 100644 --- a/clients/naming_client/naming_proxy/proxy_interface.go +++ b/clients/naming_client/naming_proxy/proxy_interface.go @@ -38,5 +38,7 @@ type INamingProxy interface { Unsubscribe(serviceName, groupName, clusters string) error + IsSubscribed(serviceName, groupName, clusters string) bool + CloseClient() } diff --git a/clients/naming_client/naming_proxy/proxy_interface_mock.go b/clients/naming_client/naming_proxy/proxy_interface_mock.go index cb069653..dad2e8c8 100644 --- a/clients/naming_client/naming_proxy/proxy_interface_mock.go +++ b/clients/naming_client/naming_proxy/proxy_interface_mock.go @@ -11,6 +11,8 @@ import ( model "github.com/nacos-group/nacos-sdk-go/v2/model" ) +var _ INamingProxy = new(MockINamingProxy) + // MockINamingProxy is a mock of INamingProxy interface. type MockINamingProxy struct { ctrl *gomock.Controller @@ -158,6 +160,11 @@ func (m *MockINamingProxy) Unsubscribe(serviceName, groupName, clusters string) return ret0 } +func (m *MockINamingProxy) IsSubscribed(serviceName, groupName, clusters string) bool { + //TODO implement me + panic("implement me") +} + // Unsubscribe indicates an expected call of Unsubscribe. func (mr *MockINamingProxyMockRecorder) Unsubscribe(serviceName, groupName, clusters interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() diff --git a/clients/naming_client/naming_proxy_delegate.go b/clients/naming_client/naming_proxy_delegate.go index 3b0d0b63..d498d03e 100644 --- a/clients/naming_client/naming_proxy_delegate.go +++ b/clients/naming_client/naming_proxy_delegate.go @@ -38,6 +38,8 @@ type NamingProxyDelegate struct { serviceInfoHolder *naming_cache.ServiceInfoHolder } +var _ naming_proxy.INamingProxy = (*NamingProxyDelegate)(nil) + func NewNamingProxyDelegate(ctx context.Context, clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig, httpAgent http_agent.IHttpAgent, serviceInfoHolder *naming_cache.ServiceInfoHolder) (naming_proxy.INamingProxy, error) { @@ -128,6 +130,10 @@ func (proxy *NamingProxyDelegate) Unsubscribe(serviceName, groupName, clusters s return proxy.grpcClientProxy.Unsubscribe(serviceName, groupName, clusters) } +func (proxy *NamingProxyDelegate) IsSubscribed(serviceName, groupName, clusters string) bool { + return proxy.grpcClientProxy.IsSubscribed(serviceName, groupName, clusters) +} + func (proxy *NamingProxyDelegate) CloseClient() { proxy.grpcClientProxy.CloseClient() } diff --git a/go.mod b/go.mod index 09d8efbf..7f2488df 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/nacos-group/nacos-sdk-go/v2 go 1.18 require ( + github.com/agiledragon/gomonkey/v2 v2.11.0 github.com/alibabacloud-go/tea v1.1.17 github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800 github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2 @@ -12,6 +13,7 @@ require ( github.com/golang/protobuf v1.5.3 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.12.2 + github.com/smartystreets/goconvey v1.8.1 github.com/stretchr/testify v1.8.1 go.uber.org/zap v1.21.0 golang.org/x/sync v0.1.0 @@ -27,8 +29,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/kr/pretty v0.1.0 // indirect github.com/kr/text v0.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -38,6 +42,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/smarty/assertions v1.15.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.17.0 // indirect diff --git a/go.sum b/go.sum index a1614907..201588aa 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/agiledragon/gomonkey/v2 v2.11.0 h1:5oxSgA+tC1xuGsrIorR+sYiziYltmJyEZ9qA25b6l5U= +github.com/agiledragon/gomonkey/v2 v2.11.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -145,6 +147,9 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -159,6 +164,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -213,6 +220,12 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -392,6 +405,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=