Skip to content

Commit 2a6edea

Browse files
authored
feat: Isolate input-dependent calculations in get_online_features (#4041)
refactor get online features Signed-off-by: tokoko <togurg14@freeuni.edu.ge>
1 parent d45fb4e commit 2a6edea

File tree

1 file changed

+63
-34
lines changed

1 file changed

+63
-34
lines changed

sdk/python/feast/feature_store.py

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,22 +1535,11 @@ def get_online_features(
15351535
native_entity_values=True,
15361536
)
15371537

1538-
def _get_online_features(
1539-
self,
1540-
features: Union[List[str], FeatureService],
1541-
entity_values: Mapping[
1542-
str, Union[Sequence[Any], Sequence[Value], RepeatedValue]
1543-
],
1544-
full_feature_names: bool = False,
1545-
native_entity_values: bool = True,
1538+
def _get_online_request_context(
1539+
self, features: Union[List[str], FeatureService], full_feature_names: bool
15461540
):
1547-
# Extract Sequence from RepeatedValue Protobuf.
1548-
entity_value_lists: Dict[str, Union[List[Any], List[Value]]] = {
1549-
k: list(v) if isinstance(v, Sequence) else list(v.val)
1550-
for k, v in entity_values.items()
1551-
}
1552-
15531541
_feature_refs = self._get_features(features, allow_cache=True)
1542+
15541543
(
15551544
requested_feature_views,
15561545
requested_on_demand_feature_views,
@@ -1564,19 +1553,6 @@ def _get_online_features(
15641553
join_keys_set,
15651554
) = self._get_entity_maps(requested_feature_views)
15661555

1567-
entity_proto_values: Dict[str, List[Value]]
1568-
if native_entity_values:
1569-
# Convert values to Protobuf once.
1570-
entity_proto_values = {
1571-
k: python_values_to_proto_values(
1572-
v, entity_type_map.get(k, ValueType.UNKNOWN)
1573-
)
1574-
for k, v in entity_value_lists.items()
1575-
}
1576-
else:
1577-
entity_proto_values = entity_value_lists
1578-
1579-
num_rows = _validate_entity_values(entity_proto_values)
15801556
_validate_feature_refs(_feature_refs, full_feature_names)
15811557
(
15821558
grouped_refs,
@@ -1588,7 +1564,6 @@ def _get_online_features(
15881564
)
15891565
set_usage_attribute("odfv", bool(grouped_odfv_refs))
15901566

1591-
# All requested features should be present in the result.
15921567
requested_result_row_names = {
15931568
feat_ref.replace(":", "__") for feat_ref in _feature_refs
15941569
}
@@ -1601,6 +1576,65 @@ def _get_online_features(
16011576

16021577
needed_request_data = self.get_needed_request_data(grouped_odfv_refs)
16031578

1579+
entityless_case = DUMMY_ENTITY_NAME in [
1580+
entity_name
1581+
for feature_view in feature_views
1582+
for entity_name in feature_view.entities
1583+
]
1584+
1585+
return (
1586+
_feature_refs,
1587+
requested_on_demand_feature_views,
1588+
entity_name_to_join_key_map,
1589+
entity_type_map,
1590+
join_keys_set,
1591+
grouped_refs,
1592+
requested_result_row_names,
1593+
needed_request_data,
1594+
entityless_case,
1595+
)
1596+
1597+
def _get_online_features(
1598+
self,
1599+
features: Union[List[str], FeatureService],
1600+
entity_values: Mapping[
1601+
str, Union[Sequence[Any], Sequence[Value], RepeatedValue]
1602+
],
1603+
full_feature_names: bool = False,
1604+
native_entity_values: bool = True,
1605+
):
1606+
(
1607+
_feature_refs,
1608+
requested_on_demand_feature_views,
1609+
entity_name_to_join_key_map,
1610+
entity_type_map,
1611+
join_keys_set,
1612+
grouped_refs,
1613+
requested_result_row_names,
1614+
needed_request_data,
1615+
entityless_case,
1616+
) = self._get_online_request_context(features, full_feature_names)
1617+
1618+
# Extract Sequence from RepeatedValue Protobuf.
1619+
entity_value_lists: Dict[str, Union[List[Any], List[Value]]] = {
1620+
k: list(v) if isinstance(v, Sequence) else list(v.val)
1621+
for k, v in entity_values.items()
1622+
}
1623+
1624+
entity_proto_values: Dict[str, List[Value]]
1625+
if native_entity_values:
1626+
# Convert values to Protobuf once.
1627+
entity_proto_values = {
1628+
k: python_values_to_proto_values(
1629+
v, entity_type_map.get(k, ValueType.UNKNOWN)
1630+
)
1631+
for k, v in entity_value_lists.items()
1632+
}
1633+
else:
1634+
entity_proto_values = entity_value_lists
1635+
1636+
num_rows = _validate_entity_values(entity_proto_values)
1637+
16041638
join_key_values: Dict[str, List[Value]] = {}
16051639
request_data_features: Dict[str, List[Value]] = {}
16061640
# Entity rows may be either entities or request data.
@@ -1640,11 +1674,6 @@ def _get_online_features(
16401674

16411675
# Add the Entityless case after populating result rows to avoid having to remove
16421676
# it later.
1643-
entityless_case = DUMMY_ENTITY_NAME in [
1644-
entity_name
1645-
for feature_view in feature_views
1646-
for entity_name in feature_view.entities
1647-
]
16481677
if entityless_case:
16491678
join_key_values[DUMMY_ENTITY_ID] = python_values_to_proto_values(
16501679
[DUMMY_ENTITY_VAL] * num_rows, DUMMY_ENTITY.value_type
@@ -1677,7 +1706,7 @@ def _get_online_features(
16771706
table,
16781707
)
16791708

1680-
if grouped_odfv_refs:
1709+
if requested_on_demand_feature_views:
16811710
self._augment_response_with_on_demand_transforms(
16821711
online_features_response,
16831712
_feature_refs,

0 commit comments

Comments
 (0)