88
99from feast import Entity , FeatureService , FeatureStore , FeatureView , Field , FileSource
1010from feast .api .registry .rest .rest_registry_server import RestRegistryServer
11+ from feast .data_source import RequestSource
1112from feast .infra .offline_stores .file_source import SavedDatasetFileStorage
13+ from feast .on_demand_feature_view import on_demand_feature_view
1214from feast .repo_config import RepoConfig
1315from feast .saved_dataset import SavedDataset
1416from feast .types import Float64 , Int64
@@ -107,6 +109,24 @@ def fastapi_test_app():
107109 storage = saved_dataset_storage ,
108110 tags = {"environment" : "test" , "version" : "1.0" },
109111 )
112+ input_request = RequestSource (
113+ name = "input_request_source" ,
114+ schema = [
115+ Field (name = "request_feature" , dtype = Float64 ),
116+ ],
117+ )
118+
119+ @on_demand_feature_view (
120+ sources = [user_profile_feature_view , input_request ],
121+ schema = [
122+ Field (name = "combined_feature" , dtype = Float64 ),
123+ ],
124+ description = "On-demand feature view with request source for testing" ,
125+ )
126+ def test_on_demand_feature_view (features_df : pd .DataFrame ) -> pd .DataFrame :
127+ df = pd .DataFrame ()
128+ df ["combined_feature" ] = features_df ["age" ] + features_df ["request_feature" ]
129+ return df
110130
111131 # Apply objects
112132 store .apply (
@@ -116,6 +136,7 @@ def fastapi_test_app():
116136 user_behavior_feature_view ,
117137 user_preferences_feature_view ,
118138 user_feature_service ,
139+ test_on_demand_feature_view ,
119140 ]
120141 )
121142 store ._registry .apply_saved_dataset (test_saved_dataset , "demo_project" )
@@ -181,7 +202,7 @@ def test_feature_views_type_field_via_rest(fastapi_test_app):
181202 for fv in data ["featureViews" ]:
182203 assert "type" in fv
183204 assert fv ["type" ] is not None
184- assert fv ["type" ] == "featureView"
205+ assert fv ["type" ] in [ "featureView" , "onDemandFeatureView" ]
185206
186207 # Test single endpoint
187208 response = fastapi_test_app .get ("/feature_views/user_profile?project=demo_project" )
@@ -245,6 +266,26 @@ def test_feature_views_comprehensive_filtering_via_rest(fastapi_test_app):
245266 data_source_filtered_views = data ["featureViews" ]
246267 assert len (data_source_filtered_views ) <= len (all_feature_views )
247268
269+ # Test filtering on-demand feature views by request source data source
270+ response = fastapi_test_app .get (
271+ "/feature_views?project=demo_project&data_source=input_request_source"
272+ )
273+ assert response .status_code == 200
274+ data = response .json ()
275+ assert "featureViews" in data
276+ odfv_data_source_filtered_views = data ["featureViews" ]
277+
278+ # Should find the on-demand feature view that uses the request source
279+ assert len (odfv_data_source_filtered_views ) > 0
280+ odfv_found = False
281+ for fv in odfv_data_source_filtered_views :
282+ if fv ["type" ] == "onDemandFeatureView" :
283+ odfv_found = True
284+ break
285+ assert odfv_found , (
286+ "On-demand feature view should be found when filtering by request source data source"
287+ )
288+
248289 response = fastapi_test_app .get (
249290 "/feature_views?project=demo_project&feature_service=user_service"
250291 )
0 commit comments