From bf7fd75bf601a7b0a2dd0bb9b8f2c750730620fa Mon Sep 17 00:00:00 2001 From: ntkathole Date: Wed, 22 Jul 2026 10:49:17 +0530 Subject: [PATCH 1/2] feat: Added optional namespace/colleciton to datasets Signed-off-by: ntkathole --- protos/feast/core/SavedDataset.proto | 13 ++ protos/feast/registry/RegistryServer.proto | 4 + .../feast/api/registry/rest/saved_datasets.py | 27 ++++ sdk/python/feast/feature_store.py | 14 +- .../feast/infra/registry/base_registry.py | 4 + .../feast/infra/registry/caching_registry.py | 18 ++- .../infra/registry/proto_registry_utils.py | 19 ++- sdk/python/feast/infra/registry/registry.py | 10 +- sdk/python/feast/infra/registry/remote.py | 8 +- sdk/python/feast/infra/registry/snowflake.py | 15 +- sdk/python/feast/infra/registry/sql.py | 14 +- .../protos/feast/core/SavedDataset_pb2.py | 20 +-- .../protos/feast/core/SavedDataset_pb2.pyi | 20 ++- .../feast/registry/RegistryServer_pb2.py | 152 +++++++++--------- .../feast/registry/RegistryServer_pb2.pyi | 10 +- sdk/python/feast/registry_server.py | 4 + sdk/python/feast/saved_dataset.py | 18 +++ 17 files changed, 266 insertions(+), 104 deletions(-) diff --git a/protos/feast/core/SavedDataset.proto b/protos/feast/core/SavedDataset.proto index 111548aa480..c4a65accd36 100644 --- a/protos/feast/core/SavedDataset.proto +++ b/protos/feast/core/SavedDataset.proto @@ -48,6 +48,19 @@ message SavedDatasetSpec { // User defined metadata map tags = 7; + + // Optional logical namespace for hierarchical grouping. + // Maps to the top-level prefix in Iceberg REST Catalog API. + // Empty string means not set (no namespace scoping). + string namespace = 9; + + // Optional sub-grouping within a namespace. + // Maps to the namespace level in Iceberg REST Catalog API. + // Empty string means not set (dataset sits directly under namespace). + string collection = 10; + + // Description of the saved dataset. + string description = 11; } message SavedDatasetStorage { diff --git a/protos/feast/registry/RegistryServer.proto b/protos/feast/registry/RegistryServer.proto index cd60d47939f..2906e8a80b5 100644 --- a/protos/feast/registry/RegistryServer.proto +++ b/protos/feast/registry/RegistryServer.proto @@ -417,6 +417,10 @@ message ListSavedDatasetsRequest { map tags = 3; PaginationParams pagination = 4; SortingParams sorting = 5; + // Optional logical namespace filter. Empty string means no filter. + string namespace = 6; + // Optional collection filter. Empty string means no filter. + string collection = 7; } message ListSavedDatasetsResponse { diff --git a/sdk/python/feast/api/registry/rest/saved_datasets.py b/sdk/python/feast/api/registry/rest/saved_datasets.py index 4509c65f53d..ff6993183c2 100644 --- a/sdk/python/feast/api/registry/rest/saved_datasets.py +++ b/sdk/python/feast/api/registry/rest/saved_datasets.py @@ -43,6 +43,9 @@ class RegisterDatasetRequest(BaseModel): full_feature_names: bool = False feature_service_name: Optional[str] = None allow_override: bool = False + namespace: str = "" + collection: str = "" + description: str = "" class CreateDatasetRequest(BaseModel): @@ -75,10 +78,22 @@ def list_saved_datasets_all( limit: int = Query(50, ge=1, le=100), sort_by: str = Query(None), sort_order: str = Query("asc"), + namespace: Optional[str] = Query( + None, description="Filter by namespace (logical grouping)" + ), + collection: Optional[str] = Query( + None, description="Filter by collection (sub-grouping within namespace)" + ), include_relationships: bool = Query( False, description="Include relationships for each saved dataset" ), ): + extra_params = {} + if namespace is not None: + extra_params["namespace"] = namespace + if collection is not None: + extra_params["collection"] = collection + return aggregate_across_projects( grpc_handler=grpc_handler, list_method=grpc_handler.ListSavedDatasets, @@ -91,6 +106,7 @@ def list_saved_datasets_all( sort_by=sort_by, sort_order=sort_order, include_relationships=include_relationships, + extra_request_params=extra_params or None, ) @router.get("/saved_datasets/data/{name}") @@ -230,6 +246,12 @@ def list_saved_datasets( project: str = Query(...), allow_cache: bool = Query(default=True), tags: Dict[str, str] = Depends(parse_tags), + namespace: Optional[str] = Query( + None, description="Filter by namespace (logical grouping)" + ), + collection: Optional[str] = Query( + None, description="Filter by collection (sub-grouping within namespace)" + ), include_relationships: bool = Query( False, description="Include relationships for each saved dataset" ), @@ -240,6 +262,8 @@ def list_saved_datasets( project=project, allow_cache=allow_cache, tags=tags, + namespace=namespace or "", + collection=collection or "", pagination=create_grpc_pagination_params(pagination_params), sorting=create_grpc_sorting_params(sorting_params), ) @@ -347,6 +371,9 @@ def register_saved_dataset(payload: RegisterDatasetRequest = Body(...)): full_feature_names=payload.full_feature_names, storage=storage_proto, tags=payload.tags, + namespace=payload.namespace, + collection=payload.collection, + description=payload.description, ) if payload.feature_service_name: spec.feature_service_name = payload.feature_service_name diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index a35b02f3319..c9888768003 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -4770,7 +4770,11 @@ def delete_project(self, name: str, commit: bool = True) -> None: return self.registry.delete_project(name, commit=commit) def list_saved_datasets( - self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None + self, + allow_cache: bool = False, + tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: """ Retrieves the list of saved datasets from the registry. @@ -4778,12 +4782,18 @@ def list_saved_datasets( Args: allow_cache: Whether to allow returning saved datasets from a cached registry. tags: Filter by tags. + namespace: Filter by logical namespace grouping. + collection: Filter by collection sub-grouping within namespace. Returns: A list of saved datasets. """ return self.registry.list_saved_datasets( - self.project, allow_cache=allow_cache, tags=tags + self.project, + allow_cache=allow_cache, + tags=tags, + namespace=namespace, + collection=collection, ) async def initialize(self) -> None: diff --git a/sdk/python/feast/infra/registry/base_registry.py b/sdk/python/feast/infra/registry/base_registry.py index a0d98d5d2c2..4256c82e50d 100644 --- a/sdk/python/feast/infra/registry/base_registry.py +++ b/sdk/python/feast/infra/registry/base_registry.py @@ -698,6 +698,8 @@ def list_saved_datasets( project: str, allow_cache: bool = False, tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: """ Retrieves a list of all saved datasets in specified project @@ -706,6 +708,8 @@ def list_saved_datasets( project: Feast project allow_cache: Whether to allow returning this dataset from a cached registry tags: Filter by tags + namespace: Filter by logical namespace grouping + collection: Filter by collection sub-grouping within namespace Returns: Returns the list of SavedDatasets diff --git a/sdk/python/feast/infra/registry/caching_registry.py b/sdk/python/feast/infra/registry/caching_registry.py index 6780a2ece69..81fc11ed025 100644 --- a/sdk/python/feast/infra/registry/caching_registry.py +++ b/sdk/python/feast/infra/registry/caching_registry.py @@ -344,7 +344,11 @@ def get_saved_dataset( @abstractmethod def _list_saved_datasets( - self, project: str, tags: Optional[dict[str, str]] = None + self, + project: str, + tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: pass @@ -353,13 +357,21 @@ def list_saved_datasets( project: str, allow_cache: bool = False, tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: if allow_cache: self._refresh_cached_registry_if_necessary() return proto_registry_utils.list_saved_datasets( - self.cached_registry_proto, project, tags + self.cached_registry_proto, + project, + tags, + namespace=namespace, + collection=collection, ) - return self._list_saved_datasets(project, tags) + return self._list_saved_datasets( + project, tags, namespace=namespace, collection=collection + ) @abstractmethod def _get_validation_reference(self, name: str, project: str) -> ValidationReference: diff --git a/sdk/python/feast/infra/registry/proto_registry_utils.py b/sdk/python/feast/infra/registry/proto_registry_utils.py index de5d199555b..2be5e7f2cb6 100644 --- a/sdk/python/feast/infra/registry/proto_registry_utils.py +++ b/sdk/python/feast/infra/registry/proto_registry_utils.py @@ -418,14 +418,23 @@ def list_data_sources( @registry_proto_cache_with_tags def list_saved_datasets( - registry_proto: RegistryProto, project: str, tags: Optional[dict[str, str]] + registry_proto: RegistryProto, + project: str, + tags: Optional[dict[str, str]], + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: saved_datasets = [] for saved_dataset in registry_proto.saved_datasets: - if saved_dataset.spec.project == project and utils.has_all_tags( - saved_dataset.spec.tags, tags - ): - saved_datasets.append(SavedDataset.from_proto(saved_dataset)) + if saved_dataset.spec.project != project: + continue + if not utils.has_all_tags(saved_dataset.spec.tags, tags): + continue + if namespace is not None and saved_dataset.spec.namespace != namespace: + continue + if collection is not None and saved_dataset.spec.collection != collection: + continue + saved_datasets.append(SavedDataset.from_proto(saved_dataset)) return saved_datasets diff --git a/sdk/python/feast/infra/registry/registry.py b/sdk/python/feast/infra/registry/registry.py index f09f05e971f..78994f5b8c3 100644 --- a/sdk/python/feast/infra/registry/registry.py +++ b/sdk/python/feast/infra/registry/registry.py @@ -1305,11 +1305,19 @@ def list_saved_datasets( project: str, allow_cache: bool = False, tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: registry_proto = self._get_registry_proto( project=project, allow_cache=allow_cache ) - return proto_registry_utils.list_saved_datasets(registry_proto, project, tags) + return proto_registry_utils.list_saved_datasets( + registry_proto, + project, + tags, + namespace=namespace, + collection=collection, + ) def delete_saved_dataset(self, name: str, project: str, commit: bool = True): self._prepare_registry_for_changes(project) diff --git a/sdk/python/feast/infra/registry/remote.py b/sdk/python/feast/infra/registry/remote.py index 287eb3fda17..43550a49882 100644 --- a/sdk/python/feast/infra/registry/remote.py +++ b/sdk/python/feast/infra/registry/remote.py @@ -511,9 +511,15 @@ def list_saved_datasets( project: str, allow_cache: bool = False, tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: request = RegistryServer_pb2.ListSavedDatasetsRequest( - project=project, allow_cache=allow_cache, tags=tags + project=project, + allow_cache=allow_cache, + tags=tags, + namespace=namespace or "", + collection=collection or "", ) response = self.stub.ListSavedDatasets(request) return [ diff --git a/sdk/python/feast/infra/registry/snowflake.py b/sdk/python/feast/infra/registry/snowflake.py index 5590e1b7574..c04ea65b7df 100644 --- a/sdk/python/feast/infra/registry/snowflake.py +++ b/sdk/python/feast/infra/registry/snowflake.py @@ -945,13 +945,19 @@ def list_saved_datasets( project: str, allow_cache: bool = False, tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, ) -> List[SavedDataset]: if allow_cache: registry_proto = self._refresh_cached_registry_if_necessary() return proto_registry_utils.list_saved_datasets( - registry_proto, project, tags + registry_proto, + project, + tags, + namespace=namespace, + collection=collection, ) - return self._list_objects( + results = self._list_objects( "SAVED_DATASETS", project, SavedDatasetProto, @@ -959,6 +965,11 @@ def list_saved_datasets( "SAVED_DATASET_PROTO", tags=tags, ) + if namespace is not None: + results = [sd for sd in results if sd.namespace == namespace] + if collection is not None: + results = [sd for sd in results if sd.collection == collection] + return results def list_stream_feature_views( self, diff --git a/sdk/python/feast/infra/registry/sql.py b/sdk/python/feast/infra/registry/sql.py index edd89347be2..32fc7dd07f0 100644 --- a/sdk/python/feast/infra/registry/sql.py +++ b/sdk/python/feast/infra/registry/sql.py @@ -1076,9 +1076,14 @@ def _list_feature_views( ) def _list_saved_datasets( - self, project: str, tags: Optional[dict[str, str]] = None, **kwargs + self, + project: str, + tags: Optional[dict[str, str]] = None, + namespace: Optional[str] = None, + collection: Optional[str] = None, + **kwargs, ) -> List[SavedDataset]: - return self._list_objects( + results = self._list_objects( saved_datasets, project, SavedDatasetProto, @@ -1087,6 +1092,11 @@ def _list_saved_datasets( tags=tags, **kwargs, ) + if namespace is not None: + results = [sd for sd in results if sd.namespace == namespace] + if collection is not None: + results = [sd for sd in results if sd.collection == collection] + return results def _list_on_demand_feature_views( self, project: str, tags: Optional[dict[str, str]], **kwargs diff --git a/sdk/python/feast/protos/feast/core/SavedDataset_pb2.py b/sdk/python/feast/protos/feast/core/SavedDataset_pb2.py index fe1e2d49eac..8e394dec7ec 100644 --- a/sdk/python/feast/protos/feast/core/SavedDataset_pb2.py +++ b/sdk/python/feast/protos/feast/core/SavedDataset_pb2.py @@ -16,7 +16,7 @@ from feast.protos.feast.core import DataSource_pb2 as feast_dot_core_dot_DataSource__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66\x65\x61st/core/SavedDataset.proto\x12\nfeast.core\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\"\xa5\x02\n\x10SavedDatasetSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x66\x65\x61tures\x18\x03 \x03(\t\x12\x11\n\tjoin_keys\x18\x04 \x03(\t\x12\x1a\n\x12\x66ull_feature_names\x18\x05 \x01(\x08\x12\x30\n\x07storage\x18\x06 \x01(\x0b\x32\x1f.feast.core.SavedDatasetStorage\x12\x1c\n\x14\x66\x65\x61ture_service_name\x18\x08 \x01(\t\x12\x34\n\x04tags\x18\x07 \x03(\x0b\x32&.feast.core.SavedDatasetSpec.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xa9\x04\n\x13SavedDatasetStorage\x12:\n\x0c\x66ile_storage\x18\x04 \x01(\x0b\x32\".feast.core.DataSource.FileOptionsH\x00\x12\x42\n\x10\x62igquery_storage\x18\x05 \x01(\x0b\x32&.feast.core.DataSource.BigQueryOptionsH\x00\x12\x42\n\x10redshift_storage\x18\x06 \x01(\x0b\x32&.feast.core.DataSource.RedshiftOptionsH\x00\x12\x44\n\x11snowflake_storage\x18\x07 \x01(\x0b\x32\'.feast.core.DataSource.SnowflakeOptionsH\x00\x12<\n\rtrino_storage\x18\x08 \x01(\x0b\x32#.feast.core.DataSource.TrinoOptionsH\x00\x12<\n\rspark_storage\x18\t \x01(\x0b\x32#.feast.core.DataSource.SparkOptionsH\x00\x12\x44\n\x0e\x63ustom_storage\x18\n \x01(\x0b\x32*.feast.core.DataSource.CustomSourceOptionsH\x00\x12>\n\x0e\x61thena_storage\x18\x0b \x01(\x0b\x32$.feast.core.DataSource.AthenaOptionsH\x00\x42\x06\n\x04kind\"\xf7\x01\n\x10SavedDatasetMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13min_event_timestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13max_event_timestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"f\n\x0cSavedDataset\x12*\n\x04spec\x18\x01 \x01(\x0b\x32\x1c.feast.core.SavedDatasetSpec\x12*\n\x04meta\x18\x02 \x01(\x0b\x32\x1c.feast.core.SavedDatasetMetaBV\n\x10\x66\x65\x61st.proto.coreB\x11SavedDatasetProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66\x65\x61st/core/SavedDataset.proto\x12\nfeast.core\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\"\xe1\x02\n\x10SavedDatasetSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x66\x65\x61tures\x18\x03 \x03(\t\x12\x11\n\tjoin_keys\x18\x04 \x03(\t\x12\x1a\n\x12\x66ull_feature_names\x18\x05 \x01(\x08\x12\x30\n\x07storage\x18\x06 \x01(\x0b\x32\x1f.feast.core.SavedDatasetStorage\x12\x1c\n\x14\x66\x65\x61ture_service_name\x18\x08 \x01(\t\x12\x34\n\x04tags\x18\x07 \x03(\x0b\x32&.feast.core.SavedDatasetSpec.TagsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x12\n\ncollection\x18\n \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x0b \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xa9\x04\n\x13SavedDatasetStorage\x12:\n\x0c\x66ile_storage\x18\x04 \x01(\x0b\x32\".feast.core.DataSource.FileOptionsH\x00\x12\x42\n\x10\x62igquery_storage\x18\x05 \x01(\x0b\x32&.feast.core.DataSource.BigQueryOptionsH\x00\x12\x42\n\x10redshift_storage\x18\x06 \x01(\x0b\x32&.feast.core.DataSource.RedshiftOptionsH\x00\x12\x44\n\x11snowflake_storage\x18\x07 \x01(\x0b\x32\'.feast.core.DataSource.SnowflakeOptionsH\x00\x12<\n\rtrino_storage\x18\x08 \x01(\x0b\x32#.feast.core.DataSource.TrinoOptionsH\x00\x12<\n\rspark_storage\x18\t \x01(\x0b\x32#.feast.core.DataSource.SparkOptionsH\x00\x12\x44\n\x0e\x63ustom_storage\x18\n \x01(\x0b\x32*.feast.core.DataSource.CustomSourceOptionsH\x00\x12>\n\x0e\x61thena_storage\x18\x0b \x01(\x0b\x32$.feast.core.DataSource.AthenaOptionsH\x00\x42\x06\n\x04kind\"\xf7\x01\n\x10SavedDatasetMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13min_event_timestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13max_event_timestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"f\n\x0cSavedDataset\x12*\n\x04spec\x18\x01 \x01(\x0b\x32\x1c.feast.core.SavedDatasetSpec\x12*\n\x04meta\x18\x02 \x01(\x0b\x32\x1c.feast.core.SavedDatasetMetaBV\n\x10\x66\x65\x61st.proto.coreB\x11SavedDatasetProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -27,13 +27,13 @@ _globals['_SAVEDDATASETSPEC_TAGSENTRY']._options = None _globals['_SAVEDDATASETSPEC_TAGSENTRY']._serialized_options = b'8\001' _globals['_SAVEDDATASETSPEC']._serialized_start=108 - _globals['_SAVEDDATASETSPEC']._serialized_end=401 - _globals['_SAVEDDATASETSPEC_TAGSENTRY']._serialized_start=358 - _globals['_SAVEDDATASETSPEC_TAGSENTRY']._serialized_end=401 - _globals['_SAVEDDATASETSTORAGE']._serialized_start=404 - _globals['_SAVEDDATASETSTORAGE']._serialized_end=957 - _globals['_SAVEDDATASETMETA']._serialized_start=960 - _globals['_SAVEDDATASETMETA']._serialized_end=1207 - _globals['_SAVEDDATASET']._serialized_start=1209 - _globals['_SAVEDDATASET']._serialized_end=1311 + _globals['_SAVEDDATASETSPEC']._serialized_end=461 + _globals['_SAVEDDATASETSPEC_TAGSENTRY']._serialized_start=418 + _globals['_SAVEDDATASETSPEC_TAGSENTRY']._serialized_end=461 + _globals['_SAVEDDATASETSTORAGE']._serialized_start=464 + _globals['_SAVEDDATASETSTORAGE']._serialized_end=1017 + _globals['_SAVEDDATASETMETA']._serialized_start=1020 + _globals['_SAVEDDATASETMETA']._serialized_end=1267 + _globals['_SAVEDDATASET']._serialized_start=1269 + _globals['_SAVEDDATASET']._serialized_end=1371 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/SavedDataset_pb2.pyi b/sdk/python/feast/protos/feast/core/SavedDataset_pb2.pyi index 47525b64ede..2fbf5e05271 100644 --- a/sdk/python/feast/protos/feast/core/SavedDataset_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/SavedDataset_pb2.pyi @@ -58,6 +58,9 @@ class SavedDatasetSpec(google.protobuf.message.Message): STORAGE_FIELD_NUMBER: builtins.int FEATURE_SERVICE_NAME_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int + NAMESPACE_FIELD_NUMBER: builtins.int + COLLECTION_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int name: builtins.str """Name of the dataset. Must be unique since it's possible to overwrite dataset by name""" project: builtins.str @@ -77,6 +80,18 @@ class SavedDatasetSpec(google.protobuf.message.Message): @property def tags(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: """User defined metadata""" + namespace: builtins.str + """Optional logical namespace for hierarchical grouping. + Maps to the top-level prefix in Iceberg REST Catalog API. + Empty string means not set (no namespace scoping). + """ + collection: builtins.str + """Optional sub-grouping within a namespace. + Maps to the namespace level in Iceberg REST Catalog API. + Empty string means not set (dataset sits directly under namespace). + """ + description: builtins.str + """Description of the saved dataset.""" def __init__( self, *, @@ -88,9 +103,12 @@ class SavedDatasetSpec(google.protobuf.message.Message): storage: global___SavedDatasetStorage | None = ..., feature_service_name: builtins.str = ..., tags: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + namespace: builtins.str = ..., + collection: builtins.str = ..., + description: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["storage", b"storage"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["feature_service_name", b"feature_service_name", "features", b"features", "full_feature_names", b"full_feature_names", "join_keys", b"join_keys", "name", b"name", "project", b"project", "storage", b"storage", "tags", b"tags"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["collection", b"collection", "description", b"description", "feature_service_name", b"feature_service_name", "features", b"features", "full_feature_names", b"full_feature_names", "join_keys", b"join_keys", "name", b"name", "namespace", b"namespace", "project", b"project", "storage", b"storage", "tags", b"tags"]) -> None: ... global___SavedDatasetSpec = SavedDatasetSpec diff --git a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py index 25766701899..95e5c449912 100644 --- a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py +++ b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py @@ -29,7 +29,7 @@ from feast.protos.feast.core import Project_pb2 as feast_dot_core_dot_Project__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#feast/registry/RegistryServer.proto\x12\x0e\x66\x65\x61st.registry\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x19\x66\x65\x61st/core/Registry.proto\x1a\x17\x66\x65\x61st/core/Entity.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\"feast/core/StreamFeatureView.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\x1f\x66\x65\x61st/core/FeatureService.proto\x1a\x1d\x66\x65\x61st/core/SavedDataset.proto\x1a\"feast/core/ValidationProfile.proto\x1a\x1c\x66\x65\x61st/core/InfraObject.proto\x1a\x1a\x66\x65\x61st/core/LabelView.proto\x1a\x1b\x66\x65\x61st/core/Permission.proto\x1a\x18\x66\x65\x61st/core/Project.proto\"/\n\x10PaginationParams\x12\x0c\n\x04page\x18\x01 \x01(\x05\x12\r\n\x05limit\x18\x02 \x01(\x05\"4\n\rSortingParams\x12\x0f\n\x07sort_by\x18\x01 \x01(\t\x12\x12\n\nsort_order\x18\x02 \x01(\t\"\x83\x01\n\x12PaginationMetadata\x12\x0c\n\x04page\x18\x01 \x01(\x05\x12\r\n\x05limit\x18\x02 \x01(\x05\x12\x13\n\x0btotal_count\x18\x03 \x01(\x05\x12\x13\n\x0btotal_pages\x18\x04 \x01(\x05\x12\x10\n\x08has_next\x18\x05 \x01(\x08\x12\x14\n\x0chas_previous\x18\x06 \x01(\x08\"!\n\x0eRefreshRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\"W\n\x12UpdateInfraRequest\x12 \n\x05infra\x18\x01 \x01(\x0b\x32\x11.feast.core.Infra\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"7\n\x0fGetInfraRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"B\n\x1aListProjectMetadataRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"T\n\x1bListProjectMetadataResponse\x12\x35\n\x10project_metadata\x18\x01 \x03(\x0b\x32\x1b.feast.core.ProjectMetadata\"\xcb\x01\n\x1b\x41pplyMaterializationRequest\x12-\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureView\x12\x0f\n\x07project\x18\x02 \x01(\t\x12.\n\nstart_date\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_date\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06\x63ommit\x18\x05 \x01(\x08\"Y\n\x12\x41pplyEntityRequest\x12\"\n\x06\x65ntity\x18\x01 \x01(\x0b\x32\x12.feast.core.Entity\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"F\n\x10GetEntityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x8b\x02\n\x13ListEntitiesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12;\n\x04tags\x18\x03 \x03(\x0b\x32-.feast.registry.ListEntitiesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"t\n\x14ListEntitiesResponse\x12$\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x12.feast.core.Entity\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"D\n\x13\x44\x65leteEntityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"f\n\x16\x41pplyDataSourceRequest\x12+\n\x0b\x64\x61ta_source\x18\x01 \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"J\n\x14GetDataSourceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x91\x02\n\x16ListDataSourcesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12>\n\x04tags\x18\x03 \x03(\x0b\x32\x30.feast.registry.ListDataSourcesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x7f\n\x17ListDataSourcesResponse\x12,\n\x0c\x64\x61ta_sources\x18\x01 \x03(\x0b\x32\x16.feast.core.DataSource\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"H\n\x17\x44\x65leteDataSourceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\xae\x02\n\x17\x41pplyFeatureViewRequest\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x41\n\x16on_demand_feature_view\x18\x02 \x01(\x0b\x32\x1f.feast.core.OnDemandFeatureViewH\x00\x12<\n\x13stream_feature_view\x18\x03 \x01(\x0b\x32\x1d.feast.core.StreamFeatureViewH\x00\x12+\n\nlabel_view\x18\x06 \x01(\x0b\x32\x15.feast.core.LabelViewH\x00\x12\x0f\n\x07project\x18\x04 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x05 \x01(\x08\x42\x13\n\x11\x62\x61se_feature_view\"K\n\x15GetFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x93\x02\n\x17ListFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12?\n\x04tags\x18\x03 \x03(\x0b\x32\x31.feast.registry.ListFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x82\x01\n\x18ListFeatureViewsResponse\x12.\n\rfeature_views\x18\x01 \x03(\x0b\x32\x17.feast.core.FeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"I\n\x18\x44\x65leteFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\x83\x02\n\x0e\x41nyFeatureView\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x41\n\x16on_demand_feature_view\x18\x02 \x01(\x0b\x32\x1f.feast.core.OnDemandFeatureViewH\x00\x12<\n\x13stream_feature_view\x18\x03 \x01(\x0b\x32\x1d.feast.core.StreamFeatureViewH\x00\x12+\n\nlabel_view\x18\x04 \x01(\x0b\x32\x15.feast.core.LabelViewH\x00\x42\x12\n\x10\x61ny_feature_view\"N\n\x18GetAnyFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"U\n\x19GetAnyFeatureViewResponse\x12\x38\n\x10\x61ny_feature_view\x18\x01 \x01(\x0b\x32\x1e.feast.registry.AnyFeatureView\"\x9b\x03\n\x1aListAllFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x42\n\x04tags\x18\x03 \x03(\x0b\x32\x34.feast.registry.ListAllFeatureViewsRequest.TagsEntry\x12\x0e\n\x06\x65ntity\x18\x04 \x01(\t\x12\x0f\n\x07\x66\x65\x61ture\x18\x05 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_service\x18\x06 \x01(\t\x12\x13\n\x0b\x64\x61ta_source\x18\x07 \x01(\t\x12\x34\n\npagination\x18\x08 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\t \x01(\x0b\x32\x1d.feast.registry.SortingParams\x12\x31\n\rupdated_since\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8c\x01\n\x1bListAllFeatureViewsResponse\x12\x35\n\rfeature_views\x18\x01 \x03(\x0b\x32\x1e.feast.registry.AnyFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"Q\n\x1bGetStreamFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x9f\x02\n\x1dListStreamFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x45\n\x04tags\x18\x03 \x03(\x0b\x32\x37.feast.registry.ListStreamFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x95\x01\n\x1eListStreamFeatureViewsResponse\x12;\n\x14stream_feature_views\x18\x01 \x03(\x0b\x32\x1d.feast.core.StreamFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"S\n\x1dGetOnDemandFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xa3\x02\n\x1fListOnDemandFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12G\n\x04tags\x18\x03 \x03(\x0b\x32\x39.feast.registry.ListOnDemandFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9c\x01\n ListOnDemandFeatureViewsResponse\x12@\n\x17on_demand_feature_views\x18\x01 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"I\n\x13GetLabelViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x8f\x02\n\x15ListLabelViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12=\n\x04tags\x18\x03 \x03(\x0b\x32/.feast.registry.ListLabelViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"|\n\x16ListLabelViewsResponse\x12*\n\x0blabel_views\x18\x01 \x03(\x0b\x32\x15.feast.core.LabelView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"r\n\x1a\x41pplyFeatureServiceRequest\x12\x33\n\x0f\x66\x65\x61ture_service\x18\x01 \x01(\x0b\x32\x1a.feast.core.FeatureService\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"N\n\x18GetFeatureServiceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xaf\x02\n\x1aListFeatureServicesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x42\n\x04tags\x18\x03 \x03(\x0b\x32\x34.feast.registry.ListFeatureServicesRequest.TagsEntry\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x04 \x01(\t\x12\x34\n\npagination\x18\x05 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x06 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8b\x01\n\x1bListFeatureServicesResponse\x12\x34\n\x10\x66\x65\x61ture_services\x18\x01 \x03(\x0b\x32\x1a.feast.core.FeatureService\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"L\n\x1b\x44\x65leteFeatureServiceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"l\n\x18\x41pplySavedDatasetRequest\x12/\n\rsaved_dataset\x18\x01 \x01(\x0b\x32\x18.feast.core.SavedDataset\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"L\n\x16GetSavedDatasetRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x95\x02\n\x18ListSavedDatasetsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12@\n\x04tags\x18\x03 \x03(\x0b\x32\x32.feast.registry.ListSavedDatasetsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x85\x01\n\x19ListSavedDatasetsResponse\x12\x30\n\x0esaved_datasets\x18\x01 \x03(\x0b\x32\x18.feast.core.SavedDataset\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"J\n\x19\x44\x65leteSavedDatasetRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\xd0\x03\n!CreateDatasetFromRetrievalRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x1c\n\x14\x66\x65\x61ture_service_name\x18\x03 \x01(\t\x12\x10\n\x08\x66\x65\x61tures\x18\x04 \x03(\t\x12\x1a\n\x12\x65ntity_source_type\x18\x05 \x01(\t\x12\x1a\n\x12\x65ntity_source_path\x18\x06 \x01(\t\x12\x13\n\x0b\x65ntity_keys\x18\x08 \x03(\t\x12\x15\n\rentity_values\x18\t \x01(\t\x12\x12\n\nstart_date\x18\n \x01(\t\x12\x10\n\x08\x65nd_date\x18\x0b \x01(\t\x12\x15\n\rextra_columns\x18\x0c \x01(\t\x12\x14\n\x0cstorage_type\x18\r \x01(\t\x12\x14\n\x0cstorage_path\x18\x0e \x01(\t\x12I\n\x04tags\x18\x0f \x03(\x0b\x32;.feast.registry.CreateDatasetFromRetrievalRequest.TagsEntry\x12\x17\n\x0f\x61llow_overwrite\x18\x10 \x01(\x08\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"D\n\"CreateDatasetFromRetrievalResponse\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\t\"E\n\x15GetDatasetDataRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\r\n\x05limit\x18\x03 \x01(\x05\"\x1c\n\nTabularRow\x12\x0e\n\x06values\x18\x01 \x03(\t\"|\n\x16GetDatasetDataResponse\x12\x0f\n\x07\x63olumns\x18\x01 \x03(\t\x12(\n\x04rows\x18\x02 \x03(\x0b\x32\x1a.feast.registry.TabularRow\x12\x12\n\ntotal_rows\x18\x03 \x01(\x05\x12\x13\n\x0bsample_size\x18\x04 \x01(\x05\",\n\x1aGetDatasetJobStatusRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\"\x9d\x01\n\x1bGetDatasetJobStatusResponse\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x14\n\x0c\x64\x61taset_name\x18\x02 \x01(\t\x12\x0f\n\x07project\x18\x03 \x01(\t\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ncreated_at\x18\x05 \x01(\t\x12\x14\n\x0c\x63ompleted_at\x18\x06 \x01(\t\x12\r\n\x05\x65rror\x18\x07 \x01(\t\"@\n\x16ListDatasetJobsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x15\n\rstatus_filter\x18\x02 \x01(\t\"T\n\x17ListDatasetJobsResponse\x12\x39\n\x04jobs\x18\x01 \x03(\x0b\x32+.feast.registry.GetDatasetJobStatusResponse\"\x81\x01\n\x1f\x41pplyValidationReferenceRequest\x12=\n\x14validation_reference\x18\x01 \x01(\x0b\x32\x1f.feast.core.ValidationReference\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"S\n\x1dGetValidationReferenceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xa3\x02\n\x1fListValidationReferencesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12G\n\x04tags\x18\x03 \x03(\x0b\x32\x39.feast.registry.ListValidationReferencesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9a\x01\n ListValidationReferencesResponse\x12>\n\x15validation_references\x18\x01 \x03(\x0b\x32\x1f.feast.core.ValidationReference\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"Q\n DeleteValidationReferenceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"e\n\x16\x41pplyPermissionRequest\x12*\n\npermission\x18\x01 \x01(\x0b\x32\x16.feast.core.Permission\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"J\n\x14GetPermissionRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x91\x02\n\x16ListPermissionsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12>\n\x04tags\x18\x03 \x03(\x0b\x32\x30.feast.registry.ListPermissionsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"~\n\x17ListPermissionsResponse\x12+\n\x0bpermissions\x18\x01 \x03(\x0b\x32\x16.feast.core.Permission\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"H\n\x17\x44\x65letePermissionRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"K\n\x13\x41pplyProjectRequest\x12$\n\x07project\x18\x01 \x01(\x0b\x32\x13.feast.core.Project\x12\x0e\n\x06\x63ommit\x18\x02 \x01(\x08\"6\n\x11GetProjectRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"\xfa\x01\n\x13ListProjectsRequest\x12\x13\n\x0b\x61llow_cache\x18\x01 \x01(\x08\x12;\n\x04tags\x18\x02 \x03(\x0b\x32-.feast.registry.ListProjectsRequest.TagsEntry\x12\x34\n\npagination\x18\x03 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x04 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"u\n\x14ListProjectsResponse\x12%\n\x08projects\x18\x01 \x03(\x0b\x32\x13.feast.core.Project\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"4\n\x14\x44\x65leteProjectRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x02 \x01(\x08\"-\n\x0f\x45ntityReference\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"r\n\x0e\x45ntityRelation\x12/\n\x06source\x18\x01 \x01(\x0b\x32\x1f.feast.registry.EntityReference\x12/\n\x06target\x18\x02 \x01(\x0b\x32\x1f.feast.registry.EntityReference\"\xdf\x01\n\x19GetRegistryLineageRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x1a\n\x12\x66ilter_object_type\x18\x03 \x01(\t\x12\x1a\n\x12\x66ilter_object_name\x18\x04 \x01(\t\x12\x34\n\npagination\x18\x05 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x06 \x01(\x0b\x32\x1d.feast.registry.SortingParams\"\xa8\x02\n\x1aGetRegistryLineageResponse\x12\x35\n\rrelationships\x18\x01 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12>\n\x16indirect_relationships\x18\x02 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12\x44\n\x18relationships_pagination\x18\x03 \x01(\x0b\x32\".feast.registry.PaginationMetadata\x12M\n!indirect_relationships_pagination\x18\x04 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"\xef\x01\n\x1dGetObjectRelationshipsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0bobject_type\x18\x02 \x01(\t\x12\x13\n\x0bobject_name\x18\x03 \x01(\t\x12\x18\n\x10include_indirect\x18\x04 \x01(\x08\x12\x13\n\x0b\x61llow_cache\x18\x05 \x01(\x08\x12\x34\n\npagination\x18\x06 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x07 \x01(\x0b\x32\x1d.feast.registry.SortingParams\"\x8f\x01\n\x1eGetObjectRelationshipsResponse\x12\x35\n\rrelationships\x18\x01 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"\xbe\x02\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\r\n\x05owner\x18\x05 \x01(\t\x12\x35\n\x11\x63reated_timestamp\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x04tags\x18\x08 \x03(\x0b\x32!.feast.registry.Feature.TagsEntry\x12\x0c\n\x04kind\x18\t \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xd3\x01\n\x13ListFeaturesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x06 \x01(\x08\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x12\x0c\n\x04kind\x18\x07 \x01(\t\"y\n\x14ListFeaturesResponse\x12)\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32\x17.feast.registry.Feature\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"]\n\x11GetFeatureRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x04 \x01(\x08\x32\xd2(\n\x0eRegistryServer\x12K\n\x0b\x41pplyEntity\x12\".feast.registry.ApplyEntityRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x43\n\tGetEntity\x12 .feast.registry.GetEntityRequest\x1a\x12.feast.core.Entity\"\x00\x12[\n\x0cListEntities\x12#.feast.registry.ListEntitiesRequest\x1a$.feast.registry.ListEntitiesResponse\"\x00\x12M\n\x0c\x44\x65leteEntity\x12#.feast.registry.DeleteEntityRequest\x1a\x16.google.protobuf.Empty\"\x00\x12S\n\x0f\x41pplyDataSource\x12&.feast.registry.ApplyDataSourceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12O\n\rGetDataSource\x12$.feast.registry.GetDataSourceRequest\x1a\x16.feast.core.DataSource\"\x00\x12\x64\n\x0fListDataSources\x12&.feast.registry.ListDataSourcesRequest\x1a\'.feast.registry.ListDataSourcesResponse\"\x00\x12U\n\x10\x44\x65leteDataSource\x12\'.feast.registry.DeleteDataSourceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12U\n\x10\x41pplyFeatureView\x12\'.feast.registry.ApplyFeatureViewRequest\x1a\x16.google.protobuf.Empty\"\x00\x12W\n\x11\x44\x65leteFeatureView\x12(.feast.registry.DeleteFeatureViewRequest\x1a\x16.google.protobuf.Empty\"\x00\x12j\n\x11GetAnyFeatureView\x12(.feast.registry.GetAnyFeatureViewRequest\x1a).feast.registry.GetAnyFeatureViewResponse\"\x00\x12p\n\x13ListAllFeatureViews\x12*.feast.registry.ListAllFeatureViewsRequest\x1a+.feast.registry.ListAllFeatureViewsResponse\"\x00\x12R\n\x0eGetFeatureView\x12%.feast.registry.GetFeatureViewRequest\x1a\x17.feast.core.FeatureView\"\x00\x12g\n\x10ListFeatureViews\x12\'.feast.registry.ListFeatureViewsRequest\x1a(.feast.registry.ListFeatureViewsResponse\"\x00\x12\x64\n\x14GetStreamFeatureView\x12+.feast.registry.GetStreamFeatureViewRequest\x1a\x1d.feast.core.StreamFeatureView\"\x00\x12y\n\x16ListStreamFeatureViews\x12-.feast.registry.ListStreamFeatureViewsRequest\x1a..feast.registry.ListStreamFeatureViewsResponse\"\x00\x12j\n\x16GetOnDemandFeatureView\x12-.feast.registry.GetOnDemandFeatureViewRequest\x1a\x1f.feast.core.OnDemandFeatureView\"\x00\x12\x7f\n\x18ListOnDemandFeatureViews\x12/.feast.registry.ListOnDemandFeatureViewsRequest\x1a\x30.feast.registry.ListOnDemandFeatureViewsResponse\"\x00\x12L\n\x0cGetLabelView\x12#.feast.registry.GetLabelViewRequest\x1a\x15.feast.core.LabelView\"\x00\x12\x61\n\x0eListLabelViews\x12%.feast.registry.ListLabelViewsRequest\x1a&.feast.registry.ListLabelViewsResponse\"\x00\x12[\n\x13\x41pplyFeatureService\x12*.feast.registry.ApplyFeatureServiceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12[\n\x11GetFeatureService\x12(.feast.registry.GetFeatureServiceRequest\x1a\x1a.feast.core.FeatureService\"\x00\x12p\n\x13ListFeatureServices\x12*.feast.registry.ListFeatureServicesRequest\x1a+.feast.registry.ListFeatureServicesResponse\"\x00\x12]\n\x14\x44\x65leteFeatureService\x12+.feast.registry.DeleteFeatureServiceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12W\n\x11\x41pplySavedDataset\x12(.feast.registry.ApplySavedDatasetRequest\x1a\x16.google.protobuf.Empty\"\x00\x12U\n\x0fGetSavedDataset\x12&.feast.registry.GetSavedDatasetRequest\x1a\x18.feast.core.SavedDataset\"\x00\x12j\n\x11ListSavedDatasets\x12(.feast.registry.ListSavedDatasetsRequest\x1a).feast.registry.ListSavedDatasetsResponse\"\x00\x12Y\n\x12\x44\x65leteSavedDataset\x12).feast.registry.DeleteSavedDatasetRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x85\x01\n\x1a\x43reateDatasetFromRetrieval\x12\x31.feast.registry.CreateDatasetFromRetrievalRequest\x1a\x32.feast.registry.CreateDatasetFromRetrievalResponse\"\x00\x12\x61\n\x0eGetDatasetData\x12%.feast.registry.GetDatasetDataRequest\x1a&.feast.registry.GetDatasetDataResponse\"\x00\x12p\n\x13GetDatasetJobStatus\x12*.feast.registry.GetDatasetJobStatusRequest\x1a+.feast.registry.GetDatasetJobStatusResponse\"\x00\x12\x64\n\x0fListDatasetJobs\x12&.feast.registry.ListDatasetJobsRequest\x1a\'.feast.registry.ListDatasetJobsResponse\"\x00\x12\x65\n\x18\x41pplyValidationReference\x12/.feast.registry.ApplyValidationReferenceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12j\n\x16GetValidationReference\x12-.feast.registry.GetValidationReferenceRequest\x1a\x1f.feast.core.ValidationReference\"\x00\x12\x7f\n\x18ListValidationReferences\x12/.feast.registry.ListValidationReferencesRequest\x1a\x30.feast.registry.ListValidationReferencesResponse\"\x00\x12g\n\x19\x44\x65leteValidationReference\x12\x30.feast.registry.DeleteValidationReferenceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12S\n\x0f\x41pplyPermission\x12&.feast.registry.ApplyPermissionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12O\n\rGetPermission\x12$.feast.registry.GetPermissionRequest\x1a\x16.feast.core.Permission\"\x00\x12\x64\n\x0fListPermissions\x12&.feast.registry.ListPermissionsRequest\x1a\'.feast.registry.ListPermissionsResponse\"\x00\x12U\n\x10\x44\x65letePermission\x12\'.feast.registry.DeletePermissionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12M\n\x0c\x41pplyProject\x12#.feast.registry.ApplyProjectRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x46\n\nGetProject\x12!.feast.registry.GetProjectRequest\x1a\x13.feast.core.Project\"\x00\x12[\n\x0cListProjects\x12#.feast.registry.ListProjectsRequest\x1a$.feast.registry.ListProjectsResponse\"\x00\x12O\n\rDeleteProject\x12$.feast.registry.DeleteProjectRequest\x1a\x16.google.protobuf.Empty\"\x00\x12]\n\x14\x41pplyMaterialization\x12+.feast.registry.ApplyMaterializationRequest\x1a\x16.google.protobuf.Empty\"\x00\x12p\n\x13ListProjectMetadata\x12*.feast.registry.ListProjectMetadataRequest\x1a+.feast.registry.ListProjectMetadataResponse\"\x00\x12K\n\x0bUpdateInfra\x12\".feast.registry.UpdateInfraRequest\x1a\x16.google.protobuf.Empty\"\x00\x12@\n\x08GetInfra\x12\x1f.feast.registry.GetInfraRequest\x1a\x11.feast.core.Infra\"\x00\x12:\n\x06\x43ommit\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12\x43\n\x07Refresh\x12\x1e.feast.registry.RefreshRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x37\n\x05Proto\x12\x16.google.protobuf.Empty\x1a\x14.feast.core.Registry\"\x00\x12m\n\x12GetRegistryLineage\x12).feast.registry.GetRegistryLineageRequest\x1a*.feast.registry.GetRegistryLineageResponse\"\x00\x12y\n\x16GetObjectRelationships\x12-.feast.registry.GetObjectRelationshipsRequest\x1a..feast.registry.GetObjectRelationshipsResponse\"\x00\x12[\n\x0cListFeatures\x12#.feast.registry.ListFeaturesRequest\x1a$.feast.registry.ListFeaturesResponse\"\x00\x12J\n\nGetFeature\x12!.feast.registry.GetFeatureRequest\x1a\x17.feast.registry.Feature\"\x00\x42\x35Z3github.com/feast-dev/feast/go/protos/feast/registryb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#feast/registry/RegistryServer.proto\x12\x0e\x66\x65\x61st.registry\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x19\x66\x65\x61st/core/Registry.proto\x1a\x17\x66\x65\x61st/core/Entity.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\"feast/core/StreamFeatureView.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\x1f\x66\x65\x61st/core/FeatureService.proto\x1a\x1d\x66\x65\x61st/core/SavedDataset.proto\x1a\"feast/core/ValidationProfile.proto\x1a\x1c\x66\x65\x61st/core/InfraObject.proto\x1a\x1a\x66\x65\x61st/core/LabelView.proto\x1a\x1b\x66\x65\x61st/core/Permission.proto\x1a\x18\x66\x65\x61st/core/Project.proto\"/\n\x10PaginationParams\x12\x0c\n\x04page\x18\x01 \x01(\x05\x12\r\n\x05limit\x18\x02 \x01(\x05\"4\n\rSortingParams\x12\x0f\n\x07sort_by\x18\x01 \x01(\t\x12\x12\n\nsort_order\x18\x02 \x01(\t\"\x83\x01\n\x12PaginationMetadata\x12\x0c\n\x04page\x18\x01 \x01(\x05\x12\r\n\x05limit\x18\x02 \x01(\x05\x12\x13\n\x0btotal_count\x18\x03 \x01(\x05\x12\x13\n\x0btotal_pages\x18\x04 \x01(\x05\x12\x10\n\x08has_next\x18\x05 \x01(\x08\x12\x14\n\x0chas_previous\x18\x06 \x01(\x08\"!\n\x0eRefreshRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\"W\n\x12UpdateInfraRequest\x12 \n\x05infra\x18\x01 \x01(\x0b\x32\x11.feast.core.Infra\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"7\n\x0fGetInfraRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"B\n\x1aListProjectMetadataRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"T\n\x1bListProjectMetadataResponse\x12\x35\n\x10project_metadata\x18\x01 \x03(\x0b\x32\x1b.feast.core.ProjectMetadata\"\xcb\x01\n\x1b\x41pplyMaterializationRequest\x12-\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureView\x12\x0f\n\x07project\x18\x02 \x01(\t\x12.\n\nstart_date\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_date\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06\x63ommit\x18\x05 \x01(\x08\"Y\n\x12\x41pplyEntityRequest\x12\"\n\x06\x65ntity\x18\x01 \x01(\x0b\x32\x12.feast.core.Entity\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"F\n\x10GetEntityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x8b\x02\n\x13ListEntitiesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12;\n\x04tags\x18\x03 \x03(\x0b\x32-.feast.registry.ListEntitiesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"t\n\x14ListEntitiesResponse\x12$\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x12.feast.core.Entity\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"D\n\x13\x44\x65leteEntityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"f\n\x16\x41pplyDataSourceRequest\x12+\n\x0b\x64\x61ta_source\x18\x01 \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"J\n\x14GetDataSourceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x91\x02\n\x16ListDataSourcesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12>\n\x04tags\x18\x03 \x03(\x0b\x32\x30.feast.registry.ListDataSourcesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x7f\n\x17ListDataSourcesResponse\x12,\n\x0c\x64\x61ta_sources\x18\x01 \x03(\x0b\x32\x16.feast.core.DataSource\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"H\n\x17\x44\x65leteDataSourceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\xae\x02\n\x17\x41pplyFeatureViewRequest\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x41\n\x16on_demand_feature_view\x18\x02 \x01(\x0b\x32\x1f.feast.core.OnDemandFeatureViewH\x00\x12<\n\x13stream_feature_view\x18\x03 \x01(\x0b\x32\x1d.feast.core.StreamFeatureViewH\x00\x12+\n\nlabel_view\x18\x06 \x01(\x0b\x32\x15.feast.core.LabelViewH\x00\x12\x0f\n\x07project\x18\x04 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x05 \x01(\x08\x42\x13\n\x11\x62\x61se_feature_view\"K\n\x15GetFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x93\x02\n\x17ListFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12?\n\x04tags\x18\x03 \x03(\x0b\x32\x31.feast.registry.ListFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x82\x01\n\x18ListFeatureViewsResponse\x12.\n\rfeature_views\x18\x01 \x03(\x0b\x32\x17.feast.core.FeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"I\n\x18\x44\x65leteFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\x83\x02\n\x0e\x41nyFeatureView\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x41\n\x16on_demand_feature_view\x18\x02 \x01(\x0b\x32\x1f.feast.core.OnDemandFeatureViewH\x00\x12<\n\x13stream_feature_view\x18\x03 \x01(\x0b\x32\x1d.feast.core.StreamFeatureViewH\x00\x12+\n\nlabel_view\x18\x04 \x01(\x0b\x32\x15.feast.core.LabelViewH\x00\x42\x12\n\x10\x61ny_feature_view\"N\n\x18GetAnyFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"U\n\x19GetAnyFeatureViewResponse\x12\x38\n\x10\x61ny_feature_view\x18\x01 \x01(\x0b\x32\x1e.feast.registry.AnyFeatureView\"\x9b\x03\n\x1aListAllFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x42\n\x04tags\x18\x03 \x03(\x0b\x32\x34.feast.registry.ListAllFeatureViewsRequest.TagsEntry\x12\x0e\n\x06\x65ntity\x18\x04 \x01(\t\x12\x0f\n\x07\x66\x65\x61ture\x18\x05 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_service\x18\x06 \x01(\t\x12\x13\n\x0b\x64\x61ta_source\x18\x07 \x01(\t\x12\x34\n\npagination\x18\x08 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\t \x01(\x0b\x32\x1d.feast.registry.SortingParams\x12\x31\n\rupdated_since\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8c\x01\n\x1bListAllFeatureViewsResponse\x12\x35\n\rfeature_views\x18\x01 \x03(\x0b\x32\x1e.feast.registry.AnyFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"Q\n\x1bGetStreamFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x9f\x02\n\x1dListStreamFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x45\n\x04tags\x18\x03 \x03(\x0b\x32\x37.feast.registry.ListStreamFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x95\x01\n\x1eListStreamFeatureViewsResponse\x12;\n\x14stream_feature_views\x18\x01 \x03(\x0b\x32\x1d.feast.core.StreamFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"S\n\x1dGetOnDemandFeatureViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xa3\x02\n\x1fListOnDemandFeatureViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12G\n\x04tags\x18\x03 \x03(\x0b\x32\x39.feast.registry.ListOnDemandFeatureViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9c\x01\n ListOnDemandFeatureViewsResponse\x12@\n\x17on_demand_feature_views\x18\x01 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"I\n\x13GetLabelViewRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x8f\x02\n\x15ListLabelViewsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12=\n\x04tags\x18\x03 \x03(\x0b\x32/.feast.registry.ListLabelViewsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"|\n\x16ListLabelViewsResponse\x12*\n\x0blabel_views\x18\x01 \x03(\x0b\x32\x15.feast.core.LabelView\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"r\n\x1a\x41pplyFeatureServiceRequest\x12\x33\n\x0f\x66\x65\x61ture_service\x18\x01 \x01(\x0b\x32\x1a.feast.core.FeatureService\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"N\n\x18GetFeatureServiceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xaf\x02\n\x1aListFeatureServicesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x42\n\x04tags\x18\x03 \x03(\x0b\x32\x34.feast.registry.ListFeatureServicesRequest.TagsEntry\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x04 \x01(\t\x12\x34\n\npagination\x18\x05 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x06 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8b\x01\n\x1bListFeatureServicesResponse\x12\x34\n\x10\x66\x65\x61ture_services\x18\x01 \x03(\x0b\x32\x1a.feast.core.FeatureService\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"L\n\x1b\x44\x65leteFeatureServiceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"l\n\x18\x41pplySavedDatasetRequest\x12/\n\rsaved_dataset\x18\x01 \x01(\x0b\x32\x18.feast.core.SavedDataset\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"L\n\x16GetSavedDatasetRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xbc\x02\n\x18ListSavedDatasetsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12@\n\x04tags\x18\x03 \x03(\x0b\x32\x32.feast.registry.ListSavedDatasetsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x12\n\ncollection\x18\x07 \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x85\x01\n\x19ListSavedDatasetsResponse\x12\x30\n\x0esaved_datasets\x18\x01 \x03(\x0b\x32\x18.feast.core.SavedDataset\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"J\n\x19\x44\x65leteSavedDatasetRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"\xd0\x03\n!CreateDatasetFromRetrievalRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x1c\n\x14\x66\x65\x61ture_service_name\x18\x03 \x01(\t\x12\x10\n\x08\x66\x65\x61tures\x18\x04 \x03(\t\x12\x1a\n\x12\x65ntity_source_type\x18\x05 \x01(\t\x12\x1a\n\x12\x65ntity_source_path\x18\x06 \x01(\t\x12\x13\n\x0b\x65ntity_keys\x18\x08 \x03(\t\x12\x15\n\rentity_values\x18\t \x01(\t\x12\x12\n\nstart_date\x18\n \x01(\t\x12\x10\n\x08\x65nd_date\x18\x0b \x01(\t\x12\x15\n\rextra_columns\x18\x0c \x01(\t\x12\x14\n\x0cstorage_type\x18\r \x01(\t\x12\x14\n\x0cstorage_path\x18\x0e \x01(\t\x12I\n\x04tags\x18\x0f \x03(\x0b\x32;.feast.registry.CreateDatasetFromRetrievalRequest.TagsEntry\x12\x17\n\x0f\x61llow_overwrite\x18\x10 \x01(\x08\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"D\n\"CreateDatasetFromRetrievalResponse\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\t\"E\n\x15GetDatasetDataRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\r\n\x05limit\x18\x03 \x01(\x05\"\x1c\n\nTabularRow\x12\x0e\n\x06values\x18\x01 \x03(\t\"|\n\x16GetDatasetDataResponse\x12\x0f\n\x07\x63olumns\x18\x01 \x03(\t\x12(\n\x04rows\x18\x02 \x03(\x0b\x32\x1a.feast.registry.TabularRow\x12\x12\n\ntotal_rows\x18\x03 \x01(\x05\x12\x13\n\x0bsample_size\x18\x04 \x01(\x05\",\n\x1aGetDatasetJobStatusRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\"\x9d\x01\n\x1bGetDatasetJobStatusResponse\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x14\n\x0c\x64\x61taset_name\x18\x02 \x01(\t\x12\x0f\n\x07project\x18\x03 \x01(\t\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ncreated_at\x18\x05 \x01(\t\x12\x14\n\x0c\x63ompleted_at\x18\x06 \x01(\t\x12\r\n\x05\x65rror\x18\x07 \x01(\t\"@\n\x16ListDatasetJobsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x15\n\rstatus_filter\x18\x02 \x01(\t\"T\n\x17ListDatasetJobsResponse\x12\x39\n\x04jobs\x18\x01 \x03(\x0b\x32+.feast.registry.GetDatasetJobStatusResponse\"\x81\x01\n\x1f\x41pplyValidationReferenceRequest\x12=\n\x14validation_reference\x18\x01 \x01(\x0b\x32\x1f.feast.core.ValidationReference\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"S\n\x1dGetValidationReferenceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\xa3\x02\n\x1fListValidationReferencesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12G\n\x04tags\x18\x03 \x03(\x0b\x32\x39.feast.registry.ListValidationReferencesRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9a\x01\n ListValidationReferencesResponse\x12>\n\x15validation_references\x18\x01 \x03(\x0b\x32\x1f.feast.core.ValidationReference\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"Q\n DeleteValidationReferenceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"e\n\x16\x41pplyPermissionRequest\x12*\n\npermission\x18\x01 \x01(\x0b\x32\x16.feast.core.Permission\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"J\n\x14GetPermissionRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x03 \x01(\x08\"\x91\x02\n\x16ListPermissionsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12>\n\x04tags\x18\x03 \x03(\x0b\x32\x30.feast.registry.ListPermissionsRequest.TagsEntry\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"~\n\x17ListPermissionsResponse\x12+\n\x0bpermissions\x18\x01 \x03(\x0b\x32\x16.feast.core.Permission\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"H\n\x17\x44\x65letePermissionRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x03 \x01(\x08\"K\n\x13\x41pplyProjectRequest\x12$\n\x07project\x18\x01 \x01(\x0b\x32\x13.feast.core.Project\x12\x0e\n\x06\x63ommit\x18\x02 \x01(\x08\"6\n\x11GetProjectRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\"\xfa\x01\n\x13ListProjectsRequest\x12\x13\n\x0b\x61llow_cache\x18\x01 \x01(\x08\x12;\n\x04tags\x18\x02 \x03(\x0b\x32-.feast.registry.ListProjectsRequest.TagsEntry\x12\x34\n\npagination\x18\x03 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x04 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"u\n\x14ListProjectsResponse\x12%\n\x08projects\x18\x01 \x03(\x0b\x32\x13.feast.core.Project\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"4\n\x14\x44\x65leteProjectRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x02 \x01(\x08\"-\n\x0f\x45ntityReference\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"r\n\x0e\x45ntityRelation\x12/\n\x06source\x18\x01 \x01(\x0b\x32\x1f.feast.registry.EntityReference\x12/\n\x06target\x18\x02 \x01(\x0b\x32\x1f.feast.registry.EntityReference\"\xdf\x01\n\x19GetRegistryLineageRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x02 \x01(\x08\x12\x1a\n\x12\x66ilter_object_type\x18\x03 \x01(\t\x12\x1a\n\x12\x66ilter_object_name\x18\x04 \x01(\t\x12\x34\n\npagination\x18\x05 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x06 \x01(\x0b\x32\x1d.feast.registry.SortingParams\"\xa8\x02\n\x1aGetRegistryLineageResponse\x12\x35\n\rrelationships\x18\x01 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12>\n\x16indirect_relationships\x18\x02 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12\x44\n\x18relationships_pagination\x18\x03 \x01(\x0b\x32\".feast.registry.PaginationMetadata\x12M\n!indirect_relationships_pagination\x18\x04 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"\xef\x01\n\x1dGetObjectRelationshipsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x13\n\x0bobject_type\x18\x02 \x01(\t\x12\x13\n\x0bobject_name\x18\x03 \x01(\t\x12\x18\n\x10include_indirect\x18\x04 \x01(\x08\x12\x13\n\x0b\x61llow_cache\x18\x05 \x01(\x08\x12\x34\n\npagination\x18\x06 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x07 \x01(\x0b\x32\x1d.feast.registry.SortingParams\"\x8f\x01\n\x1eGetObjectRelationshipsResponse\x12\x35\n\rrelationships\x18\x01 \x03(\x0b\x32\x1e.feast.registry.EntityRelation\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"\xbe\x02\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\r\n\x05owner\x18\x05 \x01(\t\x12\x35\n\x11\x63reated_timestamp\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x04tags\x18\x08 \x03(\x0b\x32!.feast.registry.Feature.TagsEntry\x12\x0c\n\x04kind\x18\t \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xd3\x01\n\x13ListFeaturesRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x06 \x01(\x08\x12\x34\n\npagination\x18\x04 \x01(\x0b\x32 .feast.registry.PaginationParams\x12.\n\x07sorting\x18\x05 \x01(\x0b\x32\x1d.feast.registry.SortingParams\x12\x0c\n\x04kind\x18\x07 \x01(\t\"y\n\x14ListFeaturesResponse\x12)\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32\x17.feast.registry.Feature\x12\x36\n\npagination\x18\x02 \x01(\x0b\x32\".feast.registry.PaginationMetadata\"]\n\x11GetFeatureRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_view\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x61llow_cache\x18\x04 \x01(\x08\x32\xd2(\n\x0eRegistryServer\x12K\n\x0b\x41pplyEntity\x12\".feast.registry.ApplyEntityRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x43\n\tGetEntity\x12 .feast.registry.GetEntityRequest\x1a\x12.feast.core.Entity\"\x00\x12[\n\x0cListEntities\x12#.feast.registry.ListEntitiesRequest\x1a$.feast.registry.ListEntitiesResponse\"\x00\x12M\n\x0c\x44\x65leteEntity\x12#.feast.registry.DeleteEntityRequest\x1a\x16.google.protobuf.Empty\"\x00\x12S\n\x0f\x41pplyDataSource\x12&.feast.registry.ApplyDataSourceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12O\n\rGetDataSource\x12$.feast.registry.GetDataSourceRequest\x1a\x16.feast.core.DataSource\"\x00\x12\x64\n\x0fListDataSources\x12&.feast.registry.ListDataSourcesRequest\x1a\'.feast.registry.ListDataSourcesResponse\"\x00\x12U\n\x10\x44\x65leteDataSource\x12\'.feast.registry.DeleteDataSourceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12U\n\x10\x41pplyFeatureView\x12\'.feast.registry.ApplyFeatureViewRequest\x1a\x16.google.protobuf.Empty\"\x00\x12W\n\x11\x44\x65leteFeatureView\x12(.feast.registry.DeleteFeatureViewRequest\x1a\x16.google.protobuf.Empty\"\x00\x12j\n\x11GetAnyFeatureView\x12(.feast.registry.GetAnyFeatureViewRequest\x1a).feast.registry.GetAnyFeatureViewResponse\"\x00\x12p\n\x13ListAllFeatureViews\x12*.feast.registry.ListAllFeatureViewsRequest\x1a+.feast.registry.ListAllFeatureViewsResponse\"\x00\x12R\n\x0eGetFeatureView\x12%.feast.registry.GetFeatureViewRequest\x1a\x17.feast.core.FeatureView\"\x00\x12g\n\x10ListFeatureViews\x12\'.feast.registry.ListFeatureViewsRequest\x1a(.feast.registry.ListFeatureViewsResponse\"\x00\x12\x64\n\x14GetStreamFeatureView\x12+.feast.registry.GetStreamFeatureViewRequest\x1a\x1d.feast.core.StreamFeatureView\"\x00\x12y\n\x16ListStreamFeatureViews\x12-.feast.registry.ListStreamFeatureViewsRequest\x1a..feast.registry.ListStreamFeatureViewsResponse\"\x00\x12j\n\x16GetOnDemandFeatureView\x12-.feast.registry.GetOnDemandFeatureViewRequest\x1a\x1f.feast.core.OnDemandFeatureView\"\x00\x12\x7f\n\x18ListOnDemandFeatureViews\x12/.feast.registry.ListOnDemandFeatureViewsRequest\x1a\x30.feast.registry.ListOnDemandFeatureViewsResponse\"\x00\x12L\n\x0cGetLabelView\x12#.feast.registry.GetLabelViewRequest\x1a\x15.feast.core.LabelView\"\x00\x12\x61\n\x0eListLabelViews\x12%.feast.registry.ListLabelViewsRequest\x1a&.feast.registry.ListLabelViewsResponse\"\x00\x12[\n\x13\x41pplyFeatureService\x12*.feast.registry.ApplyFeatureServiceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12[\n\x11GetFeatureService\x12(.feast.registry.GetFeatureServiceRequest\x1a\x1a.feast.core.FeatureService\"\x00\x12p\n\x13ListFeatureServices\x12*.feast.registry.ListFeatureServicesRequest\x1a+.feast.registry.ListFeatureServicesResponse\"\x00\x12]\n\x14\x44\x65leteFeatureService\x12+.feast.registry.DeleteFeatureServiceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12W\n\x11\x41pplySavedDataset\x12(.feast.registry.ApplySavedDatasetRequest\x1a\x16.google.protobuf.Empty\"\x00\x12U\n\x0fGetSavedDataset\x12&.feast.registry.GetSavedDatasetRequest\x1a\x18.feast.core.SavedDataset\"\x00\x12j\n\x11ListSavedDatasets\x12(.feast.registry.ListSavedDatasetsRequest\x1a).feast.registry.ListSavedDatasetsResponse\"\x00\x12Y\n\x12\x44\x65leteSavedDataset\x12).feast.registry.DeleteSavedDatasetRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x85\x01\n\x1a\x43reateDatasetFromRetrieval\x12\x31.feast.registry.CreateDatasetFromRetrievalRequest\x1a\x32.feast.registry.CreateDatasetFromRetrievalResponse\"\x00\x12\x61\n\x0eGetDatasetData\x12%.feast.registry.GetDatasetDataRequest\x1a&.feast.registry.GetDatasetDataResponse\"\x00\x12p\n\x13GetDatasetJobStatus\x12*.feast.registry.GetDatasetJobStatusRequest\x1a+.feast.registry.GetDatasetJobStatusResponse\"\x00\x12\x64\n\x0fListDatasetJobs\x12&.feast.registry.ListDatasetJobsRequest\x1a\'.feast.registry.ListDatasetJobsResponse\"\x00\x12\x65\n\x18\x41pplyValidationReference\x12/.feast.registry.ApplyValidationReferenceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12j\n\x16GetValidationReference\x12-.feast.registry.GetValidationReferenceRequest\x1a\x1f.feast.core.ValidationReference\"\x00\x12\x7f\n\x18ListValidationReferences\x12/.feast.registry.ListValidationReferencesRequest\x1a\x30.feast.registry.ListValidationReferencesResponse\"\x00\x12g\n\x19\x44\x65leteValidationReference\x12\x30.feast.registry.DeleteValidationReferenceRequest\x1a\x16.google.protobuf.Empty\"\x00\x12S\n\x0f\x41pplyPermission\x12&.feast.registry.ApplyPermissionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12O\n\rGetPermission\x12$.feast.registry.GetPermissionRequest\x1a\x16.feast.core.Permission\"\x00\x12\x64\n\x0fListPermissions\x12&.feast.registry.ListPermissionsRequest\x1a\'.feast.registry.ListPermissionsResponse\"\x00\x12U\n\x10\x44\x65letePermission\x12\'.feast.registry.DeletePermissionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12M\n\x0c\x41pplyProject\x12#.feast.registry.ApplyProjectRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x46\n\nGetProject\x12!.feast.registry.GetProjectRequest\x1a\x13.feast.core.Project\"\x00\x12[\n\x0cListProjects\x12#.feast.registry.ListProjectsRequest\x1a$.feast.registry.ListProjectsResponse\"\x00\x12O\n\rDeleteProject\x12$.feast.registry.DeleteProjectRequest\x1a\x16.google.protobuf.Empty\"\x00\x12]\n\x14\x41pplyMaterialization\x12+.feast.registry.ApplyMaterializationRequest\x1a\x16.google.protobuf.Empty\"\x00\x12p\n\x13ListProjectMetadata\x12*.feast.registry.ListProjectMetadataRequest\x1a+.feast.registry.ListProjectMetadataResponse\"\x00\x12K\n\x0bUpdateInfra\x12\".feast.registry.UpdateInfraRequest\x1a\x16.google.protobuf.Empty\"\x00\x12@\n\x08GetInfra\x12\x1f.feast.registry.GetInfraRequest\x1a\x11.feast.core.Infra\"\x00\x12:\n\x06\x43ommit\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12\x43\n\x07Refresh\x12\x1e.feast.registry.RefreshRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x37\n\x05Proto\x12\x16.google.protobuf.Empty\x1a\x14.feast.core.Registry\"\x00\x12m\n\x12GetRegistryLineage\x12).feast.registry.GetRegistryLineageRequest\x1a*.feast.registry.GetRegistryLineageResponse\"\x00\x12y\n\x16GetObjectRelationships\x12-.feast.registry.GetObjectRelationshipsRequest\x1a..feast.registry.GetObjectRelationshipsResponse\"\x00\x12[\n\x0cListFeatures\x12#.feast.registry.ListFeaturesRequest\x1a$.feast.registry.ListFeaturesResponse\"\x00\x12J\n\nGetFeature\x12!.feast.registry.GetFeatureRequest\x1a\x17.feast.registry.Feature\"\x00\x42\x35Z3github.com/feast-dev/feast/go/protos/feast/registryb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -172,91 +172,91 @@ _globals['_GETSAVEDDATASETREQUEST']._serialized_start=6797 _globals['_GETSAVEDDATASETREQUEST']._serialized_end=6873 _globals['_LISTSAVEDDATASETSREQUEST']._serialized_start=6876 - _globals['_LISTSAVEDDATASETSREQUEST']._serialized_end=7153 + _globals['_LISTSAVEDDATASETSREQUEST']._serialized_end=7192 _globals['_LISTSAVEDDATASETSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTSAVEDDATASETSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_start=7156 - _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_end=7289 - _globals['_DELETESAVEDDATASETREQUEST']._serialized_start=7291 - _globals['_DELETESAVEDDATASETREQUEST']._serialized_end=7365 - _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_start=7368 - _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_end=7832 + _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_start=7195 + _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_end=7328 + _globals['_DELETESAVEDDATASETREQUEST']._serialized_start=7330 + _globals['_DELETESAVEDDATASETREQUEST']._serialized_end=7404 + _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_start=7407 + _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_end=7871 _globals['_CREATEDATASETFROMRETRIEVALREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_CREATEDATASETFROMRETRIEVALREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_start=7834 - _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_end=7902 - _globals['_GETDATASETDATAREQUEST']._serialized_start=7904 - _globals['_GETDATASETDATAREQUEST']._serialized_end=7973 - _globals['_TABULARROW']._serialized_start=7975 - _globals['_TABULARROW']._serialized_end=8003 - _globals['_GETDATASETDATARESPONSE']._serialized_start=8005 - _globals['_GETDATASETDATARESPONSE']._serialized_end=8129 - _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_start=8131 - _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_end=8175 - _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_start=8178 - _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_end=8335 - _globals['_LISTDATASETJOBSREQUEST']._serialized_start=8337 - _globals['_LISTDATASETJOBSREQUEST']._serialized_end=8401 - _globals['_LISTDATASETJOBSRESPONSE']._serialized_start=8403 - _globals['_LISTDATASETJOBSRESPONSE']._serialized_end=8487 - _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_start=8490 - _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_end=8619 - _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_start=8621 - _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_end=8704 - _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_start=8707 - _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_end=8998 + _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_start=7873 + _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_end=7941 + _globals['_GETDATASETDATAREQUEST']._serialized_start=7943 + _globals['_GETDATASETDATAREQUEST']._serialized_end=8012 + _globals['_TABULARROW']._serialized_start=8014 + _globals['_TABULARROW']._serialized_end=8042 + _globals['_GETDATASETDATARESPONSE']._serialized_start=8044 + _globals['_GETDATASETDATARESPONSE']._serialized_end=8168 + _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_start=8170 + _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_end=8214 + _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_start=8217 + _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_end=8374 + _globals['_LISTDATASETJOBSREQUEST']._serialized_start=8376 + _globals['_LISTDATASETJOBSREQUEST']._serialized_end=8440 + _globals['_LISTDATASETJOBSRESPONSE']._serialized_start=8442 + _globals['_LISTDATASETJOBSRESPONSE']._serialized_end=8526 + _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_start=8529 + _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_end=8658 + _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_start=8660 + _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_end=8743 + _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_start=8746 + _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_end=9037 _globals['_LISTVALIDATIONREFERENCESREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTVALIDATIONREFERENCESREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_start=9001 - _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_end=9155 - _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_start=9157 - _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_end=9238 - _globals['_APPLYPERMISSIONREQUEST']._serialized_start=9240 - _globals['_APPLYPERMISSIONREQUEST']._serialized_end=9341 - _globals['_GETPERMISSIONREQUEST']._serialized_start=9343 - _globals['_GETPERMISSIONREQUEST']._serialized_end=9417 - _globals['_LISTPERMISSIONSREQUEST']._serialized_start=9420 - _globals['_LISTPERMISSIONSREQUEST']._serialized_end=9693 + _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_start=9040 + _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_end=9194 + _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_start=9196 + _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_end=9277 + _globals['_APPLYPERMISSIONREQUEST']._serialized_start=9279 + _globals['_APPLYPERMISSIONREQUEST']._serialized_end=9380 + _globals['_GETPERMISSIONREQUEST']._serialized_start=9382 + _globals['_GETPERMISSIONREQUEST']._serialized_end=9456 + _globals['_LISTPERMISSIONSREQUEST']._serialized_start=9459 + _globals['_LISTPERMISSIONSREQUEST']._serialized_end=9732 _globals['_LISTPERMISSIONSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTPERMISSIONSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTPERMISSIONSRESPONSE']._serialized_start=9695 - _globals['_LISTPERMISSIONSRESPONSE']._serialized_end=9821 - _globals['_DELETEPERMISSIONREQUEST']._serialized_start=9823 - _globals['_DELETEPERMISSIONREQUEST']._serialized_end=9895 - _globals['_APPLYPROJECTREQUEST']._serialized_start=9897 - _globals['_APPLYPROJECTREQUEST']._serialized_end=9972 - _globals['_GETPROJECTREQUEST']._serialized_start=9974 - _globals['_GETPROJECTREQUEST']._serialized_end=10028 - _globals['_LISTPROJECTSREQUEST']._serialized_start=10031 - _globals['_LISTPROJECTSREQUEST']._serialized_end=10281 + _globals['_LISTPERMISSIONSRESPONSE']._serialized_start=9734 + _globals['_LISTPERMISSIONSRESPONSE']._serialized_end=9860 + _globals['_DELETEPERMISSIONREQUEST']._serialized_start=9862 + _globals['_DELETEPERMISSIONREQUEST']._serialized_end=9934 + _globals['_APPLYPROJECTREQUEST']._serialized_start=9936 + _globals['_APPLYPROJECTREQUEST']._serialized_end=10011 + _globals['_GETPROJECTREQUEST']._serialized_start=10013 + _globals['_GETPROJECTREQUEST']._serialized_end=10067 + _globals['_LISTPROJECTSREQUEST']._serialized_start=10070 + _globals['_LISTPROJECTSREQUEST']._serialized_end=10320 _globals['_LISTPROJECTSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTPROJECTSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTPROJECTSRESPONSE']._serialized_start=10283 - _globals['_LISTPROJECTSRESPONSE']._serialized_end=10400 - _globals['_DELETEPROJECTREQUEST']._serialized_start=10402 - _globals['_DELETEPROJECTREQUEST']._serialized_end=10454 - _globals['_ENTITYREFERENCE']._serialized_start=10456 - _globals['_ENTITYREFERENCE']._serialized_end=10501 - _globals['_ENTITYRELATION']._serialized_start=10503 - _globals['_ENTITYRELATION']._serialized_end=10617 - _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_start=10620 - _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_end=10843 - _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_start=10846 - _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_end=11142 - _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_start=11145 - _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_end=11384 - _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_start=11387 - _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_end=11530 - _globals['_FEATURE']._serialized_start=11533 - _globals['_FEATURE']._serialized_end=11851 + _globals['_LISTPROJECTSRESPONSE']._serialized_start=10322 + _globals['_LISTPROJECTSRESPONSE']._serialized_end=10439 + _globals['_DELETEPROJECTREQUEST']._serialized_start=10441 + _globals['_DELETEPROJECTREQUEST']._serialized_end=10493 + _globals['_ENTITYREFERENCE']._serialized_start=10495 + _globals['_ENTITYREFERENCE']._serialized_end=10540 + _globals['_ENTITYRELATION']._serialized_start=10542 + _globals['_ENTITYRELATION']._serialized_end=10656 + _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_start=10659 + _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_end=10882 + _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_start=10885 + _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_end=11181 + _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_start=11184 + _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_end=11423 + _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_start=11426 + _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_end=11569 + _globals['_FEATURE']._serialized_start=11572 + _globals['_FEATURE']._serialized_end=11890 _globals['_FEATURE_TAGSENTRY']._serialized_start=1681 _globals['_FEATURE_TAGSENTRY']._serialized_end=1724 - _globals['_LISTFEATURESREQUEST']._serialized_start=11854 - _globals['_LISTFEATURESREQUEST']._serialized_end=12065 - _globals['_LISTFEATURESRESPONSE']._serialized_start=12067 - _globals['_LISTFEATURESRESPONSE']._serialized_end=12188 - _globals['_GETFEATUREREQUEST']._serialized_start=12190 - _globals['_GETFEATUREREQUEST']._serialized_end=12283 - _globals['_REGISTRYSERVER']._serialized_start=12286 - _globals['_REGISTRYSERVER']._serialized_end=17488 + _globals['_LISTFEATURESREQUEST']._serialized_start=11893 + _globals['_LISTFEATURESREQUEST']._serialized_end=12104 + _globals['_LISTFEATURESRESPONSE']._serialized_start=12106 + _globals['_LISTFEATURESRESPONSE']._serialized_end=12227 + _globals['_GETFEATUREREQUEST']._serialized_start=12229 + _globals['_GETFEATUREREQUEST']._serialized_end=12322 + _globals['_REGISTRYSERVER']._serialized_start=12325 + _globals['_REGISTRYSERVER']._serialized_end=17527 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi index 9171c75a5be..e76775d0004 100644 --- a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi +++ b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi @@ -1218,6 +1218,8 @@ class ListSavedDatasetsRequest(google.protobuf.message.Message): TAGS_FIELD_NUMBER: builtins.int PAGINATION_FIELD_NUMBER: builtins.int SORTING_FIELD_NUMBER: builtins.int + NAMESPACE_FIELD_NUMBER: builtins.int + COLLECTION_FIELD_NUMBER: builtins.int project: builtins.str allow_cache: builtins.bool @property @@ -1226,6 +1228,10 @@ class ListSavedDatasetsRequest(google.protobuf.message.Message): def pagination(self) -> global___PaginationParams: ... @property def sorting(self) -> global___SortingParams: ... + namespace: builtins.str + """Optional logical namespace filter. Empty string means no filter.""" + collection: builtins.str + """Optional collection filter. Empty string means no filter.""" def __init__( self, *, @@ -1234,9 +1240,11 @@ class ListSavedDatasetsRequest(google.protobuf.message.Message): tags: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., pagination: global___PaginationParams | None = ..., sorting: global___SortingParams | None = ..., + namespace: builtins.str = ..., + collection: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["pagination", b"pagination", "sorting", b"sorting"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["allow_cache", b"allow_cache", "pagination", b"pagination", "project", b"project", "sorting", b"sorting", "tags", b"tags"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["allow_cache", b"allow_cache", "collection", b"collection", "namespace", b"namespace", "pagination", b"pagination", "project", b"project", "sorting", b"sorting", "tags", b"tags"]) -> None: ... global___ListSavedDatasetsRequest = ListSavedDatasetsRequest diff --git a/sdk/python/feast/registry_server.py b/sdk/python/feast/registry_server.py index 8c6a979cc8a..f04bdafa194 100644 --- a/sdk/python/feast/registry_server.py +++ b/sdk/python/feast/registry_server.py @@ -940,6 +940,8 @@ def GetSavedDataset( def ListSavedDatasets( self, request: RegistryServer_pb2.ListSavedDatasetsRequest, context ): + namespace_filter = request.namespace if request.namespace else None + collection_filter = request.collection if request.collection else None paginated_saved_datasets, pagination_metadata = apply_pagination_and_sorting( permitted_resources( resources=cast( @@ -948,6 +950,8 @@ def ListSavedDatasets( project=request.project, allow_cache=request.allow_cache, tags=dict(request.tags), + namespace=namespace_filter, + collection=collection_filter, ), ), actions=AuthzedAction.DESCRIBE, diff --git a/sdk/python/feast/saved_dataset.py b/sdk/python/feast/saved_dataset.py index 9ed69861d4b..d78c5b4c349 100644 --- a/sdk/python/feast/saved_dataset.py +++ b/sdk/python/feast/saved_dataset.py @@ -83,6 +83,9 @@ class SavedDataset: storage: SavedDatasetStorage tags: Dict[str, str] feature_service_name: Optional[str] = None + namespace: str = "" + collection: str = "" + description: str = "" created_timestamp: Optional[datetime] = None last_updated_timestamp: Optional[datetime] = None @@ -101,6 +104,9 @@ def __init__( full_feature_names: bool = False, tags: Optional[Dict[str, str]] = None, feature_service_name: Optional[str] = None, + namespace: str = "", + collection: str = "", + description: str = "", ): self.name = name self.features = features @@ -109,6 +115,9 @@ def __init__( self.full_feature_names = full_feature_names self.tags = tags or {} self.feature_service_name = feature_service_name + self.namespace = namespace + self.collection = collection + self.description = description self._retrieval_job = None @@ -136,6 +145,9 @@ def __eq__(self, other): or self.full_feature_names != other.full_feature_names or self.tags != other.tags or self.feature_service_name != other.feature_service_name + or self.namespace != other.namespace + or self.collection != other.collection + or self.description != other.description ): return False @@ -156,6 +168,9 @@ def from_proto(saved_dataset_proto: SavedDatasetProto): full_feature_names=saved_dataset_proto.spec.full_feature_names, storage=SavedDatasetStorage.from_proto(saved_dataset_proto.spec.storage), tags=dict(saved_dataset_proto.spec.tags.items()), + namespace=saved_dataset_proto.spec.namespace, + collection=saved_dataset_proto.spec.collection, + description=saved_dataset_proto.spec.description, ) if saved_dataset_proto.spec.feature_service_name: @@ -202,6 +217,9 @@ def to_proto(self) -> SavedDatasetProto: full_feature_names=self.full_feature_names, storage=self.storage.to_proto(), tags=self.tags, + namespace=self.namespace, + collection=self.collection, + description=self.description, ) if self.feature_service_name: spec.feature_service_name = self.feature_service_name From e6c3f28a2944ea6056907f87f47c52a105f44e9f Mon Sep 17 00:00:00 2001 From: ntkathole Date: Wed, 22 Jul 2026 13:57:23 +0530 Subject: [PATCH 2/2] feat: Updated datasets UI to support grouping Signed-off-by: ntkathole --- .../saved-data-sets/CreateDatasetForm.tsx | 48 + .../saved-data-sets/DatasetCatalogBrowser.tsx | 846 ++++++++++++++++++ .../saved-data-sets/DatasetOverviewTab.tsx | 30 + .../saved-data-sets/DatasetsCardGrid.tsx | 29 + .../saved-data-sets/DatasetsListingTable.tsx | 38 + .../saved-data-sets/EditDatasetModal.tsx | 55 ++ ui/src/pages/saved-data-sets/Index.tsx | 164 ++-- .../saved-data-sets/RegisterDatasetModal.tsx | 64 ++ 8 files changed, 1218 insertions(+), 56 deletions(-) create mode 100644 ui/src/pages/saved-data-sets/DatasetCatalogBrowser.tsx diff --git a/ui/src/pages/saved-data-sets/CreateDatasetForm.tsx b/ui/src/pages/saved-data-sets/CreateDatasetForm.tsx index a3be0bae8df..7260f0593ed 100644 --- a/ui/src/pages/saved-data-sets/CreateDatasetForm.tsx +++ b/ui/src/pages/saved-data-sets/CreateDatasetForm.tsx @@ -103,6 +103,9 @@ const CreateDatasetForm = ({ onClose }: CreateDatasetFormProps) => { // Step 3: Storage & metadata const [datasetName, setDatasetName] = useState(""); + const [namespace, setNamespace] = useState(""); + const [collection, setCollection] = useState(""); + const [description, setDescription] = useState(""); const [storageType, setStorageType] = useState("file"); const [storagePath, setStoragePath] = useState(""); const [tags, setTags] = useState([]); @@ -268,6 +271,10 @@ const CreateDatasetForm = ({ onClose }: CreateDatasetFormProps) => { ), }; + if (namespace.trim()) payload.namespace = namespace.trim(); + if (collection.trim()) payload.collection = collection.trim(); + if (description.trim()) payload.description = description.trim(); + if (featureMode === "service" && selectedService.length > 0) { payload.feature_service_name = selectedService[0].label; } else if (featureMode === "individual" && selectedFeatures.length > 0) { @@ -562,6 +569,47 @@ const CreateDatasetForm = ({ onClose }: CreateDatasetFormProps) => { /> + + setDescription(e.target.value)} + placeholder="e.g. Training data for driver fraud model" + fullWidth + /> + + + + + + setNamespace(e.target.value)} + placeholder="e.g. fraud" + /> + + + + + setCollection(e.target.value)} + placeholder="e.g. training" + /> + + + + + + diff --git a/ui/src/pages/saved-data-sets/DatasetCatalogBrowser.tsx b/ui/src/pages/saved-data-sets/DatasetCatalogBrowser.tsx new file mode 100644 index 00000000000..bcb2bd844a5 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetCatalogBrowser.tsx @@ -0,0 +1,846 @@ +import React, { useCallback, useMemo, useState } from "react"; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiTitle, + EuiText, + EuiBadge, + EuiSpacer, + EuiIcon, + EuiBreadcrumbs, + EuiEmptyPrompt, + EuiTreeView, + EuiToolTip, + EuiButtonIcon, + EuiCopy, +} from "@elastic/eui"; +import type { Node as EuiTreeNode } from "@elastic/eui/src/components/tree_view/tree_view"; +import { useNavigate, useParams } from "react-router-dom"; + +/* ────────────────────────── types ────────────────────────── */ + +interface BrowsePath { + namespace?: string; + collection?: string; +} + +interface DatasetCatalogBrowserProps { + datasets: any[]; + onDelete?: (name: string) => void; +} + +/* ──────────────────── hierarchy builder ──────────────────── */ + +function buildHierarchy(datasets: any[]) { + const tree: Record> = {}; + for (const ds of datasets) { + const ns = ds.spec?.namespace || ""; + const col = ds.spec?.collection || ""; + if (!tree[ns]) tree[ns] = {}; + if (!tree[ns][col]) tree[ns][col] = []; + tree[ns][col].push(ds); + } + return tree; +} + +/* ──────────────────── colors ──────────────────── */ + +const NS_COLOR = "#0077CC"; +const COL_COLOR = "#8B5CF6"; + +const STORAGE_TYPE_CONFIG: Record< + string, + { label: string; color: string; icon: string } +> = { + file: { label: "File", color: "#4CAF50", icon: "document" }, + bigquery: { label: "BigQuery", color: "#4285F4", icon: "storage" }, + snowflake: { label: "Snowflake", color: "#29B5E8", icon: "snowflake" }, + redshift: { label: "Redshift", color: "#205B97", icon: "compute" }, + spark: { label: "Spark", color: "#E25A1C", icon: "bolt" }, + trino: { label: "Trino", color: "#DD00A1", icon: "database" }, + athena: { label: "Athena", color: "#8C4FFF", icon: "database" }, + custom: { label: "Custom", color: "#607D8B", icon: "gear" }, + unknown: { label: "Storage", color: "#98A2B3", icon: "database" }, +}; + +function detectStorageType(dataset: any): string { + const storage = dataset?.spec?.storage; + if (!storage) return "unknown"; + if (storage.fileStorage) return "file"; + if (storage.bigqueryStorage) return "bigquery"; + if (storage.snowflakeStorage) return "snowflake"; + if (storage.redshiftStorage) return "redshift"; + if (storage.sparkStorage) return "spark"; + if (storage.trinoStorage) return "trino"; + if (storage.athenaStorage) return "athena"; + if (storage.customStorage) return "custom"; + return "unknown"; +} + +function extractStoragePath(dataset: any): string | undefined { + const storage = dataset?.spec?.storage; + if (!storage) return undefined; + if (storage.fileStorage?.uri) return storage.fileStorage.uri; + if (storage.bigqueryStorage?.table) return storage.bigqueryStorage.table; + if (storage.snowflakeStorage?.table) return storage.snowflakeStorage.table; + if (storage.redshiftStorage?.table) return storage.redshiftStorage.table; + if (storage.sparkStorage?.path) return storage.sparkStorage.path; + if (storage.sparkStorage?.table) return storage.sparkStorage.table; + if (storage.trinoStorage?.table) return storage.trinoStorage.table; + if (storage.athenaStorage?.table) return storage.athenaStorage.table; + if (storage.customStorage?.configuration) + return storage.customStorage.configuration; + return undefined; +} + +function truncatePath(path: string, maxLen: number = 42): string { + if (path.length <= maxLen) return path; + return `${path.slice(0, 18)}...${path.slice(-20)}`; +} + +function getRelativeTime(date: Date): string { + const diffMs = Date.now() - date.getTime(); + const diffDays = Math.floor(diffMs / 86400000); + if (diffDays === 0) return "Today"; + if (diffDays === 1) return "Yesterday"; + if (diffDays < 7) return `${diffDays}d ago`; + if (diffDays < 30) return `${Math.floor(diffDays / 7)}w ago`; + if (diffDays < 365) return `${Math.floor(diffDays / 30)}mo ago`; + return `${Math.floor(diffDays / 365)}y ago`; +} + +/* ──────────────────── tile: dataset card ──────────────────── */ + +const DatasetCard: React.FC<{ + dataset: any; + onNavigate: () => void; + onDelete?: (name: string) => void; +}> = ({ dataset, onNavigate, onDelete }) => { + const [isHovered, setIsHovered] = useState(false); + const spec = dataset.spec || {}; + const meta = dataset.meta || {}; + const name = spec.name || "unknown"; + const features = spec.features || []; + const joinKeys = spec.joinKeys || spec.join_keys || []; + const tags = spec.tags || {}; + const description = spec.description || ""; + const featureServiceName = + spec.featureServiceName || spec.feature_service_name; + const createdTimestamp = meta.createdTimestamp || meta.created_timestamp; + const storagePath = extractStoragePath(dataset); + const storageType = detectStorageType(dataset); + const storageInfo = + STORAGE_TYPE_CONFIG[storageType] || STORAGE_TYPE_CONFIG.unknown; + + const formattedDate = createdTimestamp + ? new Date(createdTimestamp).toLocaleDateString("en-US", { + month: "short", + day: "numeric", + year: "numeric", + }) + : null; + const relativeTime = createdTimestamp + ? getRelativeTime(new Date(createdTimestamp)) + : null; + + const codeSnippet = `dataset = store.get_saved_dataset("${name}")\ndf = dataset.to_df()`; + + return ( + + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + onClick={onNavigate} + style={{ + height: "100%", + display: "flex", + flexDirection: "column", + transition: "all 0.2s ease", + transform: isHovered ? "translateY(-2px)" : "none", + borderTop: `3px solid ${storageInfo.color}`, + cursor: "pointer", + }} + > + {/* Header */} + + + +

+ {name} +

+
+
+ + + {storageInfo.label} + + +
+ + {/* Description */} + {description && ( + +

{description}

+
+ )} + + + + {/* Storage path */} + {storagePath && ( + + + {" "} + + {truncatePath(storagePath)} + + + + )} + + + + {/* Metrics */} + + + + Features + + + {features.length} + + + + + Retrieval Keys + + + {joinKeys.length} + + + {featureServiceName && ( + + + Service + + + {featureServiceName} + + + )} + + +
+ + + {/* Tags */} + {Object.keys(tags).length > 0 && ( + <> + + {Object.entries(tags) + .slice(0, 3) + .map(([key, value]) => ( + + + {key}: {value as string} + + + ))} + {Object.keys(tags).length > 3 && ( + + + +{Object.keys(tags).length - 3} more + + + )} + + + + )} + + {/* Footer */} + + + {formattedDate && ( + + + {relativeTime} + + + )} + + + + + + {(copy) => ( + + { + e.stopPropagation(); + copy(); + }} + /> + + )} + + + {onDelete && ( + + + { + e.stopPropagation(); + onDelete(name); + }} + /> + + + )} + + + + + + ); +}; + +/* ──────────────────── tile: folder card (same width as dataset) ──────────────────── */ + +const FolderCard: React.FC<{ + name: string; + type: "namespace" | "collection"; + datasetCount: number; + collectionCount?: number; + onClick: () => void; +}> = ({ name, type, datasetCount, collectionCount, onClick }) => { + const [isHovered, setIsHovered] = useState(false); + const color = type === "namespace" ? NS_COLOR : COL_COLOR; + + return ( + + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + onClick={onClick} + style={{ + cursor: "pointer", + transition: "all 0.2s ease", + transform: isHovered ? "translateY(-2px)" : "none", + borderTop: `3px solid ${color}`, + display: "flex", + flexDirection: "column", + }} + > + + + + + + +

{name}

+
+
+
+ + + + + {type === "namespace" && + collectionCount !== undefined && + collectionCount > 0 && ( + + + Collections + + + {collectionCount} + + + )} + + + Datasets + + + {datasetCount} + + + +
+
+ ); +}; + +/* ──────────────────── tree styles ──────────────────── */ + +const TREE_CSS = ` + .catalogTree .euiTreeView__node { + margin-bottom: 1px; + } + .catalogTree .euiTreeView__node--expanded > .euiTreeView__nodeInner { + background: rgba(0, 119, 204, 0.05); + border-radius: 4px; + } + .catalogTree .euiTreeView__nodeInner { + padding: 4px 6px; + border-radius: 4px; + transition: background 0.15s ease; + } + .catalogTree .euiTreeView__nodeInner:hover { + background: rgba(0, 119, 204, 0.08); + } + .catalogTree .euiTreeView__nodeInner--withArrow .euiTreeView__nodeInner__arrow { + margin-right: 2px; + } + .catalogTree .euiTreeView__nodeLabel { + font-size: 13px; + } +`; + +/* ──────────────────── main component ──────────────────── */ + +const DatasetCatalogBrowser: React.FC = ({ + datasets, + onDelete, +}) => { + const { projectName } = useParams(); + const navigate = useNavigate(); + const [browsePath, setBrowsePath] = useState({}); + const [showTree, setShowTree] = useState(true); + + const hierarchy = useMemo(() => buildHierarchy(datasets), [datasets]); + + const namespaceList = useMemo(() => { + const entries: Array<{ + name: string; + collections: string[]; + totalDatasets: number; + }> = []; + for (const [ns, cols] of Object.entries(hierarchy)) { + if (ns === "") continue; + const colNames = Object.keys(cols) + .filter((c) => c !== "") + .sort(); + const total = Object.values(cols).reduce((s, a) => s + a.length, 0); + entries.push({ name: ns, collections: colNames, totalDatasets: total }); + } + entries.sort((a, b) => a.name.localeCompare(b.name)); + return entries; + }, [hierarchy]); + + const rootDatasets = useMemo(() => { + const cols = hierarchy[""]; + if (!cols) return []; + const all: any[] = []; + for (const arr of Object.values(cols)) all.push(...arr); + return all; + }, [hierarchy]); + + const goToDataset = useCallback( + (dataset: any) => { + const p = dataset.project || dataset.spec?.project || projectName; + const n = dataset.spec?.name || dataset.name; + navigate(`/p/${p}/data-set/${n}`); + }, + [navigate, projectName], + ); + + /* ── tree sidebar (EuiTreeView) ── */ + + // Clickable label for parent nodes — onClick navigates, stopPropagation prevents toggle + const navLabel = useCallback( + ( + text: string, + onClick: () => void, + isActive: boolean, + activeColor?: string, + ) => ( + { + e.stopPropagation(); + onClick(); + }} + style={{ + cursor: "pointer", + fontWeight: isActive ? 600 : 400, + color: isActive ? activeColor || NS_COLOR : undefined, + }} + > + {text} + + ), + [], + ); + + const treeItems: EuiTreeNode[] = useMemo(() => { + const isRootSelected = browsePath.namespace === undefined; + const items: EuiTreeNode[] = [ + { + id: "_root", + label: navLabel( + "All Datasets", + () => setBrowsePath({}), + isRootSelected, + ), + icon: , + isExpanded: true, + }, + ]; + + for (const ns of namespaceList) { + const nsData = hierarchy[ns.name] || {}; + const nsChildren: EuiTreeNode[] = []; + const nsSelected = + browsePath.namespace === ns.name && !browsePath.collection; + + // Collection sub-folders + for (const col of ns.collections) { + const colDatasets = nsData[col] || []; + const colSelected = + browsePath.namespace === ns.name && browsePath.collection === col; + + const dsLeaves: EuiTreeNode[] = colDatasets.map((ds: any) => ({ + id: `ds:${ns.name}/${col}/${ds.spec?.name || ds.name}`, + label: ds.spec?.name || ds.name || "unknown", + icon: , + callback: () => { + goToDataset(ds); + return `ds:${ns.name}/${col}/${ds.spec?.name}`; + }, + })); + + nsChildren.push({ + id: `col:${ns.name}/${col}`, + label: navLabel( + `${col} (${colDatasets.length})`, + () => setBrowsePath({ namespace: ns.name, collection: col }), + colSelected, + COL_COLOR, + ), + icon: , + iconWhenExpanded: ( + + ), + children: dsLeaves.length > 0 ? dsLeaves : undefined, + }); + } + + // Direct datasets under namespace (no collection) + const directDatasets = nsData[""] || []; + for (const ds of directDatasets) { + nsChildren.push({ + id: `ds:${ns.name}/_/${ds.spec?.name || ds.name}`, + label: ds.spec?.name || ds.name || "unknown", + icon: , + callback: () => { + goToDataset(ds); + return `ds:${ns.name}/_/${ds.spec?.name}`; + }, + }); + } + + items.push({ + id: `ns:${ns.name}`, + label: navLabel( + `${ns.name} (${ns.totalDatasets})`, + () => setBrowsePath({ namespace: ns.name }), + nsSelected, + NS_COLOR, + ), + icon: , + iconWhenExpanded: ( + + ), + children: nsChildren.length > 0 ? nsChildren : undefined, + }); + } + + // Ungrouped datasets + if (rootDatasets.length > 0) { + const ungroupedLeaves: EuiTreeNode[] = rootDatasets.map((ds: any) => ({ + id: `ds:_ungrouped/${ds.spec?.name || ds.name}`, + label: ds.spec?.name || ds.name || "unknown", + icon: , + callback: () => { + goToDataset(ds); + return `ds:_ungrouped/${ds.spec?.name}`; + }, + })); + + items.push({ + id: "_ungrouped", + label: navLabel( + `Ungrouped (${rootDatasets.length})`, + () => setBrowsePath({}), + false, + "#98A2B3", + ), + icon: , + children: ungroupedLeaves, + }); + } + + return items; + }, [ + namespaceList, + rootDatasets, + hierarchy, + browsePath, + goToDataset, + navLabel, + ]); + + /* ── breadcrumbs ── */ + const breadcrumbs = useMemo(() => { + const crumbs: Array<{ text: string; onClick?: () => void }> = [ + { + text: "All Datasets", + onClick: + browsePath.namespace !== undefined + ? () => setBrowsePath({}) + : undefined, + }, + ]; + if (browsePath.namespace) { + crumbs.push({ + text: browsePath.namespace, + onClick: browsePath.collection + ? () => setBrowsePath({ namespace: browsePath.namespace }) + : undefined, + }); + if (browsePath.collection) { + crumbs.push({ text: browsePath.collection }); + } + } + return crumbs; + }, [browsePath]); + + /* ── content ── */ + const renderContent = () => { + // ─── Root level: namespace folders + datasets mixed in one grid ─── + if (browsePath.namespace === undefined) { + if (namespaceList.length === 0 && rootDatasets.length === 0) { + return ( + No datasets yet} + body={ +

+ Add datasets and organize them into namespaces and collections. +

+ } + /> + ); + } + + return ( + + {namespaceList.map((ns) => ( + setBrowsePath({ namespace: ns.name })} + /> + ))} + {rootDatasets.map((d: any) => ( + goToDataset(d)} + onDelete={onDelete} + /> + ))} + + ); + } + + // ─── Namespace level: collection folders + direct datasets mixed ─── + if (browsePath.namespace && !browsePath.collection) { + const ns = browsePath.namespace; + const cols = hierarchy[ns] || {}; + const colNames = Object.keys(cols) + .filter((c) => c !== "") + .sort(); + const directDs = cols[""] || []; + + return ( + + {colNames.map((col) => ( + setBrowsePath({ namespace: ns, collection: col })} + /> + ))} + {directDs.map((d: any) => ( + goToDataset(d)} + onDelete={onDelete} + /> + ))} + {colNames.length === 0 && directDs.length === 0 && ( + + + This namespace is empty. + + + )} + + ); + } + + // ─── Collection level: datasets only ─── + if (browsePath.namespace && browsePath.collection) { + const dsList = + hierarchy[browsePath.namespace]?.[browsePath.collection] || []; + + return ( + + {dsList.map((d: any) => ( + goToDataset(d)} + onDelete={onDelete} + /> + ))} + {dsList.length === 0 && ( + + + No datasets in this collection. + + + )} + + ); + } + + return null; + }; + + /* ──────────────────── render ──────────────────── */ + + const hasTree = namespaceList.length > 0; + + return ( +
+ {/* Tree sidebar */} + {hasTree && ( +
+ {showTree ? ( + <> +
+ + + Catalog + + + + setShowTree(false)} + /> + +
+ +
+ + +
+ + ) : ( + + setShowTree(true)} + /> + + )} +
+ )} + + {/* Content */} +
+ + + {renderContent()} +
+
+ ); +}; + +export default DatasetCatalogBrowser; diff --git a/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx b/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx index b765da70241..b0d8fc61f28 100644 --- a/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx +++ b/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx @@ -96,6 +96,9 @@ const DatasetOverviewTab = () => { const tags = data.spec?.tags || {}; const featureServiceName = data.spec?.featureServiceName || data.spec?.feature_service_name; + const namespace = data.spec?.namespace || ""; + const collection = data.spec?.collection || ""; + const description = data.spec?.description || ""; const createdTs = data.meta?.createdTimestamp || data.meta?.created_timestamp; const minEventTs = data.meta?.minEventTimestamp || data.meta?.min_event_timestamp; @@ -168,6 +171,33 @@ const DatasetOverviewTab = () => { + {description && ( + <> + Description + + {description} + + + )} + + {namespace && ( + <> + Namespace + + {namespace} + + + )} + + {collection && ( + <> + Collection + + {collection} + + + )} + Storage Type {storageInfo.type} diff --git a/ui/src/pages/saved-data-sets/DatasetsCardGrid.tsx b/ui/src/pages/saved-data-sets/DatasetsCardGrid.tsx index 2c96a0ee109..5b6c33038ff 100644 --- a/ui/src/pages/saved-data-sets/DatasetsCardGrid.tsx +++ b/ui/src/pages/saved-data-sets/DatasetsCardGrid.tsx @@ -103,6 +103,9 @@ const DatasetCard: React.FC = ({ const tags = spec.tags || {}; const featureServiceName = spec.featureServiceName || spec.feature_service_name; + const namespace = spec.namespace || ""; + const collection = spec.collection || ""; + const description = spec.description || ""; const createdTimestamp = meta.createdTimestamp || meta.created_timestamp; const storagePath = extractStoragePath(dataset); const storageType = detectStorageType(dataset); @@ -169,6 +172,32 @@ const DatasetCard: React.FC = ({ + {/* Description */} + {description && ( + +

{description}

+
+ )} + + {/* Namespace / Collection badges */} + {(namespace || collection) && ( + <> + + + {namespace && ( + + {namespace} + + )} + {collection && ( + + {collection} + + )} + + + )} + {/* Storage path */} diff --git a/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx index 823f42176f3..251af853ac7 100644 --- a/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx +++ b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx @@ -35,6 +35,44 @@ const DatasetsListingTable = ({ datasets }: DatasetsListingTableProps) => { ); }, }, + { + name: "Namespace", + render: (item: any) => { + const ns = item.spec?.namespace; + return ns ? ( + {ns} + ) : ( + + ); + }, + width: "140px", + }, + { + name: "Collection", + render: (item: any) => { + const col = item.spec?.collection; + return col ? ( + {col} + ) : ( + + ); + }, + width: "140px", + }, + { + name: "Description", + render: (item: any) => { + const desc = item.spec?.description; + return desc ? ( + + {desc.length > 50 ? desc.slice(0, 50) + "…" : desc} + + ) : ( + + ); + }, + width: "200px", + }, { name: "Features", render: (item: any) => (item.spec?.features || []).length, diff --git a/ui/src/pages/saved-data-sets/EditDatasetModal.tsx b/ui/src/pages/saved-data-sets/EditDatasetModal.tsx index db567a15703..77c938e3973 100644 --- a/ui/src/pages/saved-data-sets/EditDatasetModal.tsx +++ b/ui/src/pages/saved-data-sets/EditDatasetModal.tsx @@ -307,6 +307,9 @@ const EditDatasetModal = ({ // Form state const [storagePath, setStoragePath] = useState(extractStoragePath(dataset)); const [storageType, setStorageType] = useState(detectStorageType(dataset)); + const [namespace, setNamespace] = useState(spec.namespace || ""); + const [collection, setCollection] = useState(spec.collection || ""); + const [description, setDescription] = useState(spec.description || ""); const [featuresInput, setFeaturesInput] = useState( (spec.features || []).map((f: string) => ({ label: f })), ); @@ -368,6 +371,9 @@ const EditDatasetModal = ({ tags: tagsObj, full_feature_names: fullFeatureNames, feature_service_name: featureServiceName || undefined, + namespace: namespace.trim() || undefined, + collection: collection.trim() || undefined, + description: description.trim() || undefined, allow_override: true, }; await onSubmit(payload); @@ -421,6 +427,20 @@ const EditDatasetModal = ({ + + + setDescription(e.target.value)} + placeholder="e.g. Training data for driver fraud model" + /> + + + + + + + {/* Organization */} + +

Organization (optional)

+
+ + + + + + setNamespace(e.target.value)} + placeholder="e.g. fraud" + /> + + + + + setCollection(e.target.value)} + placeholder="e.g. training" + /> + + + + diff --git a/ui/src/pages/saved-data-sets/Index.tsx b/ui/src/pages/saved-data-sets/Index.tsx index 78770c5aaf8..1c587d83883 100644 --- a/ui/src/pages/saved-data-sets/Index.tsx +++ b/ui/src/pages/saved-data-sets/Index.tsx @@ -16,7 +16,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, - EuiStat, EuiPanel, EuiSelect, EuiText, @@ -32,6 +31,7 @@ import { DatasetIcon } from "../../graphics/DatasetIcon"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; import DatasetsCardGrid from "./DatasetsCardGrid"; import DatasetsListingTable from "./DatasetsListingTable"; +import DatasetCatalogBrowser from "./DatasetCatalogBrowser"; import DatasetsIndexEmptyState from "./DatasetsIndexEmptyState"; import AddToCatalogModal from "./AddToCatalogModal"; import type { RegisterDatasetPayload } from "./RegisterDatasetModal"; @@ -62,6 +62,7 @@ const SORT_OPTIONS = [ ]; const VIEW_TOGGLE_BUTTONS = [ + { id: "catalog", label: "Catalog", iconType: "folderClosed" }, { id: "cards", label: "Cards", iconType: "grid" }, { id: "table", label: "Table", iconType: "list" }, ]; @@ -84,7 +85,8 @@ const Index = () => { const [deleteTarget, setDeleteTarget] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const [sortBy, setSortBy] = useState("created_desc"); - const [viewMode, setViewMode] = useState("cards"); + const [viewMode, setViewMode] = useState("catalog"); + const [namespaceFilter, setNamespaceFilter] = useState("all"); const [submitError, setSubmitError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); @@ -197,12 +199,18 @@ const Index = () => { // Compute summary stats const stats = useMemo(() => { if (!data) - return { total: 0, totalFeatures: 0, storageTypes: new Set() }; + return { + total: 0, + totalFeatures: 0, + storageTypes: new Set(), + namespaces: [] as string[], + }; const totalFeatures = data.reduce( (acc: number, ds: any) => acc + (ds.spec?.features?.length || 0), 0, ); const storageTypes = new Set(); + const namespacesSet = new Set(); data.forEach((ds: any) => { const storage = ds.spec?.storage; if (storage?.fileStorage) storageTypes.add("File"); @@ -213,8 +221,11 @@ const Index = () => { else if (storage?.trinoStorage) storageTypes.add("Trino"); else if (storage?.athenaStorage) storageTypes.add("Athena"); else if (storage?.customStorage) storageTypes.add("Custom"); + const ns = ds.spec?.namespace; + if (ns) namespacesSet.add(ns); }); - return { total: data.length, totalFeatures, storageTypes }; + const namespaces = Array.from(namespacesSet).sort(); + return { total: data.length, totalFeatures, storageTypes, namespaces }; }, [data]); // Filter and sort @@ -222,9 +233,20 @@ const Index = () => { if (!data) return []; let filtered = data; + // Namespace filter + if (namespaceFilter !== "all") { + if (namespaceFilter === "_none") { + filtered = filtered.filter((ds: any) => !ds.spec?.namespace); + } else { + filtered = filtered.filter( + (ds: any) => ds.spec?.namespace === namespaceFilter, + ); + } + } + if (searchQuery.trim()) { const q = searchQuery.toLowerCase(); - filtered = data.filter((ds: any) => { + filtered = filtered.filter((ds: any) => { const name = (ds.spec?.name || "").toLowerCase(); const tags = JSON.stringify(ds.spec?.tags || {}).toLowerCase(); const features = (ds.spec?.features || []).join(" ").toLowerCase(); @@ -233,11 +255,17 @@ const Index = () => { ds.spec?.feature_service_name || "" ).toLowerCase(); + const ns = (ds.spec?.namespace || "").toLowerCase(); + const col = (ds.spec?.collection || "").toLowerCase(); + const desc = (ds.spec?.description || "").toLowerCase(); return ( name.includes(q) || tags.includes(q) || features.includes(q) || - service.includes(q) + service.includes(q) || + ns.includes(q) || + col.includes(q) || + desc.includes(q) ); }); } @@ -254,7 +282,7 @@ const Index = () => { }); return filtered; - }, [data, searchQuery, sortBy]); + }, [data, searchQuery, sortBy, namespaceFilter]); const hasData = data && data.length > 0; @@ -434,53 +462,71 @@ const Index = () => { {isSuccess && hasData && ( <> - {/* Summary Stats */} - - - - - - - - - - + {/* View mode toggle — always visible */} + + + + + + {stats.total} datasets + {stats.namespaces.length > 0 && ( + <> + {" "} + across {stats.namespaces.length}{" "} + namespaces + + )} + + + - - - - + + setViewMode(id)} + isIconOnly + buttonSize="compressed" + /> - + - {/* Search + Sort + View Toggle */} + {/* Search + Namespace Filter + Sort — shared toolbar */} setSearchQuery(e.target.value)} isClearable fullWidth /> + {stats.namespaces.length > 0 && ( + + ({ + value: ns, + text: ns, + })), + ]} + value={namespaceFilter} + onChange={(e) => setNamespaceFilter(e.target.value)} + compressed + prepend="Namespace" + /> + + )} { prepend="Sort" /> - - setViewMode(id)} - isIconOnly - buttonSize="compressed" - /> - - + - {/* Results count when searching */} - {searchQuery.trim() && ( + {/* Results count when filtering */} + {(searchQuery.trim() || namespaceFilter !== "all") && ( <> Showing {processedData.length} of {data.length} datasets + {namespaceFilter !== "all" && namespaceFilter !== "_none" && ( + <> + {" "} + in namespace {namespaceFilter} + + )} + {namespaceFilter === "_none" && <> with no namespace} )} - {/* Content */} - {viewMode === "cards" ? ( + {/* Catalog (hierarchical) view */} + {viewMode === "catalog" && ( + setDeleteTarget(name)} + /> + )} + + {/* Flat views (cards / table) */} + {viewMode === "cards" && ( setDeleteTarget(name)} /> - ) : ( + )} + {viewMode === "table" && ( )} diff --git a/ui/src/pages/saved-data-sets/RegisterDatasetModal.tsx b/ui/src/pages/saved-data-sets/RegisterDatasetModal.tsx index 90f93b8ca31..fa4013d661c 100644 --- a/ui/src/pages/saved-data-sets/RegisterDatasetModal.tsx +++ b/ui/src/pages/saved-data-sets/RegisterDatasetModal.tsx @@ -37,6 +37,9 @@ export interface RegisterDatasetPayload { tags: Record; full_feature_names: boolean; feature_service_name?: string; + namespace?: string; + collection?: string; + description?: string; } interface RegisterDatasetModalProps { @@ -241,6 +244,9 @@ const RegisterDatasetModal = ({ // Form state const [name, setName] = useState(""); + const [namespace, setNamespace] = useState(""); + const [collection, setCollection] = useState(""); + const [description, setDescription] = useState(""); const [storagePath, setStoragePath] = useState(""); const [storageType, setStorageType] = useState("file"); const [featuresInput, setFeaturesInput] = useState( @@ -339,6 +345,9 @@ const RegisterDatasetModal = ({ tags: tagsObj, full_feature_names: fullFeatureNames, feature_service_name: featureServiceName || undefined, + namespace: namespace.trim() || undefined, + collection: collection.trim() || undefined, + description: description.trim() || undefined, }; await onSubmit(payload); }; @@ -395,6 +404,18 @@ const RegisterDatasetModal = ({ /> + + + setDescription(e.target.value)} + placeholder="e.g. Training data for driver fraud model" + /> + + + + + {/* Section: Organization */} + +

Organization (optional)

+
+ + + + + Group datasets into namespaces and collections for hierarchical + organization. Leave empty to keep the dataset at the top level. + + + + + + + + setNamespace(e.target.value)} + placeholder="e.g. fraud" + /> + + + + + setCollection(e.target.value)} + placeholder="e.g. training" + /> + + + +