Skip to content

Commit 41be511

Browse files
authored
fix: FeatureStore.apply applies BatchFeatureView correctly (#3098)
Signed-off-by: Achal Shah <[email protected]> Signed-off-by: Achal Shah <[email protected]>
1 parent 2646a86 commit 41be511

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

sdk/python/feast/feast_object.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Union
22

3+
from .batch_feature_view import BatchFeatureView
34
from .data_source import DataSource
45
from .entity import Entity
56
from .feature_service import FeatureService
@@ -16,12 +17,15 @@
1617
)
1718
from .request_feature_view import RequestFeatureView
1819
from .saved_dataset import ValidationReference
20+
from .stream_feature_view import StreamFeatureView
1921

2022
# Convenience type representing all Feast objects
2123
FeastObject = Union[
2224
FeatureView,
2325
OnDemandFeatureView,
2426
RequestFeatureView,
27+
BatchFeatureView,
28+
StreamFeatureView,
2529
Entity,
2630
FeatureService,
2731
DataSource,

sdk/python/feast/feature_store.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ def apply(
775775
FeatureView,
776776
OnDemandFeatureView,
777777
RequestFeatureView,
778+
BatchFeatureView,
778779
StreamFeatureView,
779780
FeatureService,
780781
ValidationReference,
@@ -834,9 +835,9 @@ def apply(
834835
ob
835836
for ob in objects
836837
if (
837-
isinstance(ob, FeatureView)
838+
# BFVs are not handled separately from FVs right now.
839+
(isinstance(ob, FeatureView) or isinstance(ob, BatchFeatureView))
838840
and not isinstance(ob, StreamFeatureView)
839-
and not isinstance(ob, BatchFeatureView)
840841
)
841842
]
842843
sfvs_to_update = [ob for ob in objects if isinstance(ob, StreamFeatureView)]
@@ -919,13 +920,18 @@ def apply(
919920
validation_references, project=self.project, commit=False
920921
)
921922

923+
entities_to_delete = []
924+
views_to_delete = []
925+
sfvs_to_delete = []
922926
if not partial:
923927
# Delete all registry objects that should not exist.
924928
entities_to_delete = [
925929
ob for ob in objects_to_delete if isinstance(ob, Entity)
926930
]
927931
views_to_delete = [
928-
ob for ob in objects_to_delete if isinstance(ob, FeatureView)
932+
ob
933+
for ob in objects_to_delete
934+
if isinstance(ob, FeatureView) or isinstance(ob, BatchFeatureView)
929935
]
930936
request_views_to_delete = [
931937
ob for ob in objects_to_delete if isinstance(ob, RequestFeatureView)
@@ -979,10 +985,13 @@ def apply(
979985
validation_references.name, project=self.project, commit=False
980986
)
981987

988+
tables_to_delete: List[FeatureView] = views_to_delete + sfvs_to_delete if not partial else [] # type: ignore
989+
tables_to_keep: List[FeatureView] = views_to_update + sfvs_to_update # type: ignore
990+
982991
self._get_provider().update_infra(
983992
project=self.project,
984-
tables_to_delete=views_to_delete + sfvs_to_delete if not partial else [],
985-
tables_to_keep=views_to_update + sfvs_to_update,
993+
tables_to_delete=tables_to_delete,
994+
tables_to_keep=tables_to_keep,
986995
entities_to_delete=entities_to_delete if not partial else [],
987996
entities_to_keep=entities_to_update,
988997
partial=partial,

sdk/python/tests/unit/local_feast_tests/test_local_feature_store.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
from pytest_lazyfixture import lazy_fixture
66

7+
from feast import BatchFeatureView
78
from feast.aggregation import Aggregation
89
from feast.data_format import AvroFormat, ParquetFormat
910
from feast.data_source import KafkaSource
@@ -78,14 +79,29 @@ def test_apply_feature_view(test_feature_store):
7879
ttl=timedelta(minutes=5),
7980
)
8081

82+
bfv = BatchFeatureView(
83+
name="batch_feature_view",
84+
schema=[
85+
Field(name="fs1_my_feature_1", dtype=Int64),
86+
Field(name="fs1_my_feature_2", dtype=String),
87+
Field(name="fs1_my_feature_3", dtype=Array(String)),
88+
Field(name="fs1_my_feature_4", dtype=Array(Bytes)),
89+
Field(name="entity_id", dtype=Int64),
90+
],
91+
entities=[entity],
92+
tags={"team": "matchmaking"},
93+
source=batch_source,
94+
ttl=timedelta(minutes=5),
95+
)
96+
8197
# Register Feature View
82-
test_feature_store.apply([entity, fv1])
98+
test_feature_store.apply([entity, fv1, bfv])
8399

84100
feature_views = test_feature_store.list_feature_views()
85101

86102
# List Feature Views
87103
assert (
88-
len(feature_views) == 1
104+
len(feature_views) == 2
89105
and feature_views[0].name == "my_feature_view_1"
90106
and feature_views[0].features[0].name == "fs1_my_feature_1"
91107
and feature_views[0].features[0].dtype == Int64

0 commit comments

Comments
 (0)