@@ -26,6 +26,7 @@ import (
2626 "time"
2727
2828 "go.uber.org/zap"
29+ "golang.org/x/sync/singleflight"
2930 "google.golang.org/grpc"
3031 "google.golang.org/grpc/codes"
3132 healthpb "google.golang.org/grpc/health/grpc_health_v1"
@@ -443,6 +444,8 @@ type serviceDiscovery struct {
443444 tlsCfg * tls.Config
444445 // Client option.
445446 option * opt.Option
447+
448+ flight singleflight.Group
446449}
447450
448451// NewDefaultServiceDiscovery returns a new default service discovery-based client.
@@ -474,6 +477,7 @@ func NewServiceDiscovery(
474477 keyspaceID : keyspaceID ,
475478 tlsCfg : tlsCfg ,
476479 option : option ,
480+ flight : singleflight.Group {},
477481 }
478482 pdsd .callbacks .setServiceModeUpdateCallback (serviceModeUpdateCb )
479483 urls = tlsutil .AddrsToURLs (urls , tlsCfg )
@@ -919,18 +923,31 @@ func (c *serviceDiscovery) getClusterInfo(ctx context.Context, url string, timeo
919923 }
920924 start := time .Now ()
921925 defer func () { metrics .InternalCmdDurationGetClusterInfo .Observe (time .Since (start ).Seconds ()) }()
922- clusterInfo , err := pdpb .NewPDClient (cc ).GetClusterInfo (ctx , & pdpb.GetClusterInfoRequest {})
923- if err != nil {
924- metrics .InternalCmdFailedDurationGetClusterInfo .Observe (time .Since (start ).Seconds ())
925- attachErr := errors .Errorf ("error:%s target:%s status:%s" , err , cc .Target (), cc .GetState ().String ())
926- return nil , errs .ErrClientGetClusterInfo .Wrap (attachErr ).GenWithStackByCause ()
927- }
928- if clusterInfo .GetHeader ().GetError () != nil {
926+ key := "GetClusterInfo-" + url
927+ r := c .flight .DoChan (key , func () (any , error ) {
928+ return pdpb .NewPDClient (cc ).GetClusterInfo (ctx , & pdpb.GetClusterInfoRequest {})
929+ })
930+ select {
931+ case res := <- r :
932+ err = res .Err
933+ if err != nil {
934+ metrics .InternalCmdFailedDurationGetClusterInfo .Observe (time .Since (start ).Seconds ())
935+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , err , cc .Target (), cc .GetState ().String ())
936+ return nil , errs .ErrClientGetClusterInfo .Wrap (attachErr ).GenWithStackByCause ()
937+ }
938+ val := res .Val
939+ clusterInfo := val .(* pdpb.GetClusterInfoResponse )
940+ if clusterInfo .GetHeader ().GetError () != nil {
941+ metrics .InternalCmdFailedDurationGetClusterInfo .Observe (time .Since (start ).Seconds ())
942+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , clusterInfo .GetHeader ().GetError ().String (), cc .Target (), cc .GetState ().String ())
943+ return nil , errs .ErrClientGetClusterInfo .Wrap (attachErr ).GenWithStackByCause ()
944+ }
945+ return clusterInfo , nil
946+ case <- ctx .Done ():
947+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , ctx .Err (), cc .Target (), cc .GetState ().String ())
929948 metrics .InternalCmdFailedDurationGetClusterInfo .Observe (time .Since (start ).Seconds ())
930- attachErr := errors .Errorf ("error:%s target:%s status:%s" , clusterInfo .GetHeader ().GetError ().String (), cc .Target (), cc .GetState ().String ())
931949 return nil , errs .ErrClientGetClusterInfo .Wrap (attachErr ).GenWithStackByCause ()
932950 }
933- return clusterInfo , nil
934951}
935952
936953func (c * serviceDiscovery ) getMembers (ctx context.Context , url string , timeout time.Duration ) (* pdpb.GetMembersResponse , error ) {
@@ -942,18 +959,31 @@ func (c *serviceDiscovery) getMembers(ctx context.Context, url string, timeout t
942959 }
943960 start := time .Now ()
944961 defer func () { metrics .InternalCmdDurationGetMembers .Observe (time .Since (start ).Seconds ()) }()
945- members , err := pdpb .NewPDClient (cc ).GetMembers (ctx , & pdpb.GetMembersRequest {})
946- if err != nil {
947- metrics .InternalCmdFailedDurationGetMembers .Observe (time .Since (start ).Seconds ())
948- attachErr := errors .Errorf ("error:%s target:%s status:%s" , err , cc .Target (), cc .GetState ().String ())
949- return nil , errs .ErrClientGetMember .Wrap (attachErr ).GenWithStackByCause ()
950- }
951- if members .GetHeader ().GetError () != nil {
962+ key := "GetMembers-" + url
963+ r := c .flight .DoChan (key , func () (any , error ) {
964+ return pdpb .NewPDClient (cc ).GetMembers (ctx , & pdpb.GetMembersRequest {})
965+ })
966+ select {
967+ case res := <- r :
968+ err = res .Err
969+ if err != nil {
970+ metrics .InternalCmdFailedDurationGetMembers .Observe (time .Since (start ).Seconds ())
971+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , err , cc .Target (), cc .GetState ().String ())
972+ return nil , errs .ErrClientGetMember .Wrap (attachErr ).GenWithStackByCause ()
973+ }
974+ val := res .Val
975+ members := val .(* pdpb.GetMembersResponse )
976+ if members .GetHeader ().GetError () != nil {
977+ metrics .InternalCmdFailedDurationGetMembers .Observe (time .Since (start ).Seconds ())
978+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , members .GetHeader ().GetError ().String (), cc .Target (), cc .GetState ().String ())
979+ return nil , errs .ErrClientGetMember .Wrap (attachErr ).GenWithStackByCause ()
980+ }
981+ return members , nil
982+ case <- ctx .Done ():
983+ attachErr := errors .Errorf ("error:%s target:%s status:%s" , ctx .Err (), cc .Target (), cc .GetState ().String ())
952984 metrics .InternalCmdFailedDurationGetMembers .Observe (time .Since (start ).Seconds ())
953- attachErr := errors .Errorf ("error:%s target:%s status:%s" , members .GetHeader ().GetError ().String (), cc .Target (), cc .GetState ().String ())
954985 return nil , errs .ErrClientGetMember .Wrap (attachErr ).GenWithStackByCause ()
955986 }
956- return members , nil
957987}
958988
959989func (c * serviceDiscovery ) updateURLs (members []* pdpb.Member ) {
0 commit comments