Skip to content

Commit 9818798

Browse files
author
Bhargav Dodla
committed
feat: Added list proto methods
1 parent 5571425 commit 9818798

File tree

3 files changed

+270
-0
lines changed

3 files changed

+270
-0
lines changed

sdk/python/feast/infra/registry/caching_registry.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@
1919
from feast.permissions.permission import Permission
2020
from feast.project import Project
2121
from feast.project_metadata import ProjectMetadata
22+
from feast.protos.feast.core.DataSource_pb2 import DataSourceList as DataSourceProtoList
23+
from feast.protos.feast.core.Entity_pb2 import EntityList as EntityProtoList
24+
from feast.protos.feast.core.FeatureService_pb2 import (
25+
FeatureServiceList as FeatureServiceProtoList,
26+
)
27+
from feast.protos.feast.core.FeatureView_pb2 import (
28+
FeatureViewList as FeatureViewProtoList,
29+
)
30+
from feast.protos.feast.core.OnDemandFeatureView_pb2 import (
31+
OnDemandFeatureViewList as OnDemandFeatureViewProtoList,
32+
)
2233
from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto
2334
from feast.saved_dataset import SavedDataset, ValidationReference
2435
from feast.stream_feature_view import StreamFeatureView
@@ -467,3 +478,100 @@ def _start_thread_async_refresh(self, cache_ttl_seconds):
467478

468479
def _exit_handler(self):
469480
self.registry_refresh_thread.cancel()
481+
482+
# Methods to improve the registry calls
483+
484+
@abstractmethod
485+
def _list_feature_views_proto(
486+
self, project: str, tags: Optional[dict[str, str]]
487+
) -> List[FeatureViewProtoList]:
488+
pass
489+
490+
def list_feature_views_proto(
491+
self,
492+
project: str,
493+
allow_cache: bool = False,
494+
tags: Optional[dict[str, str]] = None,
495+
) -> List[FeatureViewProtoList]:
496+
if allow_cache:
497+
self._refresh_cached_registry_if_necessary()
498+
return proto_registry_utils.list_feature_views_proto(
499+
self.cached_registry_proto, project, tags
500+
)
501+
return self._list_feature_views_proto(project, tags)
502+
503+
@abstractmethod
504+
def _list_entities_proto(
505+
self, project: str, tags: Optional[dict[str, str]]
506+
) -> List[EntityProtoList]:
507+
pass
508+
509+
def list_entities_proto(
510+
self,
511+
project: str,
512+
allow_cache: bool = False,
513+
tags: Optional[dict[str, str]] = None,
514+
) -> List[EntityProtoList]:
515+
if allow_cache:
516+
self._refresh_cached_registry_if_necessary()
517+
return proto_registry_utils.list_entities_proto(
518+
self.cached_registry_proto, project, tags
519+
)
520+
return self._list_entities_proto(project, tags)
521+
522+
@abstractmethod
523+
def _list_data_sources_proto(
524+
self, project: str, tags: Optional[dict[str, str]]
525+
) -> List[DataSourceProtoList]:
526+
pass
527+
528+
def list_data_sources_proto(
529+
self,
530+
project: str,
531+
allow_cache: bool = False,
532+
tags: Optional[dict[str, str]] = None,
533+
) -> List[DataSourceProtoList]:
534+
if allow_cache:
535+
self._refresh_cached_registry_if_necessary()
536+
return proto_registry_utils.list_data_sources_proto(
537+
self.cached_registry_proto, project, tags
538+
)
539+
return self._list_data_sources_proto(project, tags)
540+
541+
@abstractmethod
542+
def _list_on_demand_feature_views_proto(
543+
self, project: str, tags: Optional[dict[str, str]]
544+
) -> List[OnDemandFeatureViewProtoList]:
545+
pass
546+
547+
def list_on_demand_feature_views_proto(
548+
self,
549+
project: str,
550+
allow_cache: bool = False,
551+
tags: Optional[dict[str, str]] = None,
552+
) -> List[OnDemandFeatureViewProtoList]:
553+
if allow_cache:
554+
self._refresh_cached_registry_if_necessary()
555+
return proto_registry_utils.list_on_demand_feature_views_proto(
556+
self.cached_registry_proto, project, tags
557+
)
558+
return self._list_on_demand_feature_views_proto(project, tags)
559+
560+
@abstractmethod
561+
def _list_feature_services_proto(
562+
self, project: str, tags: Optional[dict[str, str]]
563+
) -> List[FeatureServiceProtoList]:
564+
pass
565+
566+
def list_feature_services_proto(
567+
self,
568+
project: str,
569+
allow_cache: bool = False,
570+
tags: Optional[dict[str, str]] = None,
571+
) -> List[FeatureServiceProtoList]:
572+
if allow_cache:
573+
self._refresh_cached_registry_if_necessary()
574+
return proto_registry_utils.list_feature_services_proto(
575+
self.cached_registry_proto, project, tags
576+
)
577+
return self._list_feature_services_proto(project, tags)

