Skip to content

Commit 4618566

Browse files
committed
metadata methods
Signed-off-by: Achal Shah <achals@gmail.com>
1 parent d937c0f commit 4618566

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

sdk/python/feast/infra/registry_stores/sql.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140

141141

142142
class SqlRegistry(BaseRegistry):
143+
143144
def __init__(
144145
self, registry_config: Optional[RegistryConfig], repo_path: Optional[Path]
145146
):
@@ -474,6 +475,59 @@ def update_infra(self, infra: Infra, project: str, commit: bool = True):
474475
def get_infra(self, project: str, allow_cache: bool = False) -> Infra:
475476
pass
476477

478+
def apply_user_metadata(self, project: str, feature_view: BaseFeatureView, metadata_bytes: Optional[bytes]):
479+
if isinstance(feature_view, FeatureView):
480+
table = feature_views
481+
elif isinstance(feature_view, OnDemandFeatureView):
482+
table = on_demand_feature_views
483+
elif isinstance(feature_view, RequestFeatureView):
484+
table = request_feature_views
485+
elif isinstance(feature_view, StreamFeatureView):
486+
table = streaming_feature_views
487+
else:
488+
raise ValueError(f"Unexpected feature view type: {type(feature_view)}")
489+
490+
name = feature_view.name
491+
with self.engine.connect() as conn:
492+
stmt = select(table).where(getattr(table.c, "feature_view_name") == name)
493+
row = conn.execute(stmt).first()
494+
update_datetime = datetime.utcnow()
495+
update_time = int(update_datetime.timestamp())
496+
if row:
497+
values = {
498+
"user_metadata": metadata_bytes,
499+
"last_updated_timestamp": update_time,
500+
}
501+
update_stmt = (
502+
update(table)
503+
.where(getattr(table.c, "feature_view_name") == name)
504+
.values(values,)
505+
)
506+
conn.execute(update_stmt)
507+
else:
508+
raise FeatureViewNotFoundException(feature_view.name, project=project)
509+
510+
def get_user_metadata(self, project: str, feature_view: BaseFeatureView) -> Optional[bytes]:
511+
if isinstance(feature_view, FeatureView):
512+
table = feature_views
513+
elif isinstance(feature_view, OnDemandFeatureView):
514+
table = on_demand_feature_views
515+
elif isinstance(feature_view, RequestFeatureView):
516+
table = request_feature_views
517+
elif isinstance(feature_view, StreamFeatureView):
518+
table = streaming_feature_views
519+
else:
520+
raise ValueError(f"Unexpected feature view type: {type(feature_view)}")
521+
522+
name = feature_view.name
523+
with self.engine.connect() as conn:
524+
stmt = select(table).where(getattr(table.c, "feature_view_name") == name)
525+
row = conn.execute(stmt).first()
526+
if row:
527+
return row["user_metadata"]
528+
else:
529+
raise FeatureViewNotFoundException(feature_view.name, project=project)
530+
477531
def proto(self) -> RegistryProto:
478532
r = RegistryProto()
479533
project = ""
@@ -508,6 +562,7 @@ def _apply_object(
508562
update_time = int(update_datetime.timestamp())
509563
if hasattr(obj, "last_updated_timestamp"):
510564
obj.last_updated_timestamp = update_datetime
565+
511566
if row:
512567
values = {
513568
proto_field_name: obj.to_proto().SerializeToString(),
@@ -528,6 +583,7 @@ def _apply_object(
528583
insert_stmt = insert(table).values(values,)
529584
conn.execute(insert_stmt)
530585

586+
531587
def _delete_object(self, table, name, project, id_field_name, not_found_exception):
532588
with self.engine.connect() as conn:
533589
stmt = delete(table).where(getattr(table.c, id_field_name) == name)

sdk/python/feast/registry.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,14 @@ def get_infra(self, project: str, allow_cache: bool = False) -> Infra:
631631
The stored Infra object.
632632
"""
633633

634+
@abstractmethod
635+
def apply_user_metadata(self, project: str, feature_view: BaseFeatureView, metadata_bytes: Optional[bytes]):
636+
...
637+
638+
@abstractmethod
639+
def get_user_metadata(self, project: str, feature_view: BaseFeatureView) -> Optional[bytes]:
640+
...
641+
634642
@abstractmethod
635643
def proto(self) -> RegistryProto:
636644
"""
@@ -654,6 +662,12 @@ class Registry(BaseRegistry):
654662
Registry: A registry allows for the management and persistence of feature definitions and related metadata.
655663
"""
656664

665+
def apply_user_metadata(self, project: str, feature_view: BaseFeatureView, metadata_bytes: Optional[bytes]):
666+
pass
667+
668+
def get_user_metadata(self, project: str, feature_view: BaseFeatureView) -> Optional[bytes]:
669+
pass
670+
657671
# The cached_registry_proto object is used for both reads and writes. In particular,
658672
# all write operations refresh the cache and modify it in memory; the write must
659673
# then be persisted to the underlying RegistryStore with a call to commit().

0 commit comments

Comments
 (0)