diff --git a/docs/reference/feature-servers/registry-server.md b/docs/reference/feature-servers/registry-server.md index 496eaa8badc..4558a10ce63 100644 --- a/docs/reference/feature-servers/registry-server.md +++ b/docs/reference/feature-servers/registry-server.md @@ -214,6 +214,7 @@ Most endpoints support these common query parameters: - `feature` (optional): Filter feature views by feature name - `feature_service` (optional): Filter feature views by feature service name - `data_source` (optional): Filter feature views by data source name + - `updated_since` (optional): Only return feature views updated at or after this ISO-8601 UTC timestamp (e.g. `2024-01-01T00:00:00Z`) - `page` (optional): Page number for pagination - `limit` (optional): Number of items per page - `sort_by` (optional): Field to sort by @@ -223,27 +224,31 @@ Most endpoints support these common query parameters: # Basic list curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project" - + # With pagination and relationships curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&include_relationships=true&page=1&limit=5&sort_by=name" - + # Filter by entity curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&entity=user" - + # Filter by feature curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&feature=age" - + # Filter by data source curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&data_source=user_profile_source" - + # Filter by feature service curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&feature_service=user_service" - + + # Filter by last-updated timestamp + curl -H "Authorization: Bearer " \ + "http://localhost:6572/api/v1/feature_views?project=my_project&updated_since=2024-06-01T00:00:00Z" + # Multiple filters combined curl -H "Authorization: Bearer " \ "http://localhost:6572/api/v1/feature_views?project=my_project&entity=user&feature=age" diff --git a/protos/feast/registry/RegistryServer.proto b/protos/feast/registry/RegistryServer.proto index fcbacd76609..cd60d47939f 100644 --- a/protos/feast/registry/RegistryServer.proto +++ b/protos/feast/registry/RegistryServer.proto @@ -291,6 +291,7 @@ message ListAllFeatureViewsRequest { string data_source = 7; PaginationParams pagination = 8; SortingParams sorting = 9; + google.protobuf.Timestamp updated_since = 10; } message ListAllFeatureViewsResponse { diff --git a/sdk/python/feast/api/registry/rest/feature_views.py b/sdk/python/feast/api/registry/rest/feature_views.py index 1f6e6604c80..0e46e921c48 100644 --- a/sdk/python/feast/api/registry/rest/feature_views.py +++ b/sdk/python/feast/api/registry/rest/feature_views.py @@ -1,8 +1,10 @@ import logging +from datetime import timezone from typing import Dict, List, Optional -from fastapi import APIRouter, Depends, Query +from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import JSONResponse +from google.protobuf import timestamp_pb2 from google.protobuf.duration_pb2 import Duration from pydantic import BaseModel @@ -266,10 +268,34 @@ def list_all_feature_views( data_source: str = Query( None, description="Filter feature views by data source name" ), + updated_since: Optional[str] = Query( + None, + description="Only return feature views updated at or after this ISO-8601 UTC timestamp (e.g. 2024-01-01T00:00:00Z)", + ), tags: Dict[str, str] = Depends(parse_tags), pagination_params: dict = Depends(get_pagination_params), sorting_params: dict = Depends(get_sorting_params), ): + updated_since_proto = None + if updated_since is not None: + from datetime import datetime + + try: + dt = datetime.fromisoformat(updated_since.replace("Z", "+00:00")) + except ValueError: + raise HTTPException( + status_code=400, + detail=( + f"Invalid 'updated_since' value '{updated_since}'; expected an " + "ISO-8601 timestamp (e.g. 2024-01-01T00:00:00Z)." + ), + ) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + ts = timestamp_pb2.Timestamp() + ts.FromDatetime(dt.astimezone(timezone.utc)) + updated_since_proto = ts + req = RegistryServer_pb2.ListAllFeatureViewsRequest( project=project, allow_cache=allow_cache, @@ -280,6 +306,7 @@ def list_all_feature_views( data_source=data_source, pagination=create_grpc_pagination_params(pagination_params), sorting=create_grpc_sorting_params(sorting_params), + updated_since=updated_since_proto, ) response = grpc_call(grpc_handler.ListAllFeatureViews, req) any_feature_views = response.get("featureViews", []) diff --git a/sdk/python/feast/infra/registry/base_registry.py b/sdk/python/feast/infra/registry/base_registry.py index 09f47caac87..a0d98d5d2c2 100644 --- a/sdk/python/feast/infra/registry/base_registry.py +++ b/sdk/python/feast/infra/registry/base_registry.py @@ -567,6 +567,7 @@ def list_all_feature_views( allow_cache: bool = False, tags: Optional[dict[str, str]] = None, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ) -> List[BaseFeatureView]: """ Retrieve a list of feature views of all types from the registry @@ -576,6 +577,7 @@ def list_all_feature_views( project: Filter feature views based on project name tags: Filter by tags skip_udf: Skip deserializing UDFs (for metadata-only operations) + updated_since: Only return feature views updated at or after this timestamp Returns: List of feature views diff --git a/sdk/python/feast/infra/registry/caching_registry.py b/sdk/python/feast/infra/registry/caching_registry.py index d7a1f742d6e..6780a2ece69 100644 --- a/sdk/python/feast/infra/registry/caching_registry.py +++ b/sdk/python/feast/infra/registry/caching_registry.py @@ -3,7 +3,7 @@ import threading import warnings from abc import abstractmethod -from datetime import timedelta +from datetime import datetime, timedelta from threading import Lock from typing import Any, Dict, List, Optional @@ -23,7 +23,7 @@ from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView -from feast.utils import _utc_now +from feast.utils import _utc_now, to_naive_utc logger = logging.getLogger(__name__) @@ -122,7 +122,11 @@ def get_any_feature_view( @abstractmethod def _list_all_feature_views( - self, project: str, tags: Optional[dict[str, str]], **kwargs: Any + self, + project: str, + tags: Optional[dict[str, str]], + updated_since: Optional[datetime] = None, + **kwargs: Any, ) -> List[BaseFeatureView]: pass @@ -132,13 +136,27 @@ def list_all_feature_views( allow_cache: bool = False, tags: Optional[dict[str, str]] = None, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ) -> List[BaseFeatureView]: if allow_cache: self._refresh_cached_registry_if_necessary() - return proto_registry_utils.list_all_feature_views( + feature_views = proto_registry_utils.list_all_feature_views( self.cached_registry_proto, project, tags, skip_udf=skip_udf ) - return self._list_all_feature_views(project, tags, skip_udf=skip_udf) + if updated_since is not None: + # last_updated_timestamp from proto is offset-naive UTC; normalise for comparison + cutoff = to_naive_utc(updated_since) + feature_views = [ + fv + for fv in feature_views + if fv.last_updated_timestamp is not None + and fv.last_updated_timestamp >= cutoff + ] + else: + feature_views = self._list_all_feature_views( + project, tags, updated_since=updated_since, skip_udf=skip_udf + ) + return feature_views @abstractmethod def _get_feature_view(self, name: str, project: str) -> FeatureView: diff --git a/sdk/python/feast/infra/registry/registry.py b/sdk/python/feast/infra/registry/registry.py index 2933d721551..222777b325e 100644 --- a/sdk/python/feast/infra/registry/registry.py +++ b/sdk/python/feast/infra/registry/registry.py @@ -58,7 +58,7 @@ from feast.repo_contents import RepoContents from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView -from feast.utils import _utc_now +from feast.utils import _utc_now, to_naive_utc from feast.version_utils import ( generate_version_id, parse_version, @@ -1083,13 +1083,24 @@ def list_all_feature_views( allow_cache: bool = False, tags: Optional[dict[str, str]] = None, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ) -> List[BaseFeatureView]: registry_proto = self._get_registry_proto( project=project, allow_cache=allow_cache ) - return proto_registry_utils.list_all_feature_views( + feature_views = proto_registry_utils.list_all_feature_views( registry_proto, project, tags, skip_udf=skip_udf ) + if updated_since is not None: + # last_updated_timestamp from proto is offset-naive UTC; normalise for comparison + cutoff = to_naive_utc(updated_since) + feature_views = [ + fv + for fv in feature_views + if fv.last_updated_timestamp is not None + and fv.last_updated_timestamp >= cutoff + ] + return feature_views def get_any_feature_view( self, name: str, project: str, allow_cache: bool = False diff --git a/sdk/python/feast/infra/registry/remote.py b/sdk/python/feast/infra/registry/remote.py index 677183840ff..287eb3fda17 100644 --- a/sdk/python/feast/infra/registry/remote.py +++ b/sdk/python/feast/infra/registry/remote.py @@ -403,9 +403,18 @@ def list_all_feature_views( allow_cache: bool = False, tags: Optional[dict[str, str]] = None, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ) -> List[BaseFeatureView]: + updated_since_proto = None + if updated_since is not None: + ts = Timestamp() + ts.FromDatetime(updated_since) + updated_since_proto = ts request = RegistryServer_pb2.ListAllFeatureViewsRequest( - project=project, allow_cache=allow_cache, tags=tags + project=project, + allow_cache=allow_cache, + tags=tags, + updated_since=updated_since_proto, ) response: RegistryServer_pb2.ListAllFeatureViewsResponse = ( diff --git a/sdk/python/feast/infra/registry/snowflake.py b/sdk/python/feast/infra/registry/snowflake.py index 3b528209b1a..5590e1b7574 100644 --- a/sdk/python/feast/infra/registry/snowflake.py +++ b/sdk/python/feast/infra/registry/snowflake.py @@ -62,7 +62,7 @@ from feast.repo_config import RegistryConfig from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView -from feast.utils import _utc_now, has_all_tags +from feast.utils import _utc_now, has_all_tags, to_naive_utc logger = logging.getLogger(__name__) @@ -656,14 +656,24 @@ def list_all_feature_views( allow_cache: bool = False, tags: Optional[dict[str, str]] = None, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ) -> List[BaseFeatureView]: if allow_cache: registry_proto = self._refresh_cached_registry_if_necessary() - return proto_registry_utils.list_all_feature_views( + feature_views = proto_registry_utils.list_all_feature_views( registry_proto, project, tags, skip_udf=skip_udf ) + if updated_since is not None: + cutoff = to_naive_utc(updated_since) + feature_views = [ + fv + for fv in feature_views + if fv.last_updated_timestamp is not None + and fv.last_updated_timestamp >= cutoff + ] + return feature_views - return ( + feature_views = ( cast( list[BaseFeatureView], self.list_feature_views(project, allow_cache, tags, skip_udf=skip_udf), @@ -686,6 +696,17 @@ def list_all_feature_views( ) ) + if updated_since is not None: + cutoff = to_naive_utc(updated_since) + feature_views = [ + fv + for fv in feature_views + if fv.last_updated_timestamp is not None + and fv.last_updated_timestamp >= cutoff + ] + + return feature_views + def get_infra(self, project: str, allow_cache: bool = False) -> Infra: infra_object = self._get_object( "MANAGED_INFRA", diff --git a/sdk/python/feast/infra/registry/sql.py b/sdk/python/feast/infra/registry/sql.py index 531ab496776..c84097f9ad3 100644 --- a/sdk/python/feast/infra/registry/sql.py +++ b/sdk/python/feast/infra/registry/sql.py @@ -485,26 +485,36 @@ def _get_any_feature_view(self, name: str, project: str) -> BaseFeatureView: return fv def _list_all_feature_views( - self, project: str, tags: Optional[dict[str, str]], **kwargs + self, + project: str, + tags: Optional[dict[str, str]], + updated_since: Optional[datetime] = None, + **kwargs, ) -> List[BaseFeatureView]: return ( cast( list[BaseFeatureView], - self._list_feature_views(project=project, tags=tags, **kwargs), + self._list_feature_views( + project=project, tags=tags, updated_since=updated_since, **kwargs + ), ) + cast( list[BaseFeatureView], - self._list_stream_feature_views(project=project, tags=tags, **kwargs), + self._list_stream_feature_views( + project=project, tags=tags, updated_since=updated_since, **kwargs + ), ) + cast( list[BaseFeatureView], self._list_on_demand_feature_views( - project=project, tags=tags, **kwargs + project=project, tags=tags, updated_since=updated_since, **kwargs ), ) + cast( list[BaseFeatureView], - self._list_label_views(project=project, tags=tags, **kwargs), + self._list_label_views( + project=project, tags=tags, updated_since=updated_since, **kwargs + ), ) ) @@ -1597,6 +1607,7 @@ def _list_objects( tags: Optional[dict[str, str]] = None, proto_only: bool = False, skip_udf: bool = False, + updated_since: Optional[datetime] = None, ): """ Args: @@ -1618,6 +1629,17 @@ def _list_objects( with self.read_engine.begin() as conn: stmt = select(table).where(table.c.project_id == project) + if updated_since is not None: + # Ensure naive datetimes are treated as UTC, consistent with + # the Python-side filters that compare against offset-naive UTC + # last_updated_timestamp values from protobuf. + if updated_since.tzinfo is None: + updated_since_utc = updated_since.replace(tzinfo=timezone.utc) + else: + updated_since_utc = updated_since.astimezone(timezone.utc) + stmt = stmt.where( + table.c.last_updated_timestamp >= int(updated_since_utc.timestamp()) + ) rows = conn.execute(stmt).all() if rows: objects = [] diff --git a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.py index 78052df8d1b..25766701899 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\"\xe8\x02\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\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\"\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') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -126,137 +126,137 @@ _globals['_GETANYFEATUREVIEWRESPONSE']._serialized_start=3783 _globals['_GETANYFEATUREVIEWRESPONSE']._serialized_end=3868 _globals['_LISTALLFEATUREVIEWSREQUEST']._serialized_start=3871 - _globals['_LISTALLFEATUREVIEWSREQUEST']._serialized_end=4231 + _globals['_LISTALLFEATUREVIEWSREQUEST']._serialized_end=4282 _globals['_LISTALLFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTALLFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTALLFEATUREVIEWSRESPONSE']._serialized_start=4234 - _globals['_LISTALLFEATUREVIEWSRESPONSE']._serialized_end=4374 - _globals['_GETSTREAMFEATUREVIEWREQUEST']._serialized_start=4376 - _globals['_GETSTREAMFEATUREVIEWREQUEST']._serialized_end=4457 - _globals['_LISTSTREAMFEATUREVIEWSREQUEST']._serialized_start=4460 - _globals['_LISTSTREAMFEATUREVIEWSREQUEST']._serialized_end=4747 + _globals['_LISTALLFEATUREVIEWSRESPONSE']._serialized_start=4285 + _globals['_LISTALLFEATUREVIEWSRESPONSE']._serialized_end=4425 + _globals['_GETSTREAMFEATUREVIEWREQUEST']._serialized_start=4427 + _globals['_GETSTREAMFEATUREVIEWREQUEST']._serialized_end=4508 + _globals['_LISTSTREAMFEATUREVIEWSREQUEST']._serialized_start=4511 + _globals['_LISTSTREAMFEATUREVIEWSREQUEST']._serialized_end=4798 _globals['_LISTSTREAMFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTSTREAMFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTSTREAMFEATUREVIEWSRESPONSE']._serialized_start=4750 - _globals['_LISTSTREAMFEATUREVIEWSRESPONSE']._serialized_end=4899 - _globals['_GETONDEMANDFEATUREVIEWREQUEST']._serialized_start=4901 - _globals['_GETONDEMANDFEATUREVIEWREQUEST']._serialized_end=4984 - _globals['_LISTONDEMANDFEATUREVIEWSREQUEST']._serialized_start=4987 - _globals['_LISTONDEMANDFEATUREVIEWSREQUEST']._serialized_end=5278 + _globals['_LISTSTREAMFEATUREVIEWSRESPONSE']._serialized_start=4801 + _globals['_LISTSTREAMFEATUREVIEWSRESPONSE']._serialized_end=4950 + _globals['_GETONDEMANDFEATUREVIEWREQUEST']._serialized_start=4952 + _globals['_GETONDEMANDFEATUREVIEWREQUEST']._serialized_end=5035 + _globals['_LISTONDEMANDFEATUREVIEWSREQUEST']._serialized_start=5038 + _globals['_LISTONDEMANDFEATUREVIEWSREQUEST']._serialized_end=5329 _globals['_LISTONDEMANDFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTONDEMANDFEATUREVIEWSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTONDEMANDFEATUREVIEWSRESPONSE']._serialized_start=5281 - _globals['_LISTONDEMANDFEATUREVIEWSRESPONSE']._serialized_end=5437 - _globals['_GETLABELVIEWREQUEST']._serialized_start=5439 - _globals['_GETLABELVIEWREQUEST']._serialized_end=5512 - _globals['_LISTLABELVIEWSREQUEST']._serialized_start=5515 - _globals['_LISTLABELVIEWSREQUEST']._serialized_end=5786 + _globals['_LISTONDEMANDFEATUREVIEWSRESPONSE']._serialized_start=5332 + _globals['_LISTONDEMANDFEATUREVIEWSRESPONSE']._serialized_end=5488 + _globals['_GETLABELVIEWREQUEST']._serialized_start=5490 + _globals['_GETLABELVIEWREQUEST']._serialized_end=5563 + _globals['_LISTLABELVIEWSREQUEST']._serialized_start=5566 + _globals['_LISTLABELVIEWSREQUEST']._serialized_end=5837 _globals['_LISTLABELVIEWSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTLABELVIEWSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTLABELVIEWSRESPONSE']._serialized_start=5788 - _globals['_LISTLABELVIEWSRESPONSE']._serialized_end=5912 - _globals['_APPLYFEATURESERVICEREQUEST']._serialized_start=5914 - _globals['_APPLYFEATURESERVICEREQUEST']._serialized_end=6028 - _globals['_GETFEATURESERVICEREQUEST']._serialized_start=6030 - _globals['_GETFEATURESERVICEREQUEST']._serialized_end=6108 - _globals['_LISTFEATURESERVICESREQUEST']._serialized_start=6111 - _globals['_LISTFEATURESERVICESREQUEST']._serialized_end=6414 + _globals['_LISTLABELVIEWSRESPONSE']._serialized_start=5839 + _globals['_LISTLABELVIEWSRESPONSE']._serialized_end=5963 + _globals['_APPLYFEATURESERVICEREQUEST']._serialized_start=5965 + _globals['_APPLYFEATURESERVICEREQUEST']._serialized_end=6079 + _globals['_GETFEATURESERVICEREQUEST']._serialized_start=6081 + _globals['_GETFEATURESERVICEREQUEST']._serialized_end=6159 + _globals['_LISTFEATURESERVICESREQUEST']._serialized_start=6162 + _globals['_LISTFEATURESERVICESREQUEST']._serialized_end=6465 _globals['_LISTFEATURESERVICESREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTFEATURESERVICESREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTFEATURESERVICESRESPONSE']._serialized_start=6417 - _globals['_LISTFEATURESERVICESRESPONSE']._serialized_end=6556 - _globals['_DELETEFEATURESERVICEREQUEST']._serialized_start=6558 - _globals['_DELETEFEATURESERVICEREQUEST']._serialized_end=6634 - _globals['_APPLYSAVEDDATASETREQUEST']._serialized_start=6636 - _globals['_APPLYSAVEDDATASETREQUEST']._serialized_end=6744 - _globals['_GETSAVEDDATASETREQUEST']._serialized_start=6746 - _globals['_GETSAVEDDATASETREQUEST']._serialized_end=6822 - _globals['_LISTSAVEDDATASETSREQUEST']._serialized_start=6825 - _globals['_LISTSAVEDDATASETSREQUEST']._serialized_end=7102 + _globals['_LISTFEATURESERVICESRESPONSE']._serialized_start=6468 + _globals['_LISTFEATURESERVICESRESPONSE']._serialized_end=6607 + _globals['_DELETEFEATURESERVICEREQUEST']._serialized_start=6609 + _globals['_DELETEFEATURESERVICEREQUEST']._serialized_end=6685 + _globals['_APPLYSAVEDDATASETREQUEST']._serialized_start=6687 + _globals['_APPLYSAVEDDATASETREQUEST']._serialized_end=6795 + _globals['_GETSAVEDDATASETREQUEST']._serialized_start=6797 + _globals['_GETSAVEDDATASETREQUEST']._serialized_end=6873 + _globals['_LISTSAVEDDATASETSREQUEST']._serialized_start=6876 + _globals['_LISTSAVEDDATASETSREQUEST']._serialized_end=7153 _globals['_LISTSAVEDDATASETSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTSAVEDDATASETSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_start=7105 - _globals['_LISTSAVEDDATASETSRESPONSE']._serialized_end=7238 - _globals['_DELETESAVEDDATASETREQUEST']._serialized_start=7240 - _globals['_DELETESAVEDDATASETREQUEST']._serialized_end=7314 - _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_start=7317 - _globals['_CREATEDATASETFROMRETRIEVALREQUEST']._serialized_end=7781 + _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['_CREATEDATASETFROMRETRIEVALREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_CREATEDATASETFROMRETRIEVALREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_start=7783 - _globals['_CREATEDATASETFROMRETRIEVALRESPONSE']._serialized_end=7851 - _globals['_GETDATASETDATAREQUEST']._serialized_start=7853 - _globals['_GETDATASETDATAREQUEST']._serialized_end=7922 - _globals['_TABULARROW']._serialized_start=7924 - _globals['_TABULARROW']._serialized_end=7952 - _globals['_GETDATASETDATARESPONSE']._serialized_start=7954 - _globals['_GETDATASETDATARESPONSE']._serialized_end=8078 - _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_start=8080 - _globals['_GETDATASETJOBSTATUSREQUEST']._serialized_end=8124 - _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_start=8127 - _globals['_GETDATASETJOBSTATUSRESPONSE']._serialized_end=8284 - _globals['_LISTDATASETJOBSREQUEST']._serialized_start=8286 - _globals['_LISTDATASETJOBSREQUEST']._serialized_end=8350 - _globals['_LISTDATASETJOBSRESPONSE']._serialized_start=8352 - _globals['_LISTDATASETJOBSRESPONSE']._serialized_end=8436 - _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_start=8439 - _globals['_APPLYVALIDATIONREFERENCEREQUEST']._serialized_end=8568 - _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_start=8570 - _globals['_GETVALIDATIONREFERENCEREQUEST']._serialized_end=8653 - _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_start=8656 - _globals['_LISTVALIDATIONREFERENCESREQUEST']._serialized_end=8947 + _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['_LISTVALIDATIONREFERENCESREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTVALIDATIONREFERENCESREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_start=8950 - _globals['_LISTVALIDATIONREFERENCESRESPONSE']._serialized_end=9104 - _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_start=9106 - _globals['_DELETEVALIDATIONREFERENCEREQUEST']._serialized_end=9187 - _globals['_APPLYPERMISSIONREQUEST']._serialized_start=9189 - _globals['_APPLYPERMISSIONREQUEST']._serialized_end=9290 - _globals['_GETPERMISSIONREQUEST']._serialized_start=9292 - _globals['_GETPERMISSIONREQUEST']._serialized_end=9366 - _globals['_LISTPERMISSIONSREQUEST']._serialized_start=9369 - _globals['_LISTPERMISSIONSREQUEST']._serialized_end=9642 + _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['_LISTPERMISSIONSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTPERMISSIONSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTPERMISSIONSRESPONSE']._serialized_start=9644 - _globals['_LISTPERMISSIONSRESPONSE']._serialized_end=9770 - _globals['_DELETEPERMISSIONREQUEST']._serialized_start=9772 - _globals['_DELETEPERMISSIONREQUEST']._serialized_end=9844 - _globals['_APPLYPROJECTREQUEST']._serialized_start=9846 - _globals['_APPLYPROJECTREQUEST']._serialized_end=9921 - _globals['_GETPROJECTREQUEST']._serialized_start=9923 - _globals['_GETPROJECTREQUEST']._serialized_end=9977 - _globals['_LISTPROJECTSREQUEST']._serialized_start=9980 - _globals['_LISTPROJECTSREQUEST']._serialized_end=10230 + _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['_LISTPROJECTSREQUEST_TAGSENTRY']._serialized_start=1681 _globals['_LISTPROJECTSREQUEST_TAGSENTRY']._serialized_end=1724 - _globals['_LISTPROJECTSRESPONSE']._serialized_start=10232 - _globals['_LISTPROJECTSRESPONSE']._serialized_end=10349 - _globals['_DELETEPROJECTREQUEST']._serialized_start=10351 - _globals['_DELETEPROJECTREQUEST']._serialized_end=10403 - _globals['_ENTITYREFERENCE']._serialized_start=10405 - _globals['_ENTITYREFERENCE']._serialized_end=10450 - _globals['_ENTITYRELATION']._serialized_start=10452 - _globals['_ENTITYRELATION']._serialized_end=10566 - _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_start=10569 - _globals['_GETREGISTRYLINEAGEREQUEST']._serialized_end=10792 - _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_start=10795 - _globals['_GETREGISTRYLINEAGERESPONSE']._serialized_end=11091 - _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_start=11094 - _globals['_GETOBJECTRELATIONSHIPSREQUEST']._serialized_end=11333 - _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_start=11336 - _globals['_GETOBJECTRELATIONSHIPSRESPONSE']._serialized_end=11479 - _globals['_FEATURE']._serialized_start=11482 - _globals['_FEATURE']._serialized_end=11800 + _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['_FEATURE_TAGSENTRY']._serialized_start=1681 _globals['_FEATURE_TAGSENTRY']._serialized_end=1724 - _globals['_LISTFEATURESREQUEST']._serialized_start=11803 - _globals['_LISTFEATURESREQUEST']._serialized_end=12014 - _globals['_LISTFEATURESRESPONSE']._serialized_start=12016 - _globals['_LISTFEATURESRESPONSE']._serialized_end=12137 - _globals['_GETFEATUREREQUEST']._serialized_start=12139 - _globals['_GETFEATUREREQUEST']._serialized_end=12232 - _globals['_REGISTRYSERVER']._serialized_start=12235 - _globals['_REGISTRYSERVER']._serialized_end=17437 + _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 # @@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 31406fe97b0..9171c75a5be 100644 --- a/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi +++ b/sdk/python/feast/protos/feast/registry/RegistryServer_pb2.pyi @@ -704,6 +704,7 @@ class ListAllFeatureViewsRequest(google.protobuf.message.Message): DATA_SOURCE_FIELD_NUMBER: builtins.int PAGINATION_FIELD_NUMBER: builtins.int SORTING_FIELD_NUMBER: builtins.int + UPDATED_SINCE_FIELD_NUMBER: builtins.int project: builtins.str allow_cache: builtins.bool @property @@ -716,6 +717,8 @@ class ListAllFeatureViewsRequest(google.protobuf.message.Message): def pagination(self) -> global___PaginationParams: ... @property def sorting(self) -> global___SortingParams: ... + @property + def updated_since(self) -> google.protobuf.timestamp_pb2.Timestamp: ... def __init__( self, *, @@ -728,9 +731,10 @@ class ListAllFeatureViewsRequest(google.protobuf.message.Message): data_source: builtins.str = ..., pagination: global___PaginationParams | None = ..., sorting: global___SortingParams | None = ..., + updated_since: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> 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", "data_source", b"data_source", "entity", b"entity", "feature", b"feature", "feature_service", b"feature_service", "pagination", b"pagination", "project", b"project", "sorting", b"sorting", "tags", b"tags"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["pagination", b"pagination", "sorting", b"sorting", "updated_since", b"updated_since"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["allow_cache", b"allow_cache", "data_source", b"data_source", "entity", b"entity", "feature", b"feature", "feature_service", b"feature_service", "pagination", b"pagination", "project", b"project", "sorting", b"sorting", "tags", b"tags", "updated_since", b"updated_since"]) -> None: ... global___ListAllFeatureViewsRequest = ListAllFeatureViewsRequest diff --git a/sdk/python/feast/registry_server.py b/sdk/python/feast/registry_server.py index 24b446a4bdd..4cdef30c309 100644 --- a/sdk/python/feast/registry_server.py +++ b/sdk/python/feast/registry_server.py @@ -539,6 +539,12 @@ def ListAllFeatureViews( ): from feast.labeling.label_view import LabelView + updated_since = None + if request.HasField("updated_since"): + updated_since = request.updated_since.ToDatetime().replace( + tzinfo=timezone.utc + ) + all_feature_views = cast( list[FeastObject], [ @@ -548,6 +554,7 @@ def ListAllFeatureViews( allow_cache=request.allow_cache, tags=dict(request.tags), skip_udf=True, + updated_since=updated_since, ) if not isinstance(fv, LabelView) ], diff --git a/sdk/python/tests/integration/registration/test_universal_registry.py b/sdk/python/tests/integration/registration/test_universal_registry.py index 735d714a1f3..ea313e9498c 100644 --- a/sdk/python/tests/integration/registration/test_universal_registry.py +++ b/sdk/python/tests/integration/registration/test_universal_registry.py @@ -16,7 +16,7 @@ import random import string import time -from datetime import timedelta, timezone +from datetime import datetime, timedelta, timezone from tempfile import mkstemp from unittest import mock @@ -825,6 +825,65 @@ def location_features_from_push(inputs: pd.DataFrame) -> pd.DataFrame: test_registry.teardown() +@pytest.mark.integration +@pytest.mark.parametrize( + "test_registry", + [ + lazy_fixture("local_registry"), + lazy_fixture("sqlite_registry"), + pytest.param( + lazy_fixture("mock_remote_registry"), + marks=pytest.mark.rbac_remote_integration_test, + ), + ], +) +def test_list_all_feature_views_updated_since(test_registry: BaseRegistry): + """Test that list_all_feature_views correctly filters by updated_since.""" + batch_source = FileSource( + file_format=ParquetFormat(), + path="file://feast/*", + timestamp_field="ts_col", + created_timestamp_column="timestamp", + ) + entity = Entity(name="fs1_driver_1", join_keys=["test"]) + fv1 = FeatureView( + name="test_fv_updated_since_1", + schema=[Field(name="test", dtype=Int64)], + entities=[entity], + source=batch_source, + ttl=timedelta(minutes=5), + ) + fv2 = FeatureView( + name="test_fv_updated_since_2", + schema=[Field(name="test", dtype=Int64)], + entities=[entity], + source=batch_source, + ttl=timedelta(minutes=5), + ) + project = "project" + test_registry.apply_entity(entity, project) + test_registry.apply_feature_view(fv1, project) + test_registry.apply_feature_view(fv2, project) + + # A cutoff in the past should return all feature views + past = datetime(2000, 1, 1, tzinfo=timezone.utc) + result = test_registry.list_all_feature_views(project, updated_since=past) + assert len(result) == 2 + + # A cutoff in the future should return nothing + future = datetime(2999, 1, 1, tzinfo=timezone.utc) + result = test_registry.list_all_feature_views(project, updated_since=future) + assert len(result) == 0 + + # No filter returns all feature views + result = test_registry.list_all_feature_views(project) + assert len(result) == 2 + + test_registry.delete_feature_view("test_fv_updated_since_1", project) + test_registry.delete_feature_view("test_fv_updated_since_2", project) + test_registry.teardown() + + @pytest.mark.integration @pytest.mark.parametrize( "test_registry", diff --git a/sdk/python/tests/unit/api/test_api_rest_registry.py b/sdk/python/tests/unit/api/test_api_rest_registry.py index b87f0476e15..bc1aedd1c7c 100644 --- a/sdk/python/tests/unit/api/test_api_rest_registry.py +++ b/sdk/python/tests/unit/api/test_api_rest_registry.py @@ -337,6 +337,34 @@ def test_feature_views_comprehensive_filtering_via_rest(fastapi_test_app): assert len(data["featureViews"]) == 0 +def test_feature_views_updated_since_via_rest(fastapi_test_app): + """Test that feature views can be filtered by updated_since timestamp.""" + # A timestamp in the past should return all feature views + response = fastapi_test_app.get( + "/feature_views?project=demo_project&updated_since=2000-01-01T00:00:00Z" + ) + assert response.status_code == 200 + data = response.json() + assert "featureViews" in data + all_count = len(data["featureViews"]) + assert all_count > 0 + + # A timestamp far in the future should return no feature views + response = fastapi_test_app.get( + "/feature_views?project=demo_project&updated_since=2999-01-01T00:00:00Z" + ) + assert response.status_code == 200 + data = response.json() + assert "featureViews" in data + assert len(data["featureViews"]) == 0 + + # Without updated_since returns the same count as the past-timestamp query + response = fastapi_test_app.get("/feature_views?project=demo_project") + assert response.status_code == 200 + data = response.json() + assert len(data["featureViews"]) == all_count + + def test_feature_services_via_rest(fastapi_test_app): response = fastapi_test_app.get("/feature_services?project=demo_project") assert response.status_code == 200 diff --git a/sdk/python/tests/unit/infra/registry/test_remote_registry.py b/sdk/python/tests/unit/infra/registry/test_remote_registry.py new file mode 100644 index 00000000000..d6b9bbc7fa0 --- /dev/null +++ b/sdk/python/tests/unit/infra/registry/test_remote_registry.py @@ -0,0 +1,85 @@ +# Copyright 2024 The Feast Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from datetime import datetime, timedelta, timezone +from unittest.mock import MagicMock, patch + +import pytest +from google.protobuf.timestamp_pb2 import Timestamp + +from feast.infra.registry.remote import RemoteRegistry +from feast.protos.feast.registry import RegistryServer_pb2 + + +@pytest.fixture +def remote_registry(): + with patch.object(RemoteRegistry, "__init__", return_value=None): + registry = RemoteRegistry.__new__(RemoteRegistry) + registry.stub = MagicMock() + registry.stub.ListAllFeatureViews.return_value = ( + RegistryServer_pb2.ListAllFeatureViewsResponse(feature_views=[]) + ) + yield registry + + +def _captured_updated_since(remote_registry) -> Timestamp: + """Return the updated_since Timestamp from the last ListAllFeatureViews call.""" + call_args = remote_registry.stub.ListAllFeatureViews.call_args + request: RegistryServer_pb2.ListAllFeatureViewsRequest = call_args[0][0] + return request.updated_since + + +def test_updated_since_utc_aware(remote_registry): + """A UTC-aware datetime is encoded to the correct UTC epoch seconds.""" + dt = datetime(2024, 6, 1, 17, 0, 0, tzinfo=timezone.utc) + remote_registry.list_all_feature_views("project", updated_since=dt) + + ts = _captured_updated_since(remote_registry) + assert ts.seconds == int(dt.timestamp()) + + +def test_updated_since_non_utc_aware(remote_registry): + """A non-UTC tz-aware datetime is converted to the correct UTC epoch, not treated as UTC.""" + est = timezone(timedelta(hours=-5)) + # 2024-06-01 12:00 EST == 2024-06-01 17:00 UTC + dt_est = datetime(2024, 6, 1, 12, 0, 0, tzinfo=est) + dt_utc = datetime(2024, 6, 1, 17, 0, 0, tzinfo=timezone.utc) + + remote_registry.list_all_feature_views("project", updated_since=dt_est) + + ts = _captured_updated_since(remote_registry) + assert ts.seconds == int(dt_utc.timestamp()), ( + "Non-UTC datetime must be converted to UTC before encoding, " + "not have its tzinfo stripped (which would misinterpret 12:00 EST as 12:00 UTC)" + ) + + +def test_updated_since_naive_datetime(remote_registry): + """A naive datetime is treated as UTC by protobuf's FromDatetime.""" + dt_naive = datetime(2024, 6, 1, 17, 0, 0) + dt_utc = datetime(2024, 6, 1, 17, 0, 0, tzinfo=timezone.utc) + remote_registry.list_all_feature_views("project", updated_since=dt_naive) + + ts = _captured_updated_since(remote_registry) + assert ts.seconds == int(dt_utc.timestamp()) + + +def test_updated_since_none(remote_registry): + """When updated_since is None, the field is not set in the request.""" + remote_registry.list_all_feature_views("project", updated_since=None) + + request: RegistryServer_pb2.ListAllFeatureViewsRequest = ( + remote_registry.stub.ListAllFeatureViews.call_args[0][0] + ) + assert not request.HasField("updated_since") diff --git a/sdk/python/tests/unit/infra/registry/test_snowflake_registry.py b/sdk/python/tests/unit/infra/registry/test_snowflake_registry.py index f1935f329b0..59ab2b87c03 100644 --- a/sdk/python/tests/unit/infra/registry/test_snowflake_registry.py +++ b/sdk/python/tests/unit/infra/registry/test_snowflake_registry.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +from datetime import datetime, timedelta, timezone from unittest.mock import MagicMock, patch import pandas as pd import pytest +from feast import FeatureView, Field from feast.entity import Entity +from feast.infra.offline_stores.file_source import FileSource from feast.infra.registry.snowflake import SnowflakeRegistry, SnowflakeRegistryConfig from feast.infra.utils.snowflake.snowflake_utils import GetSnowflakeConnection +from feast.types import Float32 @pytest.fixture @@ -328,3 +332,127 @@ def test_private_key_kwargs_not_leaked_to_connect( assert "private_key_passphrase" not in connect_kwargs assert "private_key_content" not in connect_kwargs assert connect_kwargs["private_key"] == b"parsed_key_bytes" + + +def _make_feature_view(name: str, entity: Entity, source: FileSource) -> FeatureView: + return FeatureView( + name=name, + entities=[entity], + ttl=timedelta(days=1), + schema=[Field(name="conv_rate", dtype=Float32)], + source=source, + ) + + +@pytest.fixture +def mock_snowflake_registry(): + """Return a SnowflakeRegistry whose Snowflake connection is fully mocked.""" + config = MagicMock() + config.path = "snowflake://account/db/schema" + config.registry_type = "snowflake" + config.cache_ttl_seconds = 0 + config.cache_mode = "sync" + + with patch( + "feast.infra.registry.snowflake.SnowflakeRegistry.__init__", + return_value=None, + ): + registry = SnowflakeRegistry.__new__(SnowflakeRegistry) + registry.registry_config = config + registry.registry_path = "db.schema" + registry.cache_mode = "sync" + # list_all_feature_views also aggregates label views; default to none so the + # updated_since tests only need to stub the feature-view list methods they exercise. + registry.list_label_views = MagicMock(return_value=[]) + yield registry + + +def _make_mock_fv(name: str, updated_at: datetime) -> MagicMock: + fv = MagicMock() + fv.name = name + # Snowflake stores timestamps as offset-naive UTC after round-tripping through proto + fv.last_updated_timestamp = updated_at.replace(tzinfo=None) + fv.tags = {} + return fv + + +def test_list_all_feature_views_updated_since_no_cache(mock_snowflake_registry): + """updated_since filters Python-side when allow_cache=False.""" + old_ts = datetime(2020, 1, 1, tzinfo=timezone.utc) + new_ts = datetime(2024, 6, 1, tzinfo=timezone.utc) + + old_fv = _make_mock_fv("old_view", old_ts) + new_fv = _make_mock_fv("new_view", new_ts) + + mock_snowflake_registry.list_feature_views = MagicMock( + return_value=[old_fv, new_fv] + ) + mock_snowflake_registry.list_stream_feature_views = MagicMock(return_value=[]) + mock_snowflake_registry.list_on_demand_feature_views = MagicMock(return_value=[]) + + cutoff = datetime(2023, 1, 1, tzinfo=timezone.utc) + result = mock_snowflake_registry.list_all_feature_views( + "project", allow_cache=False, updated_since=cutoff + ) + assert [fv.name for fv in result] == ["new_view"] + + +def test_list_all_feature_views_updated_since_no_filter(mock_snowflake_registry): + """Without updated_since, all feature views are returned.""" + ts = datetime(2020, 1, 1, tzinfo=timezone.utc) + fv1 = _make_mock_fv("view_a", ts) + fv2 = _make_mock_fv("view_b", ts) + + mock_snowflake_registry.list_feature_views = MagicMock(return_value=[fv1, fv2]) + mock_snowflake_registry.list_stream_feature_views = MagicMock(return_value=[]) + mock_snowflake_registry.list_on_demand_feature_views = MagicMock(return_value=[]) + + result = mock_snowflake_registry.list_all_feature_views( + "project", allow_cache=False + ) + assert len(result) == 2 + + +def test_list_all_feature_views_updated_since_future_returns_empty( + mock_snowflake_registry, +): + """A future cutoff returns no feature views.""" + ts = datetime(2024, 1, 1, tzinfo=timezone.utc) + fv = _make_mock_fv("any_view", ts) + + mock_snowflake_registry.list_feature_views = MagicMock(return_value=[fv]) + mock_snowflake_registry.list_stream_feature_views = MagicMock(return_value=[]) + mock_snowflake_registry.list_on_demand_feature_views = MagicMock(return_value=[]) + + future = datetime(2999, 1, 1, tzinfo=timezone.utc) + result = mock_snowflake_registry.list_all_feature_views( + "project", allow_cache=False, updated_since=future + ) + assert result == [] + + +def test_list_all_feature_views_updated_since_non_utc_tz(mock_snowflake_registry): + """A non-UTC tz-aware cutoff is converted to UTC before comparing against naive-UTC timestamps.""" + est = timezone(timedelta(hours=-5)) + # 2023-01-01 00:00 EST == 2023-01-01 05:00 UTC + cutoff_est = datetime(2023, 1, 1, 0, 0, 0, tzinfo=est) + + # Feature view updated at 2023-01-01 03:00 UTC — after midnight EST but before 05:00 UTC + ts_between = datetime(2023, 1, 1, 3, 0, 0, tzinfo=timezone.utc) + # Feature view updated at 2023-01-01 06:00 UTC — after both midnight EST and 05:00 UTC + ts_after = datetime(2023, 1, 1, 6, 0, 0, tzinfo=timezone.utc) + + fv_between = _make_mock_fv("view_between", ts_between) + fv_after = _make_mock_fv("view_after", ts_after) + + mock_snowflake_registry.list_feature_views = MagicMock( + return_value=[fv_between, fv_after] + ) + mock_snowflake_registry.list_stream_feature_views = MagicMock(return_value=[]) + mock_snowflake_registry.list_on_demand_feature_views = MagicMock(return_value=[]) + + result = mock_snowflake_registry.list_all_feature_views( + "project", allow_cache=False, updated_since=cutoff_est + ) + # Only view_after is at or after 05:00 UTC; view_between (03:00 UTC) should be excluded + assert [fv.name for fv in result] == ["view_after"] diff --git a/sdk/python/tests/unit/infra/registry/test_sql_registry.py b/sdk/python/tests/unit/infra/registry/test_sql_registry.py index 1a3ec92a4a6..8d5bf976b51 100644 --- a/sdk/python/tests/unit/infra/registry/test_sql_registry.py +++ b/sdk/python/tests/unit/infra/registry/test_sql_registry.py @@ -15,7 +15,7 @@ import sys import tempfile import types -from datetime import timedelta +from datetime import datetime, timedelta, timezone import dill import pytest @@ -220,3 +220,106 @@ def test_shared_registry_cross_project_udf_does_not_crash(shared_sqlite_db_path) assert "driver_features" in fv_names registry_a.teardown() + + +def test_list_all_feature_views_updated_since(sqlite_registry): + """Test that _list_all_feature_views filters by updated_since at the SQL level.""" + entity = Entity( + name="driver", + value_type=ValueType.STRING, + join_keys=["driver_id"], + ) + sqlite_registry.apply_entity(entity, "test_project") + + file_source = FileSource( + path="driver_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) + + fv1 = _build_feature_view("driver_activity_1", entity, file_source) + fv2 = _build_feature_view("driver_activity_2", entity, file_source) + sqlite_registry.apply_feature_view(fv1, "test_project") + sqlite_registry.apply_feature_view(fv2, "test_project") + + # Filtering with a past timestamp returns all feature views + past = datetime(2000, 1, 1, tzinfo=timezone.utc) + result = sqlite_registry.list_all_feature_views("test_project", updated_since=past) + assert len(result) == 2 + + # Filtering with a future timestamp returns nothing + future = datetime(2999, 1, 1, tzinfo=timezone.utc) + result = sqlite_registry.list_all_feature_views( + "test_project", updated_since=future + ) + assert len(result) == 0 + + # No filter returns all feature views + result = sqlite_registry.list_all_feature_views("test_project") + assert len(result) == 2 + + +def test_list_feature_views_updated_since(sqlite_registry): + """Test that _list_feature_views respects updated_since via SQL WHERE clause.""" + entity = Entity( + name="rider", + value_type=ValueType.STRING, + join_keys=["rider_id"], + ) + sqlite_registry.apply_entity(entity, "test_project") + + file_source = FileSource( + path="rider_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) + + fv = _build_feature_view("rider_activity", entity, file_source) + sqlite_registry.apply_feature_view(fv, "test_project") + + # A cutoff just before the feature view was applied returns it + before = datetime.now(tz=timezone.utc) - timedelta(seconds=60) + result = sqlite_registry._list_feature_views( + "test_project", tags=None, updated_since=before + ) + assert any(fv.name == "rider_activity" for fv in result) + + # A cutoff in the future returns nothing + future = datetime(2999, 1, 1, tzinfo=timezone.utc) + result = sqlite_registry._list_feature_views( + "test_project", tags=None, updated_since=future + ) + assert len(result) == 0 + + +def test_list_feature_views_updated_since_naive_treated_as_utc(sqlite_registry): + """A naive updated_since is treated as UTC, not local time, in the SQL filter.""" + entity = Entity( + name="courier", + value_type=ValueType.STRING, + join_keys=["courier_id"], + ) + sqlite_registry.apply_entity(entity, "test_project") + + file_source = FileSource( + path="courier_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) + + fv = _build_feature_view("courier_activity", entity, file_source) + sqlite_registry.apply_feature_view(fv, "test_project") + + # A naive past cutoff (interpreted as UTC) should return the feature view + past_naive = datetime(2000, 1, 1) + result = sqlite_registry._list_feature_views( + "test_project", tags=None, updated_since=past_naive + ) + assert any(fv.name == "courier_activity" for fv in result) + + # The equivalent UTC-aware cutoff must produce the same result + past_aware = datetime(2000, 1, 1, tzinfo=timezone.utc) + result_aware = sqlite_registry._list_feature_views( + "test_project", tags=None, updated_since=past_aware + ) + assert len(result) == len(result_aware)