sdk/python/feast/infra/registry/proto_registry_utils.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
from feast.permissions.permission import Permission
2222
from feast.project import Project
2323
from feast.project_metadata import ProjectMetadata
24+
from feast.protos.feast.core.DataSource_pb2 import DataSourceList as DataSourceProtoList
25+
from feast.protos.feast.core.Entity_pb2 import EntityList as EntityProtoList
26+
from feast.protos.feast.core.FeatureService_pb2 import (
27+
FeatureServiceList as FeatureServiceProtoList,
28+
)
29+
from feast.protos.feast.core.FeatureView_pb2 import (
30+
FeatureViewList as FeatureViewProtoList,
31+
)
32+
from feast.protos.feast.core.OnDemandFeatureView_pb2 import (
33+
OnDemandFeatureViewList as OnDemandFeatureViewProtoList,
34+
)
2435
from feast.protos.feast.core.Registry_pb2 import ProjectMetadata as ProjectMetadataProto
2536
from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto
2637
from feast.saved_dataset import SavedDataset, ValidationReference
@@ -367,3 +378,68 @@ def get_project(registry_proto: RegistryProto, name: str) -> Project:
367378
if projects_proto.spec.name == name:
368379
return Project.from_proto(projects_proto)
369380
raise ProjectObjectNotFoundException(name=name)
381+
382+
383+
@registry_proto_cache_with_tags
384+
def list_feature_views_proto(
385+
registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]]
386+
) -> List[FeatureViewProtoList]:
387+
feature_views: List[FeatureViewProtoList] = []
388+
for feature_view_proto in registry_proto.feature_views:
389+
if feature_view_proto.spec.project == project and utils.has_all_tags(
390+
feature_view_proto.spec.tags, tags
391+
):
392+
feature_views.append(feature_view_proto)
393+
return feature_views
394+
395+
396+
@registry_proto_cache_with_tags
397+
def list_feature_services_proto(
398+
registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]]
399+
) -> List[FeatureServiceProtoList]:
400+
feature_services = []
401+
for feature_service_proto in registry_proto.feature_services:
402+
if feature_service_proto.spec.project == project and utils.has_all_tags(
403+
feature_service_proto.spec.tags, tags
404+
):
405+
feature_services.append(feature_service_proto)
406+
return feature_services
407+
408+
409+
@registry_proto_cache_with_tags
410+
def list_on_demand_feature_views_proto(
411+
registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]]
412+
) -> List[OnDemandFeatureViewProtoList]:
413+
on_demand_feature_views = []
414+
for on_demand_feature_view in registry_proto.on_demand_feature_views:
415+
if on_demand_feature_view.spec.project == project and utils.has_all_tags(
416+
on_demand_feature_view.spec.tags, tags
417+
):
418+
on_demand_feature_views.append(on_demand_feature_view)
419+
return on_demand_feature_views
420+
421+
422+
@registry_proto_cache_with_tags
423+
def list_entities_proto(
424+
registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]]
425+
) -> List[EntityProtoList]:
426+
entities = []
427+
for entity_proto in registry_proto.entities:
428+
if entity_proto.spec.project == project and utils.has_all_tags(
429+
entity_proto.spec.tags, tags
430+
):
431+
entities.append(entity_proto)
432+
return entities
433+
434+
435+
@registry_proto_cache_with_tags
436+
def list_data_sources_proto(
437+
registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]]
438+
) -> List[DataSourceProtoList]:
439+
data_sources = []
440+
for data_source_proto in registry_proto.data_sources:
441+
if data_source_proto.project == project and utils.has_all_tags(
442+
data_source_proto.tags, tags
443+
):
444+
data_sources.append(data_source_proto)
445+
return data_sources

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,26 @@
5050
from feast.project import Project
5151
from feast.project_metadata import ProjectMetadata
5252
from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto
53+
from feast.protos.feast.core.DataSource_pb2 import DataSourceList as DataSourceProtoList
5354
from feast.protos.feast.core.Entity_pb2 import Entity as EntityProto
55+
from feast.protos.feast.core.Entity_pb2 import EntityList as EntityProtoList
5456
from feast.protos.feast.core.FeatureService_pb2 import (
5557
FeatureService as FeatureServiceProto,
5658
)
59+
from feast.protos.feast.core.FeatureService_pb2 import (
60+
FeatureServiceList as FeatureServiceProtoList,
61+
)
5762
from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto
63+
from feast.protos.feast.core.FeatureView_pb2 import (
64+
FeatureViewList as FeatureViewProtoList,
65+
)
5866
from feast.protos.feast.core.InfraObject_pb2 import Infra as InfraProto
5967
from feast.protos.feast.core.OnDemandFeatureView_pb2 import (
6068
OnDemandFeatureView as OnDemandFeatureViewProto,
6169
)
70+
from feast.protos.feast.core.OnDemandFeatureView_pb2 import (
71+
OnDemandFeatureViewList as OnDemandFeatureViewProtoList,
72+
)
6273
from feast.protos.feast.core.Permission_pb2 import Permission as PermissionProto
6374
from feast.protos.feast.core.Project_pb2 import Project as ProjectProto
6475
from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto
@@ -1326,3 +1337,78 @@ def get_project_metadata(
13261337
datetime.utcfromtimestamp(int(metadata_value))
13271338
)
13281339
return project_metadata_model
1340+
1341+
def _list_objects_proto(
1342+
self,
1343+
table: Table,
1344+
project: str,
1345+
proto_class: Any,
1346+
proto_field_name: str,
1347+
tags: Optional[dict[str, str]] = None,
1348+
):
1349+
with self.read_engine.begin() as conn:
1350+
stmt = select(table).where(table.c.project_id == project)
1351+
rows = conn.execute(stmt).all()
1352+
if rows:
1353+
objects = []
1354+
for row in rows:
1355+
obj = proto_class.FromString(row._mapping[proto_field_name])
1356+
if utils.has_all_tags(dict(obj.spec.tags), tags):
1357+
objects.append(obj)
1358+
return objects
1359+
return []
1360+
1361+
def _list_feature_services_proto(
1362+
self, project: str, tags: Optional[dict[str, str]]
1363+
) -> List[FeatureServiceProtoList]:
1364+
return self._list_objects_proto(
1365+
feature_services,
1366+
project,
1367+
FeatureServiceProto,
1368+
"feature_service_proto",
1369+
tags=tags,
1370+
)
1371+
1372+
def _list_feature_views_proto(
1373+
self, project: str, tags: Optional[dict[str, str]]
1374+
) -> List[FeatureViewProtoList]:
1375+
return self._list_objects_proto(
1376+
feature_views,
1377+
project,
1378+
FeatureViewProto,
1379+
"feature_view_proto",
1380+
tags=tags,
1381+
)
1382+
1383+
def _list_on_demand_feature_views_proto(
1384+
self, project: str, tags: Optional[dict[str, str]]
1385+
) -> List[OnDemandFeatureViewProtoList]:
1386+
return self._list_objects_proto(
1387+
on_demand_feature_views,
1388+
project,
1389+
OnDemandFeatureViewProto,
1390+
"feature_view_proto",
1391+
tags=tags,
1392+
)
1393+
1394+
def _list_entities_proto(
1395+
self, project: str, tags: Optional[dict[str, str]]
1396+
) -> List[EntityProtoList]:
1397+
return self._list_objects_proto(
1398+
entities,
1399+
project,
1400+
EntityProto,
1401+
"entity_proto",
1402+
tags=tags,
1403+
)
1404+
1405+
def _list_data_sources_proto(
1406+
self, project: str, tags: Optional[dict[str, str]]
1407+
) -> List[DataSourceProtoList]:
1408+
return self._list_objects_proto(
1409+
data_sources,
1410+
project,
1411+
DataSourceProto,
1412+
"data_source_proto",
1413+
tags=tags,
1414+
)

0 commit comments

Comments
 (0)