feat: Added relationship support to all API endpoints (#5496) · feast-dev/feast@bea83e7
@@ -5,21 +5,42 @@
55from feast.api.registry.rest.rest_utils import (
66create_grpc_pagination_params,
77create_grpc_sorting_params,
8+get_object_relationships,
89get_pagination_params,
10+get_relationships_for_objects,
911get_sorting_params,
1012grpc_call,
1113parse_tags,
1214)
1315from feast.registry_server import RegistryServer_pb2
1416151718+def _extract_feature_view_from_any(any_feature_view: dict) -> dict:
19+"""Extract the specific feature view type and data from an AnyFeatureView object.
20+21+ Args:
22+ any_feature_view: Dictionary containing the AnyFeatureView data
23+24+ Returns:
25+ Dictionary with 'type' and feature view data, or empty dict if no valid type found
26+ """
27+for key, value in any_feature_view.items():
28+if value:
29+return {"type": key, **value}
30+31+return {}
32+33+1634def get_feature_view_router(grpc_handler) -> APIRouter:
1735router = APIRouter()
18361937@router.get("/feature_views/{name}")
2038def get_any_feature_view(
2139name: str,
2240project: str = Query(...),
41+include_relationships: bool = Query(
42+False, description="Include relationships for this feature view"
43+ ),
2344allow_cache: bool = Query(True),
2445 ):
2546req = RegistryServer_pb2.GetAnyFeatureViewRequest(
@@ -29,18 +50,24 @@ def get_any_feature_view(
2950 )
3051response = grpc_call(grpc_handler.GetAnyFeatureView, req)
3152any_feature_view = response.get("anyFeatureView", {})
32-feature_view = (
33-any_feature_view.get("featureView")
34-or any_feature_view.get("onDemandFeatureView")
35-or any_feature_view.get("streamFeatureView")
36-or {}
37- )
38-return {"featureView": feature_view}
53+54+result = _extract_feature_view_from_any(any_feature_view)
55+56+if include_relationships:
57+relationships = get_object_relationships(
58+grpc_handler, "featureView", name, project, allow_cache
59+ )
60+result["relationships"] = relationships
61+62+return result
39634064@router.get("/feature_views")
4165def list_all_feature_views(
4266project: str = Query(...),
4367allow_cache: bool = Query(default=True),
68+include_relationships: bool = Query(
69+False, description="Include relationships for each feature view"
70+ ),
4471tags: Dict[str, str] = Depends(parse_tags),
4572pagination_params: dict = Depends(get_pagination_params),
4673sorting_params: dict = Depends(get_sorting_params),
@@ -52,6 +79,27 @@ def list_all_feature_views(
5279pagination=create_grpc_pagination_params(pagination_params),
5380sorting=create_grpc_sorting_params(sorting_params),
5481 )
55-return grpc_call(grpc_handler.ListAllFeatureViews, req)
82+response = grpc_call(grpc_handler.ListAllFeatureViews, req)
83+any_feature_views = response.get("featureViews", [])
84+85+# Extract the specific type of feature view from each AnyFeatureView
86+feature_views = []
87+for any_feature_view in any_feature_views:
88+feature_view = _extract_feature_view_from_any(any_feature_view)
89+if feature_view:
90+feature_views.append(feature_view)
91+92+result = {
93+"featureViews": feature_views,
94+"pagination": response.get("pagination", {}),
95+ }
96+97+if include_relationships:
98+relationships = get_relationships_for_objects(
99+grpc_handler, feature_views, "featureView", project, allow_cache
100+ )
101+result["relationships"] = relationships
102+103+return result
5610457105return router