@@ -4,13 +4,16 @@ import (
44 "context"
55 "crypto/x509"
66 "strings"
7+ "sync"
8+ "time"
79
810 "golang.org/x/exp/maps"
911 "google.golang.org/grpc"
1012 "google.golang.org/grpc/codes"
1113 "google.golang.org/grpc/credentials"
1214 "google.golang.org/grpc/credentials/insecure"
1315 "google.golang.org/grpc/grpclog"
16+ "google.golang.org/grpc/keepalive"
1417 "google.golang.org/grpc/status"
1518
1619 "github.com/flyteorg/flyte/v2/flytestdlib/config"
@@ -32,10 +35,66 @@ type Connector struct {
3235
3336// ClientSet contains the clients exposed to communicate with various connector services.
3437type ClientSet struct {
38+ mu sync.RWMutex
3539 asyncConnectorClients map [string ]connector.AsyncConnectorServiceClient // map[endpoint] => AsyncConnectorServiceClient
3640 connectorMetadataClients map [string ]connector.ConnectorMetadataServiceClient // map[endpoint] => ConnectorMetadataServiceClient
3741}
3842
43+ // getOrDialAsyncClient returns the cached AsyncConnectorService client for the
44+ // endpoint, dialing (and caching) a persistent connection on first use.
45+ func (cs * ClientSet ) getOrDialAsyncClient (ctx context.Context , deployment * Deployment ) (connector.AsyncConnectorServiceClient , error ) {
46+ cs .mu .Lock ()
47+ defer cs .mu .Unlock ()
48+
49+ if cs .asyncConnectorClients == nil {
50+ cs .asyncConnectorClients = make (map [string ]connector.AsyncConnectorServiceClient )
51+ }
52+ if cs .connectorMetadataClients == nil {
53+ cs .connectorMetadataClients = make (map [string ]connector.ConnectorMetadataServiceClient )
54+ }
55+
56+ if client , ok := cs .asyncConnectorClients [deployment .Endpoint ]; ok {
57+ return client , nil
58+ }
59+
60+ conn , err := getGrpcConnection (ctx , deployment )
61+ if err != nil {
62+ return nil , err
63+ }
64+
65+ asyncClient := connector .NewAsyncConnectorServiceClient (conn )
66+ cs .asyncConnectorClients [deployment .Endpoint ] = asyncClient
67+ if _ , ok := cs .connectorMetadataClients [deployment .Endpoint ]; ! ok {
68+ cs .connectorMetadataClients [deployment .Endpoint ] = connector .NewConnectorMetadataServiceClient (conn )
69+ }
70+ return asyncClient , nil
71+ }
72+
73+ // getOrDialMetadataClient returns the cached ConnectorMetadataService client for
74+ // the endpoint, dialing (and caching) a persistent connection on first use.
75+ func (cs * ClientSet ) getOrDialMetadataClient (ctx context.Context , deployment * Deployment ) (connector.ConnectorMetadataServiceClient , error ) {
76+ cs .mu .Lock ()
77+ defer cs .mu .Unlock ()
78+ if client , ok := cs .connectorMetadataClients [deployment .Endpoint ]; ok {
79+ return client , nil
80+ }
81+ conn , err := getGrpcConnection (ctx , deployment )
82+ if err != nil {
83+ return nil , err
84+ }
85+ client := connector .NewConnectorMetadataServiceClient (conn )
86+ cs .connectorMetadataClients [deployment .Endpoint ] = client
87+ return client , nil
88+ }
89+
90+ // metadataClient returns the cached ConnectorMetadataService client for the endpoint.
91+ func (cs * ClientSet ) metadataClient (endpoint string ) (connector.ConnectorMetadataServiceClient , bool ) {
92+ cs .mu .RLock ()
93+ defer cs .mu .RUnlock ()
94+ client , ok := cs .connectorMetadataClients [endpoint ]
95+ return client , ok
96+ }
97+
3998func getGrpcConnection (ctx context.Context , connector * Deployment ) (* grpc.ClientConn , error ) {
4099 var opts []grpc.DialOption
41100
@@ -59,6 +118,13 @@ func getGrpcConnection(ctx context.Context, connector *Deployment) (*grpc.Client
59118 opts = append (opts ,
60119 grpc .WithChainUnaryInterceptor (clientMetrics .UnaryClientInterceptor ()),
61120 grpc .WithChainStreamInterceptor (clientMetrics .StreamClientInterceptor ()),
121+ // Keepalive lets gRPC notice a dead/half-open transport within seconds
122+ // (via HTTP/2 PINGs during active RPCs) instead of relying on the OS TCP
123+ // timeout.
124+ grpc .WithKeepaliveParams (keepalive.ClientParameters {
125+ Time : 30 * time .Second ,
126+ Timeout : 10 * time .Second ,
127+ }),
62128 )
63129
64130 var err error
@@ -102,7 +168,7 @@ func updateRegistry(
102168 isConnectorApp bool ,
103169) {
104170 for connectorID , connectorDeployment := range connectorDeployments {
105- client , ok := cs .connectorMetadataClients [ connectorDeployment .Endpoint ]
171+ client , ok := cs .metadataClient ( connectorDeployment .Endpoint )
106172 if ! ok {
107173 logger .Warningf (ctx , "Connector client not found in the clientSet for the endpoint: %v" , connectorDeployment .Endpoint )
108174 continue
@@ -199,28 +265,29 @@ func getConnectorRegistry(ctx context.Context, cs *ClientSet) Registry {
199265 return newConnectorRegistry
200266}
201267
202- func getConnectorClientSets (ctx context.Context ) * ClientSet {
203- clientSet := & ClientSet {
204- asyncConnectorClients : make (map [string ]connector.AsyncConnectorServiceClient ),
205- connectorMetadataClients : make (map [string ]connector.ConnectorMetadataServiceClient ),
206- }
207-
268+ // allConnectorDeployments returns every configured connector endpoint: the
269+ // default connector, explicit deployments, and connector apps.
270+ func allConnectorDeployments (cfg * Config ) []* Deployment {
208271 var connectorDeployments []* Deployment
209- cfg := GetConfig ()
210-
211272 if len (cfg .DefaultConnector .Endpoint ) != 0 {
212273 connectorDeployments = append (connectorDeployments , & cfg .DefaultConnector )
213274 }
214-
215275 for _ , deployment := range cfg .ConnectorDeployments {
216276 connectorDeployments = append (connectorDeployments , deployment )
217277 }
218-
219278 for _ , deployment := range cfg .ConnectorApps {
220279 connectorDeployments = append (connectorDeployments , deployment )
221280 }
281+ return connectorDeployments
282+ }
283+
284+ func getConnectorClientSets (ctx context.Context ) * ClientSet {
285+ clientSet := & ClientSet {
286+ asyncConnectorClients : make (map [string ]connector.AsyncConnectorServiceClient ),
287+ connectorMetadataClients : make (map [string ]connector.ConnectorMetadataServiceClient ),
288+ }
222289
223- for _ , connectorDeployment := range connectorDeployments {
290+ for _ , connectorDeployment := range allConnectorDeployments ( GetConfig ()) {
224291 if _ , ok := clientSet .connectorMetadataClients [connectorDeployment .Endpoint ]; ok {
225292 logger .Infof (ctx , "Connector client already initialized for [%v]" , connectorDeployment .Endpoint )
226293 continue
0 commit comments