1- import pathlib
21from typing import TYPE_CHECKING , List , Union
32
3+ from datetime import datetime
4+ from urllib .parse import urlparse
5+ import tempfile
6+ import shutil
7+
48from feast .config import Config
5- from feast .constants import (
6- CONFIG_SPARK_DATAPROC_CLUSTER_NAME ,
7- CONFIG_SPARK_DATAPROC_PROJECT ,
8- CONFIG_SPARK_DATAPROC_REGION ,
9- CONFIG_SPARK_DATAPROC_STAGING_LOCATION ,
10- CONFIG_SPARK_LAUNCHER ,
11- CONFIG_SPARK_STANDALONE_MASTER ,
12- )
9+ from feast .constants import *
1310from feast .data_source import BigQuerySource , DataSource , FileSource
1411from feast .feature_table import FeatureTable
15- from feast .pyspark .abc import JobLauncher , RetrievalJob
12+ from feast .pyspark .abc import JobLauncher , RetrievalJob , IngestionJob
1613from feast .value_type import ValueType
14+ from feast .staging .storage_client import get_staging_client
1715
1816if TYPE_CHECKING :
1917 from feast .client import Client
@@ -23,7 +21,7 @@ def _standalone_launcher(config: Config) -> JobLauncher:
2321 from feast .pyspark .launchers import standalone
2422
2523 return standalone .StandaloneClusterLauncher (
26- config .get (CONFIG_SPARK_STANDALONE_MASTER )
24+ config .get (CONFIG_SPARK_STANDALONE_MASTER ), config . get ( CONFIG_SPARK_HOME )
2725 )
2826
2927
@@ -51,7 +49,7 @@ def resolve_launcher(config: Config) -> JobLauncher:
5149}
5250
5351
54- def source_to_argument (source : DataSource ):
52+ def _source_to_argument (source : DataSource ):
5553 common_properties = {
5654 "field_mapping" : dict (source .field_mapping ),
5755 "event_timestamp_column" : source .event_timestamp_column ,
@@ -72,7 +70,7 @@ def source_to_argument(source: DataSource):
7270 return {kind : properties }
7371
7472
75- def feature_table_to_argument (client : "Client" , feature_table : FeatureTable ):
73+ def _feature_table_to_argument (client : "Client" , feature_table : FeatureTable ):
7674 return {
7775 "features" : [
7876 {"name" : f .name , "type" : ValueType (f .dtype ).name }
@@ -102,13 +100,13 @@ def start_historical_feature_retrieval_spark_session(
102100 spark_session = SparkSession .builder .getOrCreate ()
103101 return retrieve_historical_features (
104102 spark = spark_session ,
105- entity_source_conf = source_to_argument (entity_source ),
103+ entity_source_conf = _source_to_argument (entity_source ),
106104 feature_tables_sources_conf = [
107- source_to_argument (feature_table .batch_source )
105+ _source_to_argument (feature_table .batch_source )
108106 for feature_table in feature_tables
109107 ],
110108 feature_tables_conf = [
111- feature_table_to_argument (client , feature_table )
109+ _feature_table_to_argument (client , feature_table )
112110 for feature_table in feature_tables
113111 ],
114112 )
@@ -123,22 +121,45 @@ def start_historical_feature_retrieval_job(
123121 job_id : str ,
124122) -> RetrievalJob :
125123 launcher = resolve_launcher (client ._config )
126- retrieval_job_pyspark_script = str (
127- pathlib .Path (__file__ ).parent .absolute ()
128- / "pyspark"
129- / "historical_feature_retrieval_job.py"
130- )
131124 return launcher .historical_feature_retrieval (
132- pyspark_script = retrieval_job_pyspark_script ,
133- entity_source_conf = source_to_argument (entity_source ),
125+ entity_source_conf = _source_to_argument (entity_source ),
134126 feature_tables_sources_conf = [
135- source_to_argument (feature_table .batch_source )
127+ _source_to_argument (feature_table .batch_source )
136128 for feature_table in feature_tables
137129 ],
138130 feature_tables_conf = [
139- feature_table_to_argument (client , feature_table )
131+ _feature_table_to_argument (client , feature_table )
140132 for feature_table in feature_tables
141133 ],
142134 destination_conf = {"format" : output_format , "path" : output_path },
143135 job_id = job_id ,
144136 )
137+
138+
139+ def _download_jar (remote_jar : str ) -> str :
140+ remote_jar_parts = urlparse (remote_jar )
141+
142+ f = tempfile .NamedTemporaryFile (suffix = ".jar" , delete = False )
143+ with f :
144+ shutil .copyfileobj (
145+ get_staging_client (remote_jar_parts .scheme ).download_file (remote_jar_parts ),
146+ f ,
147+ )
148+
149+ return f .name
150+
151+
152+ def start_offline_to_online_ingestion (
153+ feature_table : FeatureTable , start : datetime , end : datetime , client : Client
154+ ) -> IngestionJob :
155+
156+ launcher = resolve_launcher (client ._config )
157+ local_jar_path = _download_jar (client ._config .get (CONFIG_SPARK_INGESTION_JOB_JAR ))
158+
159+ return launcher .offline_to_online_ingestion (
160+ jar_path = local_jar_path ,
161+ source_conf = _source_to_argument (feature_table .batch_source ),
162+ feature_table_conf = _feature_table_to_argument (client , feature_table ),
163+ start = start ,
164+ end = end ,
165+ )
0 commit comments