8
8
9
9
from feast import Entity , FeatureService , FeatureStore , FeatureView , Field , FileSource
10
10
from feast .api .registry .rest .rest_registry_server import RestRegistryServer
11
+ from feast .data_source import RequestSource
11
12
from feast .infra .offline_stores .file_source import SavedDatasetFileStorage
13
+ from feast .on_demand_feature_view import on_demand_feature_view
12
14
from feast .repo_config import RepoConfig
13
15
from feast .saved_dataset import SavedDataset
14
16
from feast .types import Float64 , Int64
@@ -107,6 +109,24 @@ def fastapi_test_app():
107
109
storage = saved_dataset_storage ,
108
110
tags = {"environment" : "test" , "version" : "1.0" },
109
111
)
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
110
130
111
131
# Apply objects
112
132
store .apply (
@@ -116,6 +136,7 @@ def fastapi_test_app():
116
136
user_behavior_feature_view ,
117
137
user_preferences_feature_view ,
118
138
user_feature_service ,
139
+ test_on_demand_feature_view ,
119
140
]
120
141
)
121
142
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):
181
202
for fv in data ["featureViews" ]:
182
203
assert "type" in fv
183
204
assert fv ["type" ] is not None
184
- assert fv ["type" ] == "featureView"
205
+ assert fv ["type" ] in [ "featureView" , "onDemandFeatureView" ]
185
206
186
207
# Test single endpoint
187
208
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):
245
266
data_source_filtered_views = data ["featureViews" ]
246
267
assert len (data_source_filtered_views ) <= len (all_feature_views )
247
268
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
+
248
289
response = fastapi_test_app .get (
249
290
"/feature_views?project=demo_project&feature_service=user_service"
250
291
)
0 commit comments