3333 CONFIG_ENABLE_AUTH_KEY ,
3434 CONFIG_GRPC_CONNECTION_TIMEOUT_DEFAULT_KEY ,
3535 CONFIG_JOB_SERVICE_ENABLE_SSL_KEY ,
36+ CONFIG_JOB_SERVICE_ENABLED ,
3637 CONFIG_JOB_SERVICE_SERVER_SSL_CERT_KEY ,
3738 CONFIG_JOB_SERVICE_URL_KEY ,
3839 CONFIG_PROJECT_KEY ,
6768)
6869from feast .core .CoreService_pb2_grpc import CoreServiceStub
6970from feast .core .JobService_pb2_grpc import JobServiceStub
71+ from feast .core .JobService_pb2 import (
72+ GetHistoricalFeaturesRequest ,
73+ StartOfflineToOnlineIngestionJobRequest ,
74+ StartStreamToOnlineIngestionJobRequest ,
75+ )
7076from feast .data_format import ParquetFormat
7177from feast .data_source import BigQuerySource , FileSource
7278from feast .entity import Entity
@@ -190,6 +196,10 @@ def _job_service(self):
190196
191197 Returns: JobServiceStub
192198 """
199+ # Don't initialize job service stub if the job service is disabled
200+ if self ._config .get (CONFIG_JOB_SERVICE_ENABLED ) == "False" :
201+ return None
202+
193203 if not self ._job_service_stub :
194204 channel = create_grpc_channel (
195205 url = self ._config .get (CONFIG_JOB_SERVICE_URL_KEY ),
@@ -853,8 +863,9 @@ def get_historical_features(
853863 self ,
854864 feature_refs : List [str ],
855865 entity_source : Union [pd .DataFrame , FileSource , BigQuerySource ],
856- project : str = None ,
857- ) -> RetrievalJob :
866+ project : Optional [str ] = None ,
867+ destination_path : Optional [str ] = None ,
868+ ) -> Union [RetrievalJob , str ]:
858869 """
859870 Launch a historical feature retrieval job.
860871
@@ -873,11 +884,12 @@ def get_historical_features(
873884 retrieval job.
874885 project: Specifies the project that contains the feature tables
875886 which the requested features belong to.
887+ destination_path: Specifies the path in a bucket to write the exported feature data files
876888
877889 Returns:
878- Returns a retrieval job object that can be used to monitor retrieval
879- progress asynchronously, and can be used to materialize the
880- results .
890+ If jobs are launched locally, returns a retrieval job object that can be used to monitor retrieval
891+ progress asynchronously, and can be used to materialize the results.
892+ Otherwise, if jobs are launched through Feast Job Service, returns a job id .
881893
882894 Examples:
883895 >>> from feast import Client
@@ -890,15 +902,6 @@ def get_historical_features(
890902 >>> output_file_uri = feature_retrieval_job.get_output_file_uri()
891903 "gs://some-bucket/output/
892904 """
893- feature_tables = self ._get_feature_tables_from_feature_refs (
894- feature_refs , project
895- )
896- output_location = os .path .join (
897- self ._config .get (CONFIG_SPARK_HISTORICAL_FEATURE_OUTPUT_LOCATION ),
898- str (uuid .uuid4 ()),
899- )
900- output_format = self ._config .get (CONFIG_SPARK_HISTORICAL_FEATURE_OUTPUT_FORMAT )
901-
902905 if isinstance (entity_source , pd .DataFrame ):
903906 staging_location = self ._config .get (CONFIG_SPARK_STAGING_LOCATION )
904907 entity_staging_uri = urlparse (
@@ -922,13 +925,29 @@ def get_historical_features(
922925 entity_staging_uri .geturl (),
923926 )
924927
925- return start_historical_feature_retrieval_job (
926- self ,
927- entity_source ,
928- feature_tables ,
929- output_format ,
930- os .path .join (output_location , str (uuid .uuid4 ())),
931- )
928+ if destination_path is None :
929+ destination_path = self ._config .get (CONFIG_SPARK_HISTORICAL_FEATURE_OUTPUT_LOCATION )
930+ destination_path = os .path .join (destination_path , str (uuid .uuid4 ()))
931+
932+ if not self ._job_service :
933+ feature_tables = self ._get_feature_tables_from_feature_refs (
934+ feature_refs , project
935+ )
936+ output_format = self ._config .get (CONFIG_SPARK_HISTORICAL_FEATURE_OUTPUT_FORMAT )
937+
938+
939+ return start_historical_feature_retrieval_job (
940+ self , entity_source , feature_tables , output_format , destination_path
941+ )
942+ else :
943+ request = GetHistoricalFeaturesRequest (
944+ feature_refs = feature_refs ,
945+ entities_source = entity_source .to_proto (),
946+ project = project ,
947+ destination_path = destination_path ,
948+ )
949+ response = self ._job_service .GetHistoricalFeatures (request )
950+ return response .id
932951
933952 def get_historical_features_df (
934953 self ,
@@ -993,22 +1012,43 @@ def _get_feature_tables_from_feature_refs(
9931012
9941013 def start_offline_to_online_ingestion (
9951014 self , feature_table : FeatureTable , start : datetime , end : datetime ,
996- ) -> SparkJob :
1015+ ) -> Union [ SparkJob , str ] :
9971016 """
9981017
9991018 Launch Ingestion Job from Batch Source to Online Store for given featureTable
10001019
10011020 :param feature_table: FeatureTable which will be ingested
10021021 :param start: lower datetime boundary
10031022 :param end: upper datetime boundary
1004- :return: Spark Job Proxy object
1023+ :return: Spark Job Proxy object if jobs are launched locally,
1024+ or Spark Job ID if jobs are launched through Feast Job Service
10051025 """
1006- return start_offline_to_online_ingestion (feature_table , start , end , self )
1026+ if not self ._job_service :
1027+ return start_offline_to_online_ingestion (feature_table , start , end , self )
1028+ else :
1029+ request = StartOfflineToOnlineIngestionJobRequest (
1030+ project = self .project ,
1031+ table_name = feature_table .name ,
1032+ )
1033+ request .start_date .FromDatetime (start )
1034+ request .end_date .FromDatetime (end )
1035+ response = self ._job_service .StartOfflineToOnlineIngestionJob (request )
1036+ return response .id
10071037
10081038 def start_stream_to_online_ingestion (
10091039 self , feature_table : FeatureTable , extra_jars : Optional [List [str ]] = None ,
1010- ) -> SparkJob :
1011- return start_stream_to_online_ingestion (feature_table , extra_jars or [], self )
1040+ ) -> Union [SparkJob , str ]:
1041+ if not self ._job_service :
1042+ return start_stream_to_online_ingestion (
1043+ feature_table , extra_jars or [], self
1044+ )
1045+ else :
1046+ request = StartStreamToOnlineIngestionJobRequest (
1047+ project = self .project ,
1048+ table_name = feature_table .name ,
1049+ )
1050+ response = self ._job_service .StartStreamToOnlineIngestionJob (request )
1051+ return response .id
10121052
10131053 def stage_dataframe (
10141054 self ,
0 commit comments