1010import pyarrow as pa
1111import pyarrow .flight as fl
1212import pyarrow .parquet
13+ from pyarrow import Schema
14+ from pyarrow ._flight import FlightCallOptions , FlightDescriptor , Ticket
1315from pydantic import StrictInt , StrictStr
1416
1517from feast import OnDemandFeatureView
18+ from feast .arrow_error_handler import arrow_client_error_handling_decorator
1619from feast .data_source import DataSource
1720from feast .feature_logging import (
1821 FeatureServiceLoggingSource ,
2730 RetrievalMetadata ,
2831)
2932from feast .infra .registry .base_registry import BaseRegistry
33+ from feast .permissions .auth .auth_type import AuthType
34+ from feast .permissions .auth_model import AuthConfig
3035from feast .permissions .client .arrow_flight_auth_interceptor import (
31- build_arrow_flight_client ,
36+ FlightAuthInterceptorFactory ,
3237)
3338from feast .repo_config import FeastConfigBaseModel , RepoConfig
3439from feast .saved_dataset import SavedDatasetStorage
3540
3641logger = logging .getLogger (__name__ )
3742
3843
44+ class FeastFlightClient (fl .FlightClient ):
45+ @arrow_client_error_handling_decorator
46+ def get_flight_info (
47+ self , descriptor : FlightDescriptor , options : FlightCallOptions = None
48+ ):
49+ return super ().get_flight_info (descriptor , options )
50+
51+ @arrow_client_error_handling_decorator
52+ def do_get (self , ticket : Ticket , options : FlightCallOptions = None ):
53+ return super ().do_get (ticket , options )
54+
55+ @arrow_client_error_handling_decorator
56+ def do_put (
57+ self ,
58+ descriptor : FlightDescriptor ,
59+ schema : Schema ,
60+ options : FlightCallOptions = None ,
61+ ):
62+ return super ().do_put (descriptor , schema , options )
63+
64+ @arrow_client_error_handling_decorator
65+ def list_flights (self , criteria : bytes = b"" , options : FlightCallOptions = None ):
66+ return super ().list_flights (criteria , options )
67+
68+ @arrow_client_error_handling_decorator
69+ def list_actions (self , options : FlightCallOptions = None ):
70+ return super ().list_actions (options )
71+
72+
73+ def build_arrow_flight_client (host : str , port , auth_config : AuthConfig ):
74+ if auth_config .type != AuthType .NONE .value :
75+ middlewares = [FlightAuthInterceptorFactory (auth_config )]
76+ return FeastFlightClient (f"grpc://{ host } :{ port } " , middleware = middlewares )
77+
78+ return FeastFlightClient (f"grpc://{ host } :{ port } " )
79+
80+
3981class RemoteOfflineStoreConfig (FeastConfigBaseModel ):
4082 type : Literal ["remote" ] = "remote"
4183 host : StrictStr
@@ -48,7 +90,7 @@ class RemoteOfflineStoreConfig(FeastConfigBaseModel):
4890class RemoteRetrievalJob (RetrievalJob ):
4991 def __init__ (
5092 self ,
51- client : fl . FlightClient ,
93+ client : FeastFlightClient ,
5294 api : str ,
5395 api_parameters : Dict [str , Any ],
5496 entity_df : Union [pd .DataFrame , str ] = None ,
@@ -338,7 +380,7 @@ def _send_retrieve_remote(
338380 api_parameters : Dict [str , Any ],
339381 entity_df : Union [pd .DataFrame , str ],
340382 table : pa .Table ,
341- client : fl . FlightClient ,
383+ client : FeastFlightClient ,
342384):
343385 command_descriptor = _call_put (
344386 api ,
@@ -351,19 +393,19 @@ def _send_retrieve_remote(
351393
352394
353395def _call_get (
354- client : fl . FlightClient ,
396+ client : FeastFlightClient ,
355397 command_descriptor : fl .FlightDescriptor ,
356398):
357399 flight = client .get_flight_info (command_descriptor )
358400 ticket = flight .endpoints [0 ].ticket
359401 reader = client .do_get (ticket )
360- return reader . read_all ()
402+ return read_all (reader )
361403
362404
363405def _call_put (
364406 api : str ,
365407 api_parameters : Dict [str , Any ],
366- client : fl . FlightClient ,
408+ client : FeastFlightClient ,
367409 entity_df : Union [pd .DataFrame , str ],
368410 table : pa .Table ,
369411):
@@ -391,7 +433,7 @@ def _put_parameters(
391433 command_descriptor : fl .FlightDescriptor ,
392434 entity_df : Union [pd .DataFrame , str ],
393435 table : pa .Table ,
394- client : fl . FlightClient ,
436+ client : FeastFlightClient ,
395437):
396438 updatedTable : pa .Table
397439
@@ -404,10 +446,20 @@ def _put_parameters(
404446
405447 writer , _ = client .do_put (command_descriptor , updatedTable .schema )
406448
407- writer .write_table (updatedTable )
449+ write_table (writer , updatedTable )
450+
451+
452+ @arrow_client_error_handling_decorator
453+ def write_table (writer , updated_table : pa .Table ):
454+ writer .write_table (updated_table )
408455 writer .close ()
409456
410457
458+ @arrow_client_error_handling_decorator
459+ def read_all (reader ):
460+ return reader .read_all ()
461+
462+
411463def _create_empty_table ():
412464 schema = pa .schema (
413465 {
0 commit comments