fix: Fixed filtering based on data_source for ODFVs (#5593) · feast-dev/feast@c3e6c56

@@ -8,7 +8,9 @@

8899

from feast import Entity, FeatureService, FeatureStore, FeatureView, Field, FileSource

1010

from feast.api.registry.rest.rest_registry_server import RestRegistryServer

11+

from feast.data_source import RequestSource

1112

from feast.infra.offline_stores.file_source import SavedDatasetFileStorage

13+

from feast.on_demand_feature_view import on_demand_feature_view

1214

from feast.repo_config import RepoConfig

1315

from feast.saved_dataset import SavedDataset

1416

from 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

110130111131

# 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"]

185206186207

# 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)

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+248289

response = fastapi_test_app.get(

249290

"/feature_views?project=demo_project&feature_service=user_service"

250291

)