1212import pyarrow .parquet
1313from pyarrow import Schema
1414from pyarrow ._flight import FlightCallOptions , FlightDescriptor , Ticket
15- from pydantic import StrictInt , StrictStr
15+ from pydantic import Field , StrictInt , StrictStr
1616
1717from feast import OnDemandFeatureView
1818from feast .arrow_error_handler import arrow_client_error_handling_decorator
4242
4343
4444class FeastFlightClient (fl .FlightClient ):
45+ def __init__ (self , * args , connection_retries : int = 3 , ** kwargs ):
46+ super ().__init__ (* args , ** kwargs )
47+ self ._connection_retries = max (0 , connection_retries )
48+
4549 @arrow_client_error_handling_decorator
4650 def get_flight_info (
4751 self , descriptor : FlightDescriptor , options : FlightCallOptions = None
@@ -71,7 +75,12 @@ def list_actions(self, options: FlightCallOptions = None):
7175
7276
7377def build_arrow_flight_client (
74- scheme : str , host : str , port , auth_config : AuthConfig , cert : str = ""
78+ scheme : str ,
79+ host : str ,
80+ port ,
81+ auth_config : AuthConfig ,
82+ cert : str = "" ,
83+ connection_retries : int = 3 ,
7584):
7685 arrow_scheme = "grpc+tcp"
7786 if scheme == "https" :
@@ -88,10 +97,17 @@ def build_arrow_flight_client(
8897 if auth_config .type != AuthType .NONE .value :
8998 middlewares = [FlightAuthInterceptorFactory (auth_config )]
9099 return FeastFlightClient (
91- f"{ arrow_scheme } ://{ host } :{ port } " , middleware = middlewares , ** kwargs
100+ f"{ arrow_scheme } ://{ host } :{ port } " ,
101+ middleware = middlewares ,
102+ connection_retries = connection_retries ,
103+ ** kwargs ,
92104 )
93105
94- return FeastFlightClient (f"{ arrow_scheme } ://{ host } :{ port } " , ** kwargs )
106+ return FeastFlightClient (
107+ f"{ arrow_scheme } ://{ host } :{ port } " ,
108+ connection_retries = connection_retries ,
109+ ** kwargs ,
110+ )
95111
96112
97113class RemoteOfflineStoreConfig (FeastConfigBaseModel ):
@@ -109,6 +125,9 @@ class RemoteOfflineStoreConfig(FeastConfigBaseModel):
109125 """ str: Path to the public certificate when the offline server starts in TLS(SSL) mode. This may be needed if the offline server started with a self-signed certificate, typically this file ends with `*.crt`, `*.cer`, or `*.pem`.
110126 If type is 'remote', then this configuration is needed to connect to remote offline server in TLS mode. """
111127
128+ connection_retries : int = Field (default = 3 , ge = 0 )
129+ """ int: Number of retries for transient Arrow Flight errors with exponential backoff (default 3). """
130+
112131
113132class RemoteRetrievalJob (RetrievalJob ):
114133 def __init__ (
@@ -207,6 +226,7 @@ def get_historical_features(
207226 port = config .offline_store .port ,
208227 auth_config = config .auth_config ,
209228 cert = config .offline_store .cert ,
229+ connection_retries = config .offline_store .connection_retries ,
210230 )
211231
212232 feature_view_names = [fv .name for fv in feature_views ]
@@ -257,6 +277,7 @@ def pull_all_from_table_or_query(
257277 port = config .offline_store .port ,
258278 auth_config = config .auth_config ,
259279 cert = config .offline_store .cert ,
280+ connection_retries = config .offline_store .connection_retries ,
260281 )
261282
262283 api_parameters = {
@@ -295,6 +316,7 @@ def pull_latest_from_table_or_query(
295316 config .offline_store .port ,
296317 config .auth_config ,
297318 cert = config .offline_store .cert ,
319+ connection_retries = config .offline_store .connection_retries ,
298320 )
299321
300322 api_parameters = {
@@ -334,6 +356,7 @@ def write_logged_features(
334356 config .offline_store .port ,
335357 config .auth_config ,
336358 config .offline_store .cert ,
359+ connection_retries = config .offline_store .connection_retries ,
337360 )
338361
339362 api_parameters = {
@@ -364,6 +387,7 @@ def offline_write_batch(
364387 config .offline_store .port ,
365388 config .auth_config ,
366389 config .offline_store .cert ,
390+ connection_retries = config .offline_store .connection_retries ,
367391 )
368392
369393 feature_view_names = [feature_view .name ]
@@ -396,6 +420,7 @@ def validate_data_source(
396420 config .offline_store .port ,
397421 config .auth_config ,
398422 config .offline_store .cert ,
423+ connection_retries = config .offline_store .connection_retries ,
399424 )
400425
401426 api_parameters = {
@@ -421,6 +446,7 @@ def get_table_column_names_and_types_from_data_source(
421446 config .offline_store .port ,
422447 config .auth_config ,
423448 config .offline_store .cert ,
449+ connection_retries = config .offline_store .connection_retries ,
424450 )
425451
426452 api_parameters = {
0 commit comments