Skip to content

Commit dd89c3c

Browse files
committed
feature: Add support for online store storage type in create feature … (aws#1098)
1 parent 897cfe4 commit dd89c3c

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

doc/api/prep_data/feature_store.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ Inputs
7777
:members:
7878
:show-inheritance:
7979

80+
.. autoclass:: sagemaker.feature_store.inputs.OnlineStoreStorageTypeEnum
81+
:members:
82+
:show-inheritance:
83+
8084
.. autoclass:: sagemaker.feature_store.inputs.ResourceEnum
8185
:members:
8286
:show-inheritance:

src/sagemaker/feature_store/feature_group.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
DeletionModeEnum,
6464
TtlDuration,
6565
OnlineStoreConfigUpdate,
66+
OnlineStoreStorageTypeEnum,
6667
)
6768
from sagemaker.utils import resolve_value_from_config
6869

@@ -539,6 +540,7 @@ def create(
539540
description: str = None,
540541
tags: List[Dict[str, str]] = None,
541542
table_format: TableFormatEnum = None,
543+
online_store_storage_type: OnlineStoreStorageTypeEnum = None,
542544
) -> Dict[str, Any]:
543545
"""Create a SageMaker FeatureStore FeatureGroup.
544546
@@ -566,6 +568,8 @@ def create(
566568
description (str): description of the FeatureGroup (default: None).
567569
tags (List[Dict[str, str]]): list of tags for labeling a FeatureGroup (default: None).
568570
table_format (TableFormatEnum): format of the offline store table (default: None).
571+
online_store_storage_type (OnlineStoreStorageTypeEnum): storage type for the
572+
online store (default: None).
569573
570574
Returns:
571575
Response dict from service.
@@ -606,6 +610,7 @@ def create(
606610
online_store_config = OnlineStoreConfig(
607611
enable_online_store=enable_online_store,
608612
ttl_duration=ttl_duration,
613+
storage_type=online_store_storage_type,
609614
)
610615
if online_store_kms_key_id is not None:
611616
online_store_config.online_store_security_config = OnlineStoreSecurityConfig(

src/sagemaker/feature_store/inputs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ def to_dict(self) -> Dict[str, Any]:
108108
)
109109

110110

111+
class OnlineStoreStorageTypeEnum(Enum):
112+
"""Enum of storage types for online store.
113+
114+
The online store storage types can be Standard or InMemory.
115+
"""
116+
117+
STANDARD = "Standard"
118+
IN_MEMORY = "InMemory"
119+
120+
111121
@attr.s
112122
class OnlineStoreConfig(Config):
113123
"""OnlineStoreConfig for FeatureStore.
@@ -121,6 +131,7 @@ class OnlineStoreConfig(Config):
121131
enable_online_store: bool = attr.ib(default=True)
122132
online_store_security_config: OnlineStoreSecurityConfig = attr.ib(default=None)
123133
ttl_duration: TtlDuration = attr.ib(default=None)
134+
storage_type: OnlineStoreStorageTypeEnum = attr.ib(default=None)
124135

125136
def to_dict(self) -> Dict[str, Any]:
126137
"""Construct a dictionary based on the attributes.
@@ -132,6 +143,7 @@ def to_dict(self) -> Dict[str, Any]:
132143
EnableOnlineStore=self.enable_online_store,
133144
SecurityConfig=self.online_store_security_config,
134145
TtlDuration=self.ttl_duration,
146+
StorageType=self.storage_type.value if self.storage_type else None,
135147
)
136148

137149

tests/integ/test_feature_store.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
DeletionModeEnum,
3939
TtlDuration,
4040
OnlineStoreConfigUpdate,
41+
OnlineStoreStorageTypeEnum,
4142
)
4243
from sagemaker.feature_store.dataset_builder import (
4344
JoinTypeEnum,
@@ -347,6 +348,54 @@ def test_create_feature_group_glue_table_format(
347348
assert table_format == "Glue"
348349

349350

351+
def test_create_feature_group_in_memory_storage_type(
352+
feature_store_session,
353+
role,
354+
feature_group_name,
355+
pandas_data_frame,
356+
):
357+
feature_group = FeatureGroup(name=feature_group_name, sagemaker_session=feature_store_session)
358+
feature_group.load_feature_definitions(data_frame=pandas_data_frame)
359+
360+
with cleanup_feature_group(feature_group):
361+
feature_group.create(
362+
s3_uri=False,
363+
record_identifier_name="feature1",
364+
event_time_feature_name="feature3",
365+
role_arn=role,
366+
enable_online_store=True,
367+
online_store_storage_type=OnlineStoreStorageTypeEnum.IN_MEMORY,
368+
)
369+
_wait_for_feature_group_create(feature_group)
370+
371+
storage_type = feature_group.describe().get("OnlineStoreConfig").get("StorageType")
372+
assert storage_type == "InMemory"
373+
374+
375+
def test_create_feature_group_standard_storage_type(
376+
feature_store_session,
377+
role,
378+
feature_group_name,
379+
pandas_data_frame,
380+
):
381+
feature_group = FeatureGroup(name=feature_group_name, sagemaker_session=feature_store_session)
382+
feature_group.load_feature_definitions(data_frame=pandas_data_frame)
383+
384+
with cleanup_feature_group(feature_group):
385+
feature_group.create(
386+
s3_uri=False,
387+
record_identifier_name="feature1",
388+
event_time_feature_name="feature3",
389+
role_arn=role,
390+
enable_online_store=True,
391+
online_store_storage_type=OnlineStoreStorageTypeEnum.STANDARD,
392+
)
393+
_wait_for_feature_group_create(feature_group)
394+
395+
storage_type = feature_group.describe().get("OnlineStoreConfig").get("StorageType")
396+
assert storage_type == "Standard"
397+
398+
350399
def test_ttl_duration(
351400
feature_store_session,
352401
role,

tests/unit/sagemaker/feature_store/test_feature_group.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
DeletionModeEnum,
3737
TtlDuration,
3838
OnlineStoreConfigUpdate,
39+
OnlineStoreStorageTypeEnum,
3940
)
4041

4142
from tests.unit import SAGEMAKER_CONFIG_FEATURE_GROUP
@@ -236,6 +237,31 @@ def test_feature_store_create_online_only(
236237
)
237238

238239

240+
def test_feature_store_create_online_only_with_in_memory(
241+
sagemaker_session_mock, role_arn, feature_group_dummy_definitions
242+
):
243+
feature_group = FeatureGroup(name="MyFeatureGroup", sagemaker_session=sagemaker_session_mock)
244+
feature_group.feature_definitions = feature_group_dummy_definitions
245+
feature_group.create(
246+
s3_uri=False,
247+
record_identifier_name="feature1",
248+
event_time_feature_name="feature2",
249+
role_arn=role_arn,
250+
enable_online_store=True,
251+
online_store_storage_type=OnlineStoreStorageTypeEnum.IN_MEMORY,
252+
)
253+
sagemaker_session_mock.create_feature_group.assert_called_with(
254+
feature_group_name="MyFeatureGroup",
255+
record_identifier_name="feature1",
256+
event_time_feature_name="feature2",
257+
feature_definitions=[fd.to_dict() for fd in feature_group_dummy_definitions],
258+
role_arn=role_arn,
259+
description=None,
260+
tags=None,
261+
online_store_config={"EnableOnlineStore": True, "StorageType": "InMemory"},
262+
)
263+
264+
239265
def test_feature_store_delete(sagemaker_session_mock):
240266
feature_group = FeatureGroup(name="MyFeatureGroup", sagemaker_session=sagemaker_session_mock)
241267
feature_group.delete()

tests/unit/sagemaker/feature_store/test_inputs.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
OfflineStoreConfig,
2222
FeatureParameter,
2323
TableFormatEnum,
24+
OnlineStoreStorageTypeEnum,
2425
Filter,
2526
FilterOperatorEnum,
2627
Identifier,
@@ -59,6 +60,32 @@ def test_online_store_config():
5960
}
6061
)
6162

63+
config_with_inmemory = OnlineStoreConfig(
64+
enable_online_store=True,
65+
storage_type=OnlineStoreStorageTypeEnum.IN_MEMORY,
66+
)
67+
assert ordered(config_with_inmemory.to_dict()) == ordered(
68+
{
69+
"EnableOnlineStore": True,
70+
"StorageType": "InMemory",
71+
}
72+
)
73+
74+
config_with_kms_standard = OnlineStoreConfig(
75+
enable_online_store=True,
76+
online_store_security_config=OnlineStoreSecurityConfig(kms_key_id="kms"),
77+
storage_type=OnlineStoreStorageTypeEnum.STANDARD,
78+
)
79+
assert ordered(config_with_kms_standard.to_dict()) == ordered(
80+
{
81+
"EnableOnlineStore": True,
82+
"SecurityConfig": {
83+
"KmsKeyId": "kms",
84+
},
85+
"StorageType": "Standard",
86+
}
87+
)
88+
6289

6390
def test_s3_store_config():
6491
config = S3StorageConfig(s3_uri="uri", kms_key_id="kms")

0 commit comments

Comments
 (0)