fix: Fixed filtering based on data_source for ODFVs (#5593) · feast-dev/feast@c3e6c56
@@ -8,7 +8,9 @@
8899from 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():
107109storage=saved_dataset_storage,
108110tags={"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
110130111131# Apply objects
112132store.apply(
@@ -116,6 +136,7 @@ def fastapi_test_app():
116136user_behavior_feature_view,
117137user_preferences_feature_view,
118138user_feature_service,
139+test_on_demand_feature_view,
119140 ]
120141 )
121142store._registry.apply_saved_dataset(test_saved_dataset, "demo_project")
@@ -181,7 +202,7 @@ def test_feature_views_type_field_via_rest(fastapi_test_app):
181202for fv in data["featureViews"]:
182203assert "type" in fv
183204assert fv["type"] is not None
184-assert fv["type"] == "featureView"
205+assert fv["type"] in ["featureView", "onDemandFeatureView"]
185206186207# Test single endpoint
187208response = 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):
245266data_source_filtered_views = data["featureViews"]
246267assert len(data_source_filtered_views) <= len(all_feature_views)
247268269+# 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+248289response = fastapi_test_app.get(
249290"/feature_views?project=demo_project&feature_service=user_service"
250291 )