From 492e682bb6e1626a67c01bf2ba351832090303ce Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 11:05:38 +0800 Subject: [PATCH 01/23] Added project field to ServingService proto's GetOnlineFeaturesResponse to specify project override --- protos/feast/serving/ServingService.proto | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/protos/feast/serving/ServingService.proto b/protos/feast/serving/ServingService.proto index f11cd124f96..4a37df2c94a 100644 --- a/protos/feast/serving/ServingService.proto +++ b/protos/feast/serving/ServingService.proto @@ -91,6 +91,11 @@ message GetOnlineFeaturesRequest { // values will be returned. bool omit_entities_in_response = 3; + // Optional field to specify project name override. If specified, uses the + // given project for retrieval. Overrides the projects specified in + // Feature References if both are specified. + string project = 5; + message EntityRow { // Request timestamp of this row. This value will be used, // together with maxAge, to determine feature staleness. From 6e2c2967b45f85faf23677d1aa0550b413165f87 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 12:24:54 +0800 Subject: [PATCH 02/23] Update Serving's OnlineServingService to apply project override when specified --- .../java/com/gojek/feast/FeastClient.java | 4 +- .../serving/service/OnlineServingService.java | 43 +++++++--- .../service/OnlineServingServiceTest.java | 83 ++++++++++++++++++- .../api/retriever/FeatureSetRequest.java | 7 -- 4 files changed, 115 insertions(+), 22 deletions(-) diff --git a/sdk/java/src/main/java/com/gojek/feast/FeastClient.java b/sdk/java/src/main/java/com/gojek/feast/FeastClient.java index a7f24e5282b..9ac91616847 100644 --- a/sdk/java/src/main/java/com/gojek/feast/FeastClient.java +++ b/sdk/java/src/main/java/com/gojek/feast/FeastClient.java @@ -110,8 +110,8 @@ public List getOnlineFeatures(List featureRefs, List rows, Str * featureSet:feature, where 'featureSet' and 'feature' refer to the FeatureSet and Feature * names respectively. Only the Feature name is required. * @param rows list of {@link Row} to select the entities to retrieve the features for - * @param project {@link String} Specifies the project which contains the FeatureSets which the - * Feature requested belong to. + * @param project {@link String} Specifies the project override. If specifed uses the project for + * retrieval. Overrides the projects set in Feature References if also specified. * @param omitEntitiesInResponse if true, the returned {@link Row} will not contain field and * value for the entity * @return list of {@link Row} containing retrieved data fields. diff --git a/serving/src/main/java/feast/serving/service/OnlineServingService.java b/serving/src/main/java/feast/serving/service/OnlineServingService.java index 861cd99dd3b..b14faa334bc 100644 --- a/serving/src/main/java/feast/serving/service/OnlineServingService.java +++ b/serving/src/main/java/feast/serving/service/OnlineServingService.java @@ -87,9 +87,8 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ }); } - List featureSetRequests = - specService.getFeatureSets(request.getFeaturesList()); - for (FeatureSetRequest featureSetRequest : featureSetRequests) { + List featureSetRequests = getFeatureSetRequests(request); + for (FeatureSetRequest featureSetRequest : getFeatureSetRequests(request)) { // Pull feature rows for given entity rows from the feature/featureset specified in feature // set request. // from the configured online @@ -113,7 +112,7 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ boolean isOutsideMaxAge = checkOutsideMaxAge(featureSetRequest, entityRow, featureRow); Map valueMap = - unpackValueMap(featureRow, featureSetRequest, isOutsideMaxAge); + unpackValueMap(featureRow, request, isOutsideMaxAge); entityValuesMap.get(entityRow).putAll(valueMap); // Generate metadata for feature values and merge into entityFieldsMap @@ -148,24 +147,48 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ } } + /** + * Compile {@link FeatureSetRequest}s from the given {@link GetOnlineFeaturesRequest}. Applies + * project override if specified and queries spec service to map features requested into feature + * set requests. + * + * @param request supplied by the client. + * @return list of{@link FeatureSetRequest}s compiled from the given online feature request. + */ + private List getFeatureSetRequests(GetOnlineFeaturesRequest request) { + List featureReferences = + request.getFeaturesList().stream() + .map( + featureRef -> { + if (!request.getProject().isEmpty()) { + return featureRef.toBuilder().setProject(request.getProject()).build(); + } + return featureRef; + }) + .collect(Collectors.toList()); + + return specService.getFeatureSets(featureReferences); + } + /** * Unpack feature values using data from the given feature row for features specified in the given - * feature set request. + * online feature request. * * @param featureRow optional to unpack for feature values. - * @param featureSetRequest for which the feature row was retrieved. + * @param request online feature request for which the feature row was retrieved. * @param isOutsideMaxAge whether which the feature row contains values that is outside max age. * @return valueMap mapping string feature name to feature value for the given feature set * request. */ private static Map unpackValueMap( - Optional featureRow, - FeatureSetRequest featureSetRequest, - boolean isOutsideMaxAge) { + Optional featureRow, GetOnlineFeaturesRequest request, boolean isOutsideMaxAge) { Map valueMap = new HashMap<>(); // In order to return values containing the same feature references provided by the user, // we reuse the feature references in the request as the keys in field builder map - Map nameRefMap = featureSetRequest.getFeatureRefsByName(); + Map nameRefMap = + request.getFeaturesList().stream() + .collect( + Collectors.toMap(FeatureReference::getName, featureReference -> featureReference)); if (featureRow.isPresent()) { // unpack feature row's feature values and populate value map Map featureValueMap = diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java index 9ab892a0c44..014a93099f1 100644 --- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java +++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java @@ -43,6 +43,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatchers; @@ -302,9 +303,8 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfMaxAgeIsExceeded() { .setFeatureSet("project/featureSet") .build()), Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp( - Timestamp.newBuilder().setSeconds(50)) // this value should be nulled + FeatureRow.newBuilder() // this feature row should have its values nulled + .setEventTimestamp(Timestamp.newBuilder().setSeconds(50)) .addAllFields( Lists.newArrayList( FieldProto.Field.newBuilder() @@ -474,6 +474,83 @@ public void shouldFilterOutUndesiredRows() { assertThat(actual, equalTo(expected)); } + @Test + public void shouldApplyProjectOverrideInRequest() { + GetOnlineFeaturesRequest request = + GetOnlineFeaturesRequest.newBuilder() + .setOmitEntitiesInResponse(false) + .setProject("project") + .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) + .addFeatures( + FeatureReference.newBuilder().setName("feature2").setProject("project").build()) + .addEntityRows( + EntityRow.newBuilder() + .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) + .putFields("entity1", intValue(1)) + .putFields("entity2", strValue("a"))) + .build(); + + List> featureRows = + Lists.newArrayList( + Optional.of( + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder() + .setName("entity1") + .setValue(intValue(1)) + .build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("a")) + .build(), + FieldProto.Field.newBuilder() + .setName("feature1") + .setValue(intValue(1)) + .build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(1)) + .build())) + .setFeatureSet("default/featureSet") + .build())); + + List projectOverrideFeatureReferences = + request.getFeaturesList().stream() + .map(featureRef -> featureRef.toBuilder().setProject("project").build()) + .collect(Collectors.toList()); + + FeatureSetRequest featureSetRequest = + FeatureSetRequest.newBuilder() + .addAllFeatureReferences(projectOverrideFeatureReferences) + .setSpec(getFeatureSetSpec()) + .build(); + + when(specService.getFeatureSets(projectOverrideFeatureReferences)) + .thenReturn(Collections.singletonList(featureSetRequest)); + when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) + .thenReturn(featureRows); + when(tracer.buildSpan(ArgumentMatchers.any())).thenReturn(Mockito.mock(SpanBuilder.class)); + + GetOnlineFeaturesResponse expected = + GetOnlineFeaturesResponse.newBuilder() + .addFieldValues( + FieldValues.newBuilder() + .putFields("entity1", intValue(1)) + .putStatuses("entity1", FieldStatus.PRESENT) + .putFields("entity2", strValue("a")) + .putStatuses("entity2", FieldStatus.PRESENT) + .putFields("feature1", intValue(1)) + .putStatuses("feature1", FieldStatus.PRESENT) + .putFields("project/feature2", intValue(1)) + .putStatuses("project/feature2", FieldStatus.PRESENT) + .build()) + .build(); + GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request); + assertThat(actual, equalTo(expected)); + } + private Value intValue(int val) { return Value.newBuilder().setInt32Val(val).build(); } diff --git a/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java b/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java index 3482529a97d..869d0027b5a 100644 --- a/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java +++ b/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java @@ -21,8 +21,6 @@ import feast.proto.core.FeatureSetProto.FeatureSetSpec; import feast.proto.serving.ServingAPIProto.FeatureReference; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; @AutoValue public abstract class FeatureSetRequest { @@ -52,9 +50,4 @@ public Builder addFeatureReference(FeatureReference featureReference) { public abstract FeatureSetRequest build(); } - - public Map getFeatureRefsByName() { - return getFeatureReferences().stream() - .collect(Collectors.toMap(FeatureReference::getName, featureReference -> featureReference)); - } } From 894ce17f0c33e57deb15be56006d82ea20c7416f Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 12:35:35 +0800 Subject: [PATCH 03/23] Updated Python SDK use project field and remove strip project code --- sdk/python/feast/client.py | 36 ++++----------------------------- sdk/python/feast/feature.py | 7 +------ sdk/python/tests/test_client.py | 24 ++++++++++------------ 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/sdk/python/feast/client.py b/sdk/python/feast/client.py index f4c822e018a..8e840b3cb87 100644 --- a/sdk/python/feast/client.py +++ b/sdk/python/feast/client.py @@ -671,10 +671,9 @@ def get_online_features( entity_rows: List of GetFeaturesRequest.EntityRow where each row contains entities. Timestamp should not be set for online retrieval. All entity types within a feature - project: Specifies the project which contain the FeatureSets - which the requested features belong to. + project: Optionally specify the the project override. If specified, uses given project for retrieval. + Overrides the projects specified in Feature References if also are specified. omit_entities: If true will omit entity values in the returned feature data. - Returns: GetOnlineFeaturesResponse containing the feature data in records. Each EntityRow provided will yield one record, which contains @@ -685,42 +684,15 @@ def get_online_features( response = self._serving_service.GetOnlineFeatures( GetOnlineFeaturesRequest( omit_entities_in_response=omit_entities, - features=_build_feature_references( - feature_ref_strs=feature_refs, - project=project if project is not None else self.project, - ), + features=_build_feature_references(feature_ref_strs=feature_refs,), entity_rows=entity_rows, + project=project if project is not None else self.project, ) ) entity_refs = { key for entity_row in entity_rows for key in entity_row.fields.keys() } - # strip the project part the string feature references returned from serving - strip = ( - lambda ref: repr(FeatureRef.from_str(ref, ignore_project=True)) - if ref not in entity_refs - else ref - ) - strip_field_values = [] - for field_value in response.field_values: - keys, fields, statuses = ( - field_value.fields.keys(), - field_value.fields, - field_value.statuses, - ) - fields_and_statuses = [ - (strip(key), fields[key], statuses[key]) for key in keys - ] - keys, fields, statuses = zip(*fields_and_statuses) - strip_field_values.append( - GetOnlineFeaturesResponse.FieldValues( - fields=dict(zip(keys, fields)), - statuses=dict(zip(keys, statuses)), - ) - ) - del response.field_values[:] - response.field_values.extend(strip_field_values) except grpc.RpcError as e: raise grpc.RpcError(e.details()) diff --git a/sdk/python/feast/feature.py b/sdk/python/feast/feature.py index 054bf5ecc58..67d309d0f16 100644 --- a/sdk/python/feast/feature.py +++ b/sdk/python/feast/feature.py @@ -97,18 +97,13 @@ def from_str(cls, feature_ref_str: str, ignore_project: bool = False): Args: feature_ref_str: String representation of the feature reference - ignore_project: Ignore projects in given string feature reference - instead throwing an error Returns: FeatureRef that refers to the given feature """ proto = FeatureRefProto() if "/" in feature_ref_str: - if ignore_project: - _, feature_ref_str = feature_ref_str.split("/") - else: - raise ValueError(f"Unsupported feature reference: {feature_ref_str}") + raise ValueError(f"Unsupported feature reference: {feature_ref_str}") # parse feature set name if specified if ":" in feature_ref_str: diff --git a/sdk/python/tests/test_client.py b/sdk/python/tests/test_client.py index 720662acb62..75e43f32a38 100644 --- a/sdk/python/tests/test_client.py +++ b/sdk/python/tests/test_client.py @@ -263,7 +263,7 @@ def test_version(self, mocked_client, mocker): [pytest.lazy_fixture("mock_client"), pytest.lazy_fixture("secure_mock_client")], ) def test_get_online_features(self, mocked_client, mocker): - ROW_COUNT = 300 + ROW_COUNT = 1 mocked_client._serving_service_stub = Serving.ServingServiceStub( grpc.insecure_channel("") @@ -272,14 +272,12 @@ def test_get_online_features(self, mocked_client, mocker): def int_val(x): return ValueProto.Value(int64_val=x) - request = GetOnlineFeaturesRequest() + request = GetOnlineFeaturesRequest(project="driver_project") request.features.extend( [ - FeatureRefProto( - project="driver_project", feature_set="driver", name="age" - ), - FeatureRefProto(project="driver_project", name="rating"), - FeatureRefProto(project="driver_project", name="null_value"), + FeatureRefProto(feature_set="driver", name="age"), + FeatureRefProto(name="rating"), + FeatureRefProto(name="null_value"), ] ) recieve_response = GetOnlineFeaturesResponse() @@ -292,15 +290,15 @@ def int_val(x): field_values = GetOnlineFeaturesResponse.FieldValues( fields={ "driver_id": int_val(row_number), - "driver_project/driver:age": int_val(1), - "driver_project/rating": int_val(9), - "driver_project/null_value": ValueProto.Value(), + "driver:age": int_val(1), + "rating": int_val(9), + "null_value": ValueProto.Value(), }, statuses={ "driver_id": GetOnlineFeaturesResponse.FieldStatus.PRESENT, - "driver_project/driver:age": GetOnlineFeaturesResponse.FieldStatus.PRESENT, - "driver_project/rating": GetOnlineFeaturesResponse.FieldStatus.PRESENT, - "driver_project/null_value": GetOnlineFeaturesResponse.FieldStatus.NULL_VALUE, + "driver:age": GetOnlineFeaturesResponse.FieldStatus.PRESENT, + "rating": GetOnlineFeaturesResponse.FieldStatus.PRESENT, + "null_value": GetOnlineFeaturesResponse.FieldStatus.NULL_VALUE, }, ) recieve_response.field_values.append(field_values) From 41779f31e843bc2318b46a395928a67b8e08540b Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 12:43:14 +0800 Subject: [PATCH 04/23] Recompile & update go protos based on current protobuf spec --- go.mod | 2 +- go.sum | 2 + sdk/go/protos/feast/core/CoreService.pb.go | 1092 +++++++++++------ sdk/go/protos/feast/core/FeatureSet.pb.go | 414 ++++--- sdk/go/protos/feast/core/IngestionJob.pb.go | 231 +++- sdk/go/protos/feast/core/Store.pb.go | 40 +- .../protos/feast/serving/ServingService.pb.go | 323 ++--- 7 files changed, 1337 insertions(+), 767 deletions(-) diff --git a/go.mod b/go.mod index f116fffa831..8f9d12581ad 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/net v0.0.0-20200513185701-a91f0712d120 golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 // indirect - golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8 // indirect + golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa // indirect google.golang.org/grpc v1.29.1 google.golang.org/protobuf v1.24.0 // indirect gopkg.in/russross/blackfriday.v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 4be66277bcf..50e81322e75 100644 --- a/go.sum +++ b/go.sum @@ -471,6 +471,8 @@ golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8 h1:8Xr1qwxn90MXYKftwNxIO2g4J+26naghxFS5rYiTZww= golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa h1:mMXQKlWCw9mIWgVLLfiycDZjMHMMYqiuakI4E/l2xcA= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/sdk/go/protos/feast/core/CoreService.pb.go b/sdk/go/protos/feast/core/CoreService.pb.go index a6d1dee6651..f0e35be844c 100644 --- a/sdk/go/protos/feast/core/CoreService.pb.go +++ b/sdk/go/protos/feast/core/CoreService.pb.go @@ -101,7 +101,7 @@ func (x ApplyFeatureSetResponse_Status) Number() protoreflect.EnumNumber { // Deprecated: Use ApplyFeatureSetResponse_Status.Descriptor instead. func (ApplyFeatureSetResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{7, 0} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{9, 0} } type UpdateStoreResponse_Status int32 @@ -149,7 +149,7 @@ func (x UpdateStoreResponse_Status) Number() protoreflect.EnumNumber { // Deprecated: Use UpdateStoreResponse_Status.Descriptor instead. func (UpdateStoreResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{11, 0} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{13, 0} } // Request for a single feature set @@ -353,6 +353,100 @@ func (x *ListFeatureSetsResponse) GetFeatureSets() []*FeatureSet { return nil } +type ListFeaturesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter *ListFeaturesRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` +} + +func (x *ListFeaturesRequest) Reset() { + *x = ListFeaturesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_feast_core_CoreService_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListFeaturesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFeaturesRequest) ProtoMessage() {} + +func (x *ListFeaturesRequest) ProtoReflect() protoreflect.Message { + mi := &file_feast_core_CoreService_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFeaturesRequest.ProtoReflect.Descriptor instead. +func (*ListFeaturesRequest) Descriptor() ([]byte, []int) { + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4} +} + +func (x *ListFeaturesRequest) GetFilter() *ListFeaturesRequest_Filter { + if x != nil { + return x.Filter + } + return nil +} + +type ListFeaturesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Features map[string]*FeatureSpec `protobuf:"bytes,1,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ListFeaturesResponse) Reset() { + *x = ListFeaturesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_feast_core_CoreService_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListFeaturesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFeaturesResponse) ProtoMessage() {} + +func (x *ListFeaturesResponse) ProtoReflect() protoreflect.Message { + mi := &file_feast_core_CoreService_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFeaturesResponse.ProtoReflect.Descriptor instead. +func (*ListFeaturesResponse) Descriptor() ([]byte, []int) { + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{5} +} + +func (x *ListFeaturesResponse) GetFeatures() map[string]*FeatureSpec { + if x != nil { + return x.Features + } + return nil +} + type ListStoresRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -364,7 +458,7 @@ type ListStoresRequest struct { func (x *ListStoresRequest) Reset() { *x = ListStoresRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[4] + mi := &file_feast_core_CoreService_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -377,7 +471,7 @@ func (x *ListStoresRequest) String() string { func (*ListStoresRequest) ProtoMessage() {} func (x *ListStoresRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[4] + mi := &file_feast_core_CoreService_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -390,7 +484,7 @@ func (x *ListStoresRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStoresRequest.ProtoReflect.Descriptor instead. func (*ListStoresRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{6} } func (x *ListStoresRequest) GetFilter() *ListStoresRequest_Filter { @@ -411,7 +505,7 @@ type ListStoresResponse struct { func (x *ListStoresResponse) Reset() { *x = ListStoresResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[5] + mi := &file_feast_core_CoreService_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -424,7 +518,7 @@ func (x *ListStoresResponse) String() string { func (*ListStoresResponse) ProtoMessage() {} func (x *ListStoresResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[5] + mi := &file_feast_core_CoreService_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -437,7 +531,7 @@ func (x *ListStoresResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStoresResponse.ProtoReflect.Descriptor instead. func (*ListStoresResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{5} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{7} } func (x *ListStoresResponse) GetStore() []*Store { @@ -461,7 +555,7 @@ type ApplyFeatureSetRequest struct { func (x *ApplyFeatureSetRequest) Reset() { *x = ApplyFeatureSetRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[6] + mi := &file_feast_core_CoreService_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -474,7 +568,7 @@ func (x *ApplyFeatureSetRequest) String() string { func (*ApplyFeatureSetRequest) ProtoMessage() {} func (x *ApplyFeatureSetRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[6] + mi := &file_feast_core_CoreService_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -487,7 +581,7 @@ func (x *ApplyFeatureSetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyFeatureSetRequest.ProtoReflect.Descriptor instead. func (*ApplyFeatureSetRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{6} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{8} } func (x *ApplyFeatureSetRequest) GetFeatureSet() *FeatureSet { @@ -509,7 +603,7 @@ type ApplyFeatureSetResponse struct { func (x *ApplyFeatureSetResponse) Reset() { *x = ApplyFeatureSetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[7] + mi := &file_feast_core_CoreService_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -522,7 +616,7 @@ func (x *ApplyFeatureSetResponse) String() string { func (*ApplyFeatureSetResponse) ProtoMessage() {} func (x *ApplyFeatureSetResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[7] + mi := &file_feast_core_CoreService_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -535,7 +629,7 @@ func (x *ApplyFeatureSetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyFeatureSetResponse.ProtoReflect.Descriptor instead. func (*ApplyFeatureSetResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{7} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{9} } func (x *ApplyFeatureSetResponse) GetFeatureSet() *FeatureSet { @@ -561,7 +655,7 @@ type GetFeastCoreVersionRequest struct { func (x *GetFeastCoreVersionRequest) Reset() { *x = GetFeastCoreVersionRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[8] + mi := &file_feast_core_CoreService_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -574,7 +668,7 @@ func (x *GetFeastCoreVersionRequest) String() string { func (*GetFeastCoreVersionRequest) ProtoMessage() {} func (x *GetFeastCoreVersionRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[8] + mi := &file_feast_core_CoreService_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -587,7 +681,7 @@ func (x *GetFeastCoreVersionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeastCoreVersionRequest.ProtoReflect.Descriptor instead. func (*GetFeastCoreVersionRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{8} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{10} } type GetFeastCoreVersionResponse struct { @@ -601,7 +695,7 @@ type GetFeastCoreVersionResponse struct { func (x *GetFeastCoreVersionResponse) Reset() { *x = GetFeastCoreVersionResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[9] + mi := &file_feast_core_CoreService_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -614,7 +708,7 @@ func (x *GetFeastCoreVersionResponse) String() string { func (*GetFeastCoreVersionResponse) ProtoMessage() {} func (x *GetFeastCoreVersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[9] + mi := &file_feast_core_CoreService_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -627,7 +721,7 @@ func (x *GetFeastCoreVersionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeastCoreVersionResponse.ProtoReflect.Descriptor instead. func (*GetFeastCoreVersionResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{9} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{11} } func (x *GetFeastCoreVersionResponse) GetVersion() string { @@ -648,7 +742,7 @@ type UpdateStoreRequest struct { func (x *UpdateStoreRequest) Reset() { *x = UpdateStoreRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[10] + mi := &file_feast_core_CoreService_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -661,7 +755,7 @@ func (x *UpdateStoreRequest) String() string { func (*UpdateStoreRequest) ProtoMessage() {} func (x *UpdateStoreRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[10] + mi := &file_feast_core_CoreService_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -674,7 +768,7 @@ func (x *UpdateStoreRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateStoreRequest.ProtoReflect.Descriptor instead. func (*UpdateStoreRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{10} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{12} } func (x *UpdateStoreRequest) GetStore() *Store { @@ -696,7 +790,7 @@ type UpdateStoreResponse struct { func (x *UpdateStoreResponse) Reset() { *x = UpdateStoreResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[11] + mi := &file_feast_core_CoreService_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -709,7 +803,7 @@ func (x *UpdateStoreResponse) String() string { func (*UpdateStoreResponse) ProtoMessage() {} func (x *UpdateStoreResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[11] + mi := &file_feast_core_CoreService_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -722,7 +816,7 @@ func (x *UpdateStoreResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateStoreResponse.ProtoReflect.Descriptor instead. func (*UpdateStoreResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{11} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{13} } func (x *UpdateStoreResponse) GetStore() *Store { @@ -752,7 +846,7 @@ type CreateProjectRequest struct { func (x *CreateProjectRequest) Reset() { *x = CreateProjectRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[12] + mi := &file_feast_core_CoreService_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -765,7 +859,7 @@ func (x *CreateProjectRequest) String() string { func (*CreateProjectRequest) ProtoMessage() {} func (x *CreateProjectRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[12] + mi := &file_feast_core_CoreService_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -778,7 +872,7 @@ func (x *CreateProjectRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateProjectRequest.ProtoReflect.Descriptor instead. func (*CreateProjectRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{12} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{14} } func (x *CreateProjectRequest) GetName() string { @@ -798,7 +892,7 @@ type CreateProjectResponse struct { func (x *CreateProjectResponse) Reset() { *x = CreateProjectResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[13] + mi := &file_feast_core_CoreService_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -811,7 +905,7 @@ func (x *CreateProjectResponse) String() string { func (*CreateProjectResponse) ProtoMessage() {} func (x *CreateProjectResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[13] + mi := &file_feast_core_CoreService_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -824,7 +918,7 @@ func (x *CreateProjectResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateProjectResponse.ProtoReflect.Descriptor instead. func (*CreateProjectResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{13} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{15} } // Request for the archival of a project @@ -840,7 +934,7 @@ type ArchiveProjectRequest struct { func (x *ArchiveProjectRequest) Reset() { *x = ArchiveProjectRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[14] + mi := &file_feast_core_CoreService_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -853,7 +947,7 @@ func (x *ArchiveProjectRequest) String() string { func (*ArchiveProjectRequest) ProtoMessage() {} func (x *ArchiveProjectRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[14] + mi := &file_feast_core_CoreService_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -866,7 +960,7 @@ func (x *ArchiveProjectRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ArchiveProjectRequest.ProtoReflect.Descriptor instead. func (*ArchiveProjectRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{14} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{16} } func (x *ArchiveProjectRequest) GetName() string { @@ -886,7 +980,7 @@ type ArchiveProjectResponse struct { func (x *ArchiveProjectResponse) Reset() { *x = ArchiveProjectResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[15] + mi := &file_feast_core_CoreService_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -899,7 +993,7 @@ func (x *ArchiveProjectResponse) String() string { func (*ArchiveProjectResponse) ProtoMessage() {} func (x *ArchiveProjectResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[15] + mi := &file_feast_core_CoreService_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -912,7 +1006,7 @@ func (x *ArchiveProjectResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ArchiveProjectResponse.ProtoReflect.Descriptor instead. func (*ArchiveProjectResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{15} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{17} } // Request for listing of projects @@ -925,7 +1019,7 @@ type ListProjectsRequest struct { func (x *ListProjectsRequest) Reset() { *x = ListProjectsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[16] + mi := &file_feast_core_CoreService_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -938,7 +1032,7 @@ func (x *ListProjectsRequest) String() string { func (*ListProjectsRequest) ProtoMessage() {} func (x *ListProjectsRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[16] + mi := &file_feast_core_CoreService_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -951,7 +1045,7 @@ func (x *ListProjectsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListProjectsRequest.ProtoReflect.Descriptor instead. func (*ListProjectsRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{16} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{18} } // Response for listing of projects @@ -967,7 +1061,7 @@ type ListProjectsResponse struct { func (x *ListProjectsResponse) Reset() { *x = ListProjectsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[17] + mi := &file_feast_core_CoreService_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -980,7 +1074,7 @@ func (x *ListProjectsResponse) String() string { func (*ListProjectsResponse) ProtoMessage() {} func (x *ListProjectsResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[17] + mi := &file_feast_core_CoreService_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -993,7 +1087,7 @@ func (x *ListProjectsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListProjectsResponse.ProtoReflect.Descriptor instead. func (*ListProjectsResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{17} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{19} } func (x *ListProjectsResponse) GetProjects() []string { @@ -1015,7 +1109,7 @@ type ListIngestionJobsRequest struct { func (x *ListIngestionJobsRequest) Reset() { *x = ListIngestionJobsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[18] + mi := &file_feast_core_CoreService_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1028,7 +1122,7 @@ func (x *ListIngestionJobsRequest) String() string { func (*ListIngestionJobsRequest) ProtoMessage() {} func (x *ListIngestionJobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[18] + mi := &file_feast_core_CoreService_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1041,7 +1135,7 @@ func (x *ListIngestionJobsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListIngestionJobsRequest.ProtoReflect.Descriptor instead. func (*ListIngestionJobsRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{18} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{20} } func (x *ListIngestionJobsRequest) GetFilter() *ListIngestionJobsRequest_Filter { @@ -1063,7 +1157,7 @@ type ListIngestionJobsResponse struct { func (x *ListIngestionJobsResponse) Reset() { *x = ListIngestionJobsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[19] + mi := &file_feast_core_CoreService_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1076,7 +1170,7 @@ func (x *ListIngestionJobsResponse) String() string { func (*ListIngestionJobsResponse) ProtoMessage() {} func (x *ListIngestionJobsResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[19] + mi := &file_feast_core_CoreService_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1089,7 +1183,7 @@ func (x *ListIngestionJobsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListIngestionJobsResponse.ProtoReflect.Descriptor instead. func (*ListIngestionJobsResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{19} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{21} } func (x *ListIngestionJobsResponse) GetJobs() []*IngestionJob { @@ -1112,7 +1206,7 @@ type RestartIngestionJobRequest struct { func (x *RestartIngestionJobRequest) Reset() { *x = RestartIngestionJobRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[20] + mi := &file_feast_core_CoreService_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1125,7 +1219,7 @@ func (x *RestartIngestionJobRequest) String() string { func (*RestartIngestionJobRequest) ProtoMessage() {} func (x *RestartIngestionJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[20] + mi := &file_feast_core_CoreService_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1138,7 +1232,7 @@ func (x *RestartIngestionJobRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestartIngestionJobRequest.ProtoReflect.Descriptor instead. func (*RestartIngestionJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{20} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{22} } func (x *RestartIngestionJobRequest) GetId() string { @@ -1158,7 +1252,7 @@ type RestartIngestionJobResponse struct { func (x *RestartIngestionJobResponse) Reset() { *x = RestartIngestionJobResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[21] + mi := &file_feast_core_CoreService_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1171,7 +1265,7 @@ func (x *RestartIngestionJobResponse) String() string { func (*RestartIngestionJobResponse) ProtoMessage() {} func (x *RestartIngestionJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[21] + mi := &file_feast_core_CoreService_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1184,7 +1278,7 @@ func (x *RestartIngestionJobResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RestartIngestionJobResponse.ProtoReflect.Descriptor instead. func (*RestartIngestionJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{21} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{23} } // Request to stop ingestion job @@ -1200,7 +1294,7 @@ type StopIngestionJobRequest struct { func (x *StopIngestionJobRequest) Reset() { *x = StopIngestionJobRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[22] + mi := &file_feast_core_CoreService_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1213,7 +1307,7 @@ func (x *StopIngestionJobRequest) String() string { func (*StopIngestionJobRequest) ProtoMessage() {} func (x *StopIngestionJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[22] + mi := &file_feast_core_CoreService_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1226,7 +1320,7 @@ func (x *StopIngestionJobRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopIngestionJobRequest.ProtoReflect.Descriptor instead. func (*StopIngestionJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{22} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{24} } func (x *StopIngestionJobRequest) GetId() string { @@ -1246,7 +1340,7 @@ type StopIngestionJobResponse struct { func (x *StopIngestionJobResponse) Reset() { *x = StopIngestionJobResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[23] + mi := &file_feast_core_CoreService_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1259,7 +1353,7 @@ func (x *StopIngestionJobResponse) String() string { func (*StopIngestionJobResponse) ProtoMessage() {} func (x *StopIngestionJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[23] + mi := &file_feast_core_CoreService_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1272,7 +1366,7 @@ func (x *StopIngestionJobResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopIngestionJobResponse.ProtoReflect.Descriptor instead. func (*StopIngestionJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{23} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{25} } type GetFeatureStatisticsRequest struct { @@ -1309,7 +1403,7 @@ type GetFeatureStatisticsRequest struct { func (x *GetFeatureStatisticsRequest) Reset() { *x = GetFeatureStatisticsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[24] + mi := &file_feast_core_CoreService_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1322,7 +1416,7 @@ func (x *GetFeatureStatisticsRequest) String() string { func (*GetFeatureStatisticsRequest) ProtoMessage() {} func (x *GetFeatureStatisticsRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[24] + mi := &file_feast_core_CoreService_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1335,7 +1429,7 @@ func (x *GetFeatureStatisticsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeatureStatisticsRequest.ProtoReflect.Descriptor instead. func (*GetFeatureStatisticsRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{24} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{26} } func (x *GetFeatureStatisticsRequest) GetFeatureSetId() string { @@ -1401,7 +1495,7 @@ type GetFeatureStatisticsResponse struct { func (x *GetFeatureStatisticsResponse) Reset() { *x = GetFeatureStatisticsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[25] + mi := &file_feast_core_CoreService_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1414,7 +1508,7 @@ func (x *GetFeatureStatisticsResponse) String() string { func (*GetFeatureStatisticsResponse) ProtoMessage() {} func (x *GetFeatureStatisticsResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[25] + mi := &file_feast_core_CoreService_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1427,7 +1521,7 @@ func (x *GetFeatureStatisticsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeatureStatisticsResponse.ProtoReflect.Descriptor instead. func (*GetFeatureStatisticsResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{25} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{27} } func (x *GetFeatureStatisticsResponse) GetDatasetFeatureStatisticsList() *v0.DatasetFeatureStatisticsList { @@ -1458,12 +1552,15 @@ type ListFeatureSetsRequest_Filter struct { // - my-feature-set* can be used to match all features prefixed by "my-feature-set" // - my-feature-set-6 can be used to select a single feature set FeatureSetName string `protobuf:"bytes,1,opt,name=feature_set_name,json=featureSetName,proto3" json:"feature_set_name,omitempty"` + // User defined metadata for feature set. + // Feature sets with all matching labels will be returned. + Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *ListFeatureSetsRequest_Filter) Reset() { *x = ListFeatureSetsRequest_Filter{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[26] + mi := &file_feast_core_CoreService_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1476,7 +1573,7 @@ func (x *ListFeatureSetsRequest_Filter) String() string { func (*ListFeatureSetsRequest_Filter) ProtoMessage() {} func (x *ListFeatureSetsRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[26] + mi := &file_feast_core_CoreService_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1506,6 +1603,83 @@ func (x *ListFeatureSetsRequest_Filter) GetFeatureSetName() string { return "" } +func (x *ListFeatureSetsRequest_Filter) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +type ListFeaturesRequest_Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // User defined metadata for feature. + // Features with all matching labels will be returned. + Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // List of entities contained within the featureSet that the feature belongs to. + // Only feature sets with these entities will be searched for features. + Entities []string `protobuf:"bytes,2,rep,name=entities,proto3" json:"entities,omitempty"` + // Name of project that the feature sets belongs to. Filtering on projects is disabled. + // It is NOT possible to provide an asterisk with a string in order to do pattern matching. + // If unspecified this field will default to the default project 'default'. + Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"` +} + +func (x *ListFeaturesRequest_Filter) Reset() { + *x = ListFeaturesRequest_Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_feast_core_CoreService_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListFeaturesRequest_Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFeaturesRequest_Filter) ProtoMessage() {} + +func (x *ListFeaturesRequest_Filter) ProtoReflect() protoreflect.Message { + mi := &file_feast_core_CoreService_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFeaturesRequest_Filter.ProtoReflect.Descriptor instead. +func (*ListFeaturesRequest_Filter) Descriptor() ([]byte, []int) { + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *ListFeaturesRequest_Filter) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *ListFeaturesRequest_Filter) GetEntities() []string { + if x != nil { + return x.Entities + } + return nil +} + +func (x *ListFeaturesRequest_Filter) GetProject() string { + if x != nil { + return x.Project + } + return "" +} + type ListStoresRequest_Filter struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1518,7 +1692,7 @@ type ListStoresRequest_Filter struct { func (x *ListStoresRequest_Filter) Reset() { *x = ListStoresRequest_Filter{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[27] + mi := &file_feast_core_CoreService_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1531,7 +1705,7 @@ func (x *ListStoresRequest_Filter) String() string { func (*ListStoresRequest_Filter) ProtoMessage() {} func (x *ListStoresRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[27] + mi := &file_feast_core_CoreService_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1544,7 +1718,7 @@ func (x *ListStoresRequest_Filter) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStoresRequest_Filter.ProtoReflect.Descriptor instead. func (*ListStoresRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4, 0} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{6, 0} } func (x *ListStoresRequest_Filter) GetName() string { @@ -1570,7 +1744,7 @@ type ListIngestionJobsRequest_Filter struct { func (x *ListIngestionJobsRequest_Filter) Reset() { *x = ListIngestionJobsRequest_Filter{} if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[28] + mi := &file_feast_core_CoreService_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1583,7 +1757,7 @@ func (x *ListIngestionJobsRequest_Filter) String() string { func (*ListIngestionJobsRequest_Filter) ProtoMessage() {} func (x *ListIngestionJobsRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[28] + mi := &file_feast_core_CoreService_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1596,7 +1770,7 @@ func (x *ListIngestionJobsRequest_Filter) ProtoReflect() protoreflect.Message { // Deprecated: Use ListIngestionJobsRequest_Filter.ProtoReflect.Descriptor instead. func (*ListIngestionJobsRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{18, 0} + return file_feast_core_CoreService_proto_rawDescGZIP(), []int{20, 0} } func (x *ListIngestionJobsRequest_Filter) GetId() string { @@ -1647,226 +1821,270 @@ var file_feast_core_CoreService_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x22, 0xa9, 0x01, 0x0a, + 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x22, 0xb4, 0x02, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x4c, 0x0a, 0x06, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, - 0x0a, 0x10, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x54, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, - 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x52, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x22, 0x6f, - 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xd6, 0x01, 0x0a, 0x06, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x28, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x54, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, + 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x0b, 0x66, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x22, 0x9d, 0x02, 0x0a, 0x13, 0x4c, 0x69, + 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x1a, 0x1c, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, - 0x3d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x51, - 0x0a, 0x16, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x17, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x42, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3c, 0x0a, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, - 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, - 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, - 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x46, - 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x37, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, - 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0x3d, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0xa4, - 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, - 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x24, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, - 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, - 0x54, 0x45, 0x44, 0x10, 0x01, 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x0a, 0x15, 0x41, 0x72, - 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x41, 0x72, 0x63, 0x68, 0x69, - 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x32, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0xee, 0x01, 0x0a, - 0x18, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x06, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x8c, - 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x53, 0x0a, 0x15, 0x66, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, + 0x72, 0x1a, 0xc5, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x39, + 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb8, 0x01, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x54, + 0x0a, 0x0d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6f, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x1c, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x22, 0x51, 0x0a, 0x16, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, + 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x0a, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x17, 0x41, 0x70, 0x70, 0x6c, + 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, + 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x13, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, - 0x19, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x6a, 0x6f, - 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, - 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x2c, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, + 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x42, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x3c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, + 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x1c, + 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x37, 0x0a, 0x1b, + 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3d, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, + 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, + 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, + 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x24, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x00, 0x12, 0x0b, + 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x22, 0x2a, 0x0a, 0x14, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2b, 0x0a, 0x15, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x18, 0x0a, + 0x16, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x32, + 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x22, 0xee, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x43, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x8c, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x53, 0x0a, 0x15, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, + 0x13, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2c, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x2c, + 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, + 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, + 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x17, 0x53, + 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x17, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, - 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x02, 0x0a, - 0x1b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0e, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, - 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, - 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, - 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, - 0x22, 0x9b, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x7b, 0x0a, 0x1f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x1c, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x32, 0xb6, - 0x09, 0x0a, 0x0b, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, - 0x0a, 0x13, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, - 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, - 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, - 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, - 0x12, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, + 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0xb1, 0x02, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x44, 0x61, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x61, 0x74, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x22, 0x9b, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x1f, 0x64, 0x61, 0x74, 0x61, 0x73, + 0x65, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x63, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x1c, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x32, 0x89, 0x0a, 0x0a, 0x0b, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, + 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x66, 0x65, + 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, + 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x20, 0x2e, + 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, + 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1f, + 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x69, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, - 0x73, 0x12, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5a, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x53, 0x65, 0x74, 0x12, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0b, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0d, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x12, 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x4c, - 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, - 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, - 0x6f, 0x62, 0x73, 0x12, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x66, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x73, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0a, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x22, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, + 0x74, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x21, 0x2e, + 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, + 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x49, + 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x24, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, + 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x53, 0x74, 0x6f, 0x70, - 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x23, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, - 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, - 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x59, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x10, 0x43, 0x6f, 0x72, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, + 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x67, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, + 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x49, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x59, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x42, 0x10, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, + 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1882,7 +2100,7 @@ func file_feast_core_CoreService_proto_rawDescGZIP() []byte { } var file_feast_core_CoreService_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_feast_core_CoreService_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_feast_core_CoreService_proto_msgTypes = make([]protoimpl.MessageInfo, 35) var file_feast_core_CoreService_proto_goTypes = []interface{}{ (ApplyFeatureSetResponse_Status)(0), // 0: feast.core.ApplyFeatureSetResponse.Status (UpdateStoreResponse_Status)(0), // 1: feast.core.UpdateStoreResponse.Status @@ -1890,87 +2108,101 @@ var file_feast_core_CoreService_proto_goTypes = []interface{}{ (*GetFeatureSetResponse)(nil), // 3: feast.core.GetFeatureSetResponse (*ListFeatureSetsRequest)(nil), // 4: feast.core.ListFeatureSetsRequest (*ListFeatureSetsResponse)(nil), // 5: feast.core.ListFeatureSetsResponse - (*ListStoresRequest)(nil), // 6: feast.core.ListStoresRequest - (*ListStoresResponse)(nil), // 7: feast.core.ListStoresResponse - (*ApplyFeatureSetRequest)(nil), // 8: feast.core.ApplyFeatureSetRequest - (*ApplyFeatureSetResponse)(nil), // 9: feast.core.ApplyFeatureSetResponse - (*GetFeastCoreVersionRequest)(nil), // 10: feast.core.GetFeastCoreVersionRequest - (*GetFeastCoreVersionResponse)(nil), // 11: feast.core.GetFeastCoreVersionResponse - (*UpdateStoreRequest)(nil), // 12: feast.core.UpdateStoreRequest - (*UpdateStoreResponse)(nil), // 13: feast.core.UpdateStoreResponse - (*CreateProjectRequest)(nil), // 14: feast.core.CreateProjectRequest - (*CreateProjectResponse)(nil), // 15: feast.core.CreateProjectResponse - (*ArchiveProjectRequest)(nil), // 16: feast.core.ArchiveProjectRequest - (*ArchiveProjectResponse)(nil), // 17: feast.core.ArchiveProjectResponse - (*ListProjectsRequest)(nil), // 18: feast.core.ListProjectsRequest - (*ListProjectsResponse)(nil), // 19: feast.core.ListProjectsResponse - (*ListIngestionJobsRequest)(nil), // 20: feast.core.ListIngestionJobsRequest - (*ListIngestionJobsResponse)(nil), // 21: feast.core.ListIngestionJobsResponse - (*RestartIngestionJobRequest)(nil), // 22: feast.core.RestartIngestionJobRequest - (*RestartIngestionJobResponse)(nil), // 23: feast.core.RestartIngestionJobResponse - (*StopIngestionJobRequest)(nil), // 24: feast.core.StopIngestionJobRequest - (*StopIngestionJobResponse)(nil), // 25: feast.core.StopIngestionJobResponse - (*GetFeatureStatisticsRequest)(nil), // 26: feast.core.GetFeatureStatisticsRequest - (*GetFeatureStatisticsResponse)(nil), // 27: feast.core.GetFeatureStatisticsResponse - (*ListFeatureSetsRequest_Filter)(nil), // 28: feast.core.ListFeatureSetsRequest.Filter - (*ListStoresRequest_Filter)(nil), // 29: feast.core.ListStoresRequest.Filter - (*ListIngestionJobsRequest_Filter)(nil), // 30: feast.core.ListIngestionJobsRequest.Filter - (*FeatureSet)(nil), // 31: feast.core.FeatureSet - (*Store)(nil), // 32: feast.core.Store - (*IngestionJob)(nil), // 33: feast.core.IngestionJob - (*timestamp.Timestamp)(nil), // 34: google.protobuf.Timestamp - (*v0.DatasetFeatureStatisticsList)(nil), // 35: tensorflow.metadata.v0.DatasetFeatureStatisticsList - (*FeatureSetReference)(nil), // 36: feast.core.FeatureSetReference + (*ListFeaturesRequest)(nil), // 6: feast.core.ListFeaturesRequest + (*ListFeaturesResponse)(nil), // 7: feast.core.ListFeaturesResponse + (*ListStoresRequest)(nil), // 8: feast.core.ListStoresRequest + (*ListStoresResponse)(nil), // 9: feast.core.ListStoresResponse + (*ApplyFeatureSetRequest)(nil), // 10: feast.core.ApplyFeatureSetRequest + (*ApplyFeatureSetResponse)(nil), // 11: feast.core.ApplyFeatureSetResponse + (*GetFeastCoreVersionRequest)(nil), // 12: feast.core.GetFeastCoreVersionRequest + (*GetFeastCoreVersionResponse)(nil), // 13: feast.core.GetFeastCoreVersionResponse + (*UpdateStoreRequest)(nil), // 14: feast.core.UpdateStoreRequest + (*UpdateStoreResponse)(nil), // 15: feast.core.UpdateStoreResponse + (*CreateProjectRequest)(nil), // 16: feast.core.CreateProjectRequest + (*CreateProjectResponse)(nil), // 17: feast.core.CreateProjectResponse + (*ArchiveProjectRequest)(nil), // 18: feast.core.ArchiveProjectRequest + (*ArchiveProjectResponse)(nil), // 19: feast.core.ArchiveProjectResponse + (*ListProjectsRequest)(nil), // 20: feast.core.ListProjectsRequest + (*ListProjectsResponse)(nil), // 21: feast.core.ListProjectsResponse + (*ListIngestionJobsRequest)(nil), // 22: feast.core.ListIngestionJobsRequest + (*ListIngestionJobsResponse)(nil), // 23: feast.core.ListIngestionJobsResponse + (*RestartIngestionJobRequest)(nil), // 24: feast.core.RestartIngestionJobRequest + (*RestartIngestionJobResponse)(nil), // 25: feast.core.RestartIngestionJobResponse + (*StopIngestionJobRequest)(nil), // 26: feast.core.StopIngestionJobRequest + (*StopIngestionJobResponse)(nil), // 27: feast.core.StopIngestionJobResponse + (*GetFeatureStatisticsRequest)(nil), // 28: feast.core.GetFeatureStatisticsRequest + (*GetFeatureStatisticsResponse)(nil), // 29: feast.core.GetFeatureStatisticsResponse + (*ListFeatureSetsRequest_Filter)(nil), // 30: feast.core.ListFeatureSetsRequest.Filter + nil, // 31: feast.core.ListFeatureSetsRequest.Filter.LabelsEntry + (*ListFeaturesRequest_Filter)(nil), // 32: feast.core.ListFeaturesRequest.Filter + nil, // 33: feast.core.ListFeaturesRequest.Filter.LabelsEntry + nil, // 34: feast.core.ListFeaturesResponse.FeaturesEntry + (*ListStoresRequest_Filter)(nil), // 35: feast.core.ListStoresRequest.Filter + (*ListIngestionJobsRequest_Filter)(nil), // 36: feast.core.ListIngestionJobsRequest.Filter + (*FeatureSet)(nil), // 37: feast.core.FeatureSet + (*Store)(nil), // 38: feast.core.Store + (*IngestionJob)(nil), // 39: feast.core.IngestionJob + (*timestamp.Timestamp)(nil), // 40: google.protobuf.Timestamp + (*v0.DatasetFeatureStatisticsList)(nil), // 41: tensorflow.metadata.v0.DatasetFeatureStatisticsList + (*FeatureSpec)(nil), // 42: feast.core.FeatureSpec + (*FeatureSetReference)(nil), // 43: feast.core.FeatureSetReference } var file_feast_core_CoreService_proto_depIdxs = []int32{ - 31, // 0: feast.core.GetFeatureSetResponse.feature_set:type_name -> feast.core.FeatureSet - 28, // 1: feast.core.ListFeatureSetsRequest.filter:type_name -> feast.core.ListFeatureSetsRequest.Filter - 31, // 2: feast.core.ListFeatureSetsResponse.feature_sets:type_name -> feast.core.FeatureSet - 29, // 3: feast.core.ListStoresRequest.filter:type_name -> feast.core.ListStoresRequest.Filter - 32, // 4: feast.core.ListStoresResponse.store:type_name -> feast.core.Store - 31, // 5: feast.core.ApplyFeatureSetRequest.feature_set:type_name -> feast.core.FeatureSet - 31, // 6: feast.core.ApplyFeatureSetResponse.feature_set:type_name -> feast.core.FeatureSet - 0, // 7: feast.core.ApplyFeatureSetResponse.status:type_name -> feast.core.ApplyFeatureSetResponse.Status - 32, // 8: feast.core.UpdateStoreRequest.store:type_name -> feast.core.Store - 32, // 9: feast.core.UpdateStoreResponse.store:type_name -> feast.core.Store - 1, // 10: feast.core.UpdateStoreResponse.status:type_name -> feast.core.UpdateStoreResponse.Status - 30, // 11: feast.core.ListIngestionJobsRequest.filter:type_name -> feast.core.ListIngestionJobsRequest.Filter - 33, // 12: feast.core.ListIngestionJobsResponse.jobs:type_name -> feast.core.IngestionJob - 34, // 13: feast.core.GetFeatureStatisticsRequest.start_date:type_name -> google.protobuf.Timestamp - 34, // 14: feast.core.GetFeatureStatisticsRequest.end_date:type_name -> google.protobuf.Timestamp - 35, // 15: feast.core.GetFeatureStatisticsResponse.dataset_feature_statistics_list:type_name -> tensorflow.metadata.v0.DatasetFeatureStatisticsList - 36, // 16: feast.core.ListIngestionJobsRequest.Filter.feature_set_reference:type_name -> feast.core.FeatureSetReference - 10, // 17: feast.core.CoreService.GetFeastCoreVersion:input_type -> feast.core.GetFeastCoreVersionRequest - 2, // 18: feast.core.CoreService.GetFeatureSet:input_type -> feast.core.GetFeatureSetRequest - 4, // 19: feast.core.CoreService.ListFeatureSets:input_type -> feast.core.ListFeatureSetsRequest - 26, // 20: feast.core.CoreService.GetFeatureStatistics:input_type -> feast.core.GetFeatureStatisticsRequest - 6, // 21: feast.core.CoreService.ListStores:input_type -> feast.core.ListStoresRequest - 8, // 22: feast.core.CoreService.ApplyFeatureSet:input_type -> feast.core.ApplyFeatureSetRequest - 12, // 23: feast.core.CoreService.UpdateStore:input_type -> feast.core.UpdateStoreRequest - 14, // 24: feast.core.CoreService.CreateProject:input_type -> feast.core.CreateProjectRequest - 16, // 25: feast.core.CoreService.ArchiveProject:input_type -> feast.core.ArchiveProjectRequest - 18, // 26: feast.core.CoreService.ListProjects:input_type -> feast.core.ListProjectsRequest - 20, // 27: feast.core.CoreService.ListIngestionJobs:input_type -> feast.core.ListIngestionJobsRequest - 22, // 28: feast.core.CoreService.RestartIngestionJob:input_type -> feast.core.RestartIngestionJobRequest - 24, // 29: feast.core.CoreService.StopIngestionJob:input_type -> feast.core.StopIngestionJobRequest - 11, // 30: feast.core.CoreService.GetFeastCoreVersion:output_type -> feast.core.GetFeastCoreVersionResponse - 3, // 31: feast.core.CoreService.GetFeatureSet:output_type -> feast.core.GetFeatureSetResponse - 5, // 32: feast.core.CoreService.ListFeatureSets:output_type -> feast.core.ListFeatureSetsResponse - 27, // 33: feast.core.CoreService.GetFeatureStatistics:output_type -> feast.core.GetFeatureStatisticsResponse - 7, // 34: feast.core.CoreService.ListStores:output_type -> feast.core.ListStoresResponse - 9, // 35: feast.core.CoreService.ApplyFeatureSet:output_type -> feast.core.ApplyFeatureSetResponse - 13, // 36: feast.core.CoreService.UpdateStore:output_type -> feast.core.UpdateStoreResponse - 15, // 37: feast.core.CoreService.CreateProject:output_type -> feast.core.CreateProjectResponse - 17, // 38: feast.core.CoreService.ArchiveProject:output_type -> feast.core.ArchiveProjectResponse - 19, // 39: feast.core.CoreService.ListProjects:output_type -> feast.core.ListProjectsResponse - 21, // 40: feast.core.CoreService.ListIngestionJobs:output_type -> feast.core.ListIngestionJobsResponse - 23, // 41: feast.core.CoreService.RestartIngestionJob:output_type -> feast.core.RestartIngestionJobResponse - 25, // 42: feast.core.CoreService.StopIngestionJob:output_type -> feast.core.StopIngestionJobResponse - 30, // [30:43] is the sub-list for method output_type - 17, // [17:30] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 37, // 0: feast.core.GetFeatureSetResponse.feature_set:type_name -> feast.core.FeatureSet + 30, // 1: feast.core.ListFeatureSetsRequest.filter:type_name -> feast.core.ListFeatureSetsRequest.Filter + 37, // 2: feast.core.ListFeatureSetsResponse.feature_sets:type_name -> feast.core.FeatureSet + 32, // 3: feast.core.ListFeaturesRequest.filter:type_name -> feast.core.ListFeaturesRequest.Filter + 34, // 4: feast.core.ListFeaturesResponse.features:type_name -> feast.core.ListFeaturesResponse.FeaturesEntry + 35, // 5: feast.core.ListStoresRequest.filter:type_name -> feast.core.ListStoresRequest.Filter + 38, // 6: feast.core.ListStoresResponse.store:type_name -> feast.core.Store + 37, // 7: feast.core.ApplyFeatureSetRequest.feature_set:type_name -> feast.core.FeatureSet + 37, // 8: feast.core.ApplyFeatureSetResponse.feature_set:type_name -> feast.core.FeatureSet + 0, // 9: feast.core.ApplyFeatureSetResponse.status:type_name -> feast.core.ApplyFeatureSetResponse.Status + 38, // 10: feast.core.UpdateStoreRequest.store:type_name -> feast.core.Store + 38, // 11: feast.core.UpdateStoreResponse.store:type_name -> feast.core.Store + 1, // 12: feast.core.UpdateStoreResponse.status:type_name -> feast.core.UpdateStoreResponse.Status + 36, // 13: feast.core.ListIngestionJobsRequest.filter:type_name -> feast.core.ListIngestionJobsRequest.Filter + 39, // 14: feast.core.ListIngestionJobsResponse.jobs:type_name -> feast.core.IngestionJob + 40, // 15: feast.core.GetFeatureStatisticsRequest.start_date:type_name -> google.protobuf.Timestamp + 40, // 16: feast.core.GetFeatureStatisticsRequest.end_date:type_name -> google.protobuf.Timestamp + 41, // 17: feast.core.GetFeatureStatisticsResponse.dataset_feature_statistics_list:type_name -> tensorflow.metadata.v0.DatasetFeatureStatisticsList + 31, // 18: feast.core.ListFeatureSetsRequest.Filter.labels:type_name -> feast.core.ListFeatureSetsRequest.Filter.LabelsEntry + 33, // 19: feast.core.ListFeaturesRequest.Filter.labels:type_name -> feast.core.ListFeaturesRequest.Filter.LabelsEntry + 42, // 20: feast.core.ListFeaturesResponse.FeaturesEntry.value:type_name -> feast.core.FeatureSpec + 43, // 21: feast.core.ListIngestionJobsRequest.Filter.feature_set_reference:type_name -> feast.core.FeatureSetReference + 12, // 22: feast.core.CoreService.GetFeastCoreVersion:input_type -> feast.core.GetFeastCoreVersionRequest + 2, // 23: feast.core.CoreService.GetFeatureSet:input_type -> feast.core.GetFeatureSetRequest + 4, // 24: feast.core.CoreService.ListFeatureSets:input_type -> feast.core.ListFeatureSetsRequest + 6, // 25: feast.core.CoreService.ListFeatures:input_type -> feast.core.ListFeaturesRequest + 28, // 26: feast.core.CoreService.GetFeatureStatistics:input_type -> feast.core.GetFeatureStatisticsRequest + 8, // 27: feast.core.CoreService.ListStores:input_type -> feast.core.ListStoresRequest + 10, // 28: feast.core.CoreService.ApplyFeatureSet:input_type -> feast.core.ApplyFeatureSetRequest + 14, // 29: feast.core.CoreService.UpdateStore:input_type -> feast.core.UpdateStoreRequest + 16, // 30: feast.core.CoreService.CreateProject:input_type -> feast.core.CreateProjectRequest + 18, // 31: feast.core.CoreService.ArchiveProject:input_type -> feast.core.ArchiveProjectRequest + 20, // 32: feast.core.CoreService.ListProjects:input_type -> feast.core.ListProjectsRequest + 22, // 33: feast.core.CoreService.ListIngestionJobs:input_type -> feast.core.ListIngestionJobsRequest + 24, // 34: feast.core.CoreService.RestartIngestionJob:input_type -> feast.core.RestartIngestionJobRequest + 26, // 35: feast.core.CoreService.StopIngestionJob:input_type -> feast.core.StopIngestionJobRequest + 13, // 36: feast.core.CoreService.GetFeastCoreVersion:output_type -> feast.core.GetFeastCoreVersionResponse + 3, // 37: feast.core.CoreService.GetFeatureSet:output_type -> feast.core.GetFeatureSetResponse + 5, // 38: feast.core.CoreService.ListFeatureSets:output_type -> feast.core.ListFeatureSetsResponse + 7, // 39: feast.core.CoreService.ListFeatures:output_type -> feast.core.ListFeaturesResponse + 29, // 40: feast.core.CoreService.GetFeatureStatistics:output_type -> feast.core.GetFeatureStatisticsResponse + 9, // 41: feast.core.CoreService.ListStores:output_type -> feast.core.ListStoresResponse + 11, // 42: feast.core.CoreService.ApplyFeatureSet:output_type -> feast.core.ApplyFeatureSetResponse + 15, // 43: feast.core.CoreService.UpdateStore:output_type -> feast.core.UpdateStoreResponse + 17, // 44: feast.core.CoreService.CreateProject:output_type -> feast.core.CreateProjectResponse + 19, // 45: feast.core.CoreService.ArchiveProject:output_type -> feast.core.ArchiveProjectResponse + 21, // 46: feast.core.CoreService.ListProjects:output_type -> feast.core.ListProjectsResponse + 23, // 47: feast.core.CoreService.ListIngestionJobs:output_type -> feast.core.ListIngestionJobsResponse + 25, // 48: feast.core.CoreService.RestartIngestionJob:output_type -> feast.core.RestartIngestionJobResponse + 27, // 49: feast.core.CoreService.StopIngestionJob:output_type -> feast.core.StopIngestionJobResponse + 36, // [36:50] is the sub-list for method output_type + 22, // [22:36] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_feast_core_CoreService_proto_init() } @@ -2032,7 +2264,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresRequest); i { + switch v := v.(*ListFeaturesRequest); i { case 0: return &v.state case 1: @@ -2044,7 +2276,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresResponse); i { + switch v := v.(*ListFeaturesResponse); i { case 0: return &v.state case 1: @@ -2056,7 +2288,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyFeatureSetRequest); i { + switch v := v.(*ListStoresRequest); i { case 0: return &v.state case 1: @@ -2068,7 +2300,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyFeatureSetResponse); i { + switch v := v.(*ListStoresResponse); i { case 0: return &v.state case 1: @@ -2080,7 +2312,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastCoreVersionRequest); i { + switch v := v.(*ApplyFeatureSetRequest); i { case 0: return &v.state case 1: @@ -2092,7 +2324,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastCoreVersionResponse); i { + switch v := v.(*ApplyFeatureSetResponse); i { case 0: return &v.state case 1: @@ -2104,7 +2336,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateStoreRequest); i { + switch v := v.(*GetFeastCoreVersionRequest); i { case 0: return &v.state case 1: @@ -2116,7 +2348,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateStoreResponse); i { + switch v := v.(*GetFeastCoreVersionResponse); i { case 0: return &v.state case 1: @@ -2128,7 +2360,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateProjectRequest); i { + switch v := v.(*UpdateStoreRequest); i { case 0: return &v.state case 1: @@ -2140,7 +2372,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateProjectResponse); i { + switch v := v.(*UpdateStoreResponse); i { case 0: return &v.state case 1: @@ -2152,7 +2384,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArchiveProjectRequest); i { + switch v := v.(*CreateProjectRequest); i { case 0: return &v.state case 1: @@ -2164,7 +2396,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArchiveProjectResponse); i { + switch v := v.(*CreateProjectResponse); i { case 0: return &v.state case 1: @@ -2176,7 +2408,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProjectsRequest); i { + switch v := v.(*ArchiveProjectRequest); i { case 0: return &v.state case 1: @@ -2188,7 +2420,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProjectsResponse); i { + switch v := v.(*ArchiveProjectResponse); i { case 0: return &v.state case 1: @@ -2200,7 +2432,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListIngestionJobsRequest); i { + switch v := v.(*ListProjectsRequest); i { case 0: return &v.state case 1: @@ -2212,7 +2444,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListIngestionJobsResponse); i { + switch v := v.(*ListProjectsResponse); i { case 0: return &v.state case 1: @@ -2224,7 +2456,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RestartIngestionJobRequest); i { + switch v := v.(*ListIngestionJobsRequest); i { case 0: return &v.state case 1: @@ -2236,7 +2468,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RestartIngestionJobResponse); i { + switch v := v.(*ListIngestionJobsResponse); i { case 0: return &v.state case 1: @@ -2248,7 +2480,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopIngestionJobRequest); i { + switch v := v.(*RestartIngestionJobRequest); i { case 0: return &v.state case 1: @@ -2260,7 +2492,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopIngestionJobResponse); i { + switch v := v.(*RestartIngestionJobResponse); i { case 0: return &v.state case 1: @@ -2272,7 +2504,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeatureStatisticsRequest); i { + switch v := v.(*StopIngestionJobRequest); i { case 0: return &v.state case 1: @@ -2284,7 +2516,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeatureStatisticsResponse); i { + switch v := v.(*StopIngestionJobResponse); i { case 0: return &v.state case 1: @@ -2296,7 +2528,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeatureSetsRequest_Filter); i { + switch v := v.(*GetFeatureStatisticsRequest); i { case 0: return &v.state case 1: @@ -2308,7 +2540,7 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresRequest_Filter); i { + switch v := v.(*GetFeatureStatisticsResponse); i { case 0: return &v.state case 1: @@ -2320,6 +2552,42 @@ func file_feast_core_CoreService_proto_init() { } } file_feast_core_CoreService_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListFeatureSetsRequest_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_feast_core_CoreService_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListFeaturesRequest_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_feast_core_CoreService_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListStoresRequest_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_feast_core_CoreService_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListIngestionJobsRequest_Filter); i { case 0: return &v.state @@ -2338,7 +2606,7 @@ func file_feast_core_CoreService_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_feast_core_CoreService_proto_rawDesc, NumEnums: 2, - NumMessages: 29, + NumMessages: 35, NumExtensions: 0, NumServices: 1, }, @@ -2376,6 +2644,11 @@ type CoreServiceClient interface { // If no filter is provided in the request, the response will contain all the feature // sets currently stored in the registry. ListFeatureSets(ctx context.Context, in *ListFeatureSetsRequest, opts ...grpc.CallOption) (*ListFeatureSetsResponse, error) + // Returns all feature references and respective features matching that filter. If none are found + // an empty map will be returned + // If no filter is provided in the request, the response will contain all the features + // currently stored in the default project. + ListFeatures(ctx context.Context, in *ListFeaturesRequest, opts ...grpc.CallOption) (*ListFeaturesResponse, error) // Get feature statistics computed over the data in the batch stores. // // Returns a dataset containing TFDV statistics mapped to each valid historical store. @@ -2462,6 +2735,15 @@ func (c *coreServiceClient) ListFeatureSets(ctx context.Context, in *ListFeature return out, nil } +func (c *coreServiceClient) ListFeatures(ctx context.Context, in *ListFeaturesRequest, opts ...grpc.CallOption) (*ListFeaturesResponse, error) { + out := new(ListFeaturesResponse) + err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListFeatures", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *coreServiceClient) GetFeatureStatistics(ctx context.Context, in *GetFeatureStatisticsRequest, opts ...grpc.CallOption) (*GetFeatureStatisticsResponse, error) { out := new(GetFeatureStatisticsResponse) err := c.cc.Invoke(ctx, "/feast.core.CoreService/GetFeatureStatistics", in, out, opts...) @@ -2565,6 +2847,11 @@ type CoreServiceServer interface { // If no filter is provided in the request, the response will contain all the feature // sets currently stored in the registry. ListFeatureSets(context.Context, *ListFeatureSetsRequest) (*ListFeatureSetsResponse, error) + // Returns all feature references and respective features matching that filter. If none are found + // an empty map will be returned + // If no filter is provided in the request, the response will contain all the features + // currently stored in the default project. + ListFeatures(context.Context, *ListFeaturesRequest) (*ListFeaturesResponse, error) // Get feature statistics computed over the data in the batch stores. // // Returns a dataset containing TFDV statistics mapped to each valid historical store. @@ -2629,6 +2916,9 @@ func (*UnimplementedCoreServiceServer) GetFeatureSet(context.Context, *GetFeatur func (*UnimplementedCoreServiceServer) ListFeatureSets(context.Context, *ListFeatureSetsRequest) (*ListFeatureSetsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListFeatureSets not implemented") } +func (*UnimplementedCoreServiceServer) ListFeatures(context.Context, *ListFeaturesRequest) (*ListFeaturesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListFeatures not implemented") +} func (*UnimplementedCoreServiceServer) GetFeatureStatistics(context.Context, *GetFeatureStatisticsRequest) (*GetFeatureStatisticsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetFeatureStatistics not implemented") } @@ -2718,6 +3008,24 @@ func _CoreService_ListFeatureSets_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _CoreService_ListFeatures_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListFeaturesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoreServiceServer).ListFeatures(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/feast.core.CoreService/ListFeatures", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoreServiceServer).ListFeatures(ctx, req.(*ListFeaturesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _CoreService_GetFeatureStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetFeatureStatisticsRequest) if err := dec(in); err != nil { @@ -2914,6 +3222,10 @@ var _CoreService_serviceDesc = grpc.ServiceDesc{ MethodName: "ListFeatureSets", Handler: _CoreService_ListFeatureSets_Handler, }, + { + MethodName: "ListFeatures", + Handler: _CoreService_ListFeatures_Handler, + }, { MethodName: "GetFeatureStatistics", Handler: _CoreService_GetFeatureStatistics_Handler, diff --git a/sdk/go/protos/feast/core/FeatureSet.pb.go b/sdk/go/protos/feast/core/FeatureSet.pb.go index acd111614d2..b43b9f4ea77 100644 --- a/sdk/go/protos/feast/core/FeatureSet.pb.go +++ b/sdk/go/protos/feast/core/FeatureSet.pb.go @@ -97,6 +97,52 @@ func (FeatureSetStatus) EnumDescriptor() ([]byte, []int) { return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{0} } +type FeatureSetJobDeliveryStatus int32 + +const ( + FeatureSetJobDeliveryStatus_STATUS_IN_PROGRESS FeatureSetJobDeliveryStatus = 0 + FeatureSetJobDeliveryStatus_STATUS_DELIVERED FeatureSetJobDeliveryStatus = 1 +) + +// Enum value maps for FeatureSetJobDeliveryStatus. +var ( + FeatureSetJobDeliveryStatus_name = map[int32]string{ + 0: "STATUS_IN_PROGRESS", + 1: "STATUS_DELIVERED", + } + FeatureSetJobDeliveryStatus_value = map[string]int32{ + "STATUS_IN_PROGRESS": 0, + "STATUS_DELIVERED": 1, + } +) + +func (x FeatureSetJobDeliveryStatus) Enum() *FeatureSetJobDeliveryStatus { + p := new(FeatureSetJobDeliveryStatus) + *p = x + return p +} + +func (x FeatureSetJobDeliveryStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FeatureSetJobDeliveryStatus) Descriptor() protoreflect.EnumDescriptor { + return file_feast_core_FeatureSet_proto_enumTypes[1].Descriptor() +} + +func (FeatureSetJobDeliveryStatus) Type() protoreflect.EnumType { + return &file_feast_core_FeatureSet_proto_enumTypes[1] +} + +func (x FeatureSetJobDeliveryStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FeatureSetJobDeliveryStatus.Descriptor instead. +func (FeatureSetJobDeliveryStatus) EnumDescriptor() ([]byte, []int) { + return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{1} +} + type FeatureSet struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -179,6 +225,9 @@ type FeatureSetSpec struct { Source *Source `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` // User defined metadata Labels map[string]string `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Read-only self-incrementing version that increases monotonically + // when changes are made to a feature set + Version int32 `protobuf:"varint,9,opt,name=version,proto3" json:"version,omitempty"` } func (x *FeatureSetSpec) Reset() { @@ -262,6 +311,13 @@ func (x *FeatureSetSpec) GetLabels() map[string]string { return nil } +func (x *FeatureSetSpec) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + type EntitySpec struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -746,7 +802,7 @@ var file_feast_core_FeatureSet_proto_rawDesc = []byte{ 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x88, 0x03, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xa2, 0x03, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, @@ -766,129 +822,136 @@ var file_feast_core_FeatureSet_proto_rawDesc = []byte{ 0x3e, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, - 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x22, 0x5c, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, - 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa0, - 0x0b, 0x0a, 0x0b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, - 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3b, - 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x45, 0x0a, 0x08, 0x70, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6e, + 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x5c, 0x0a, 0x0a, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa0, 0x0b, 0x0a, 0x0b, 0x46, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, + 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, + 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, + 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, + 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, + 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0e, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x1f, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, + 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x57, 0x69, 0x74, + 0x68, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x68, 0x61, + 0x70, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, + 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, + 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x48, 0x01, 0x52, 0x05, + 0x73, 0x68, 0x61, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, - 0x6e, 0x63, 0x65, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, - 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, - 0x3a, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x70, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, - 0x70, 0x65, 0x48, 0x01, 0x52, 0x05, 0x73, 0x68, 0x61, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x48, 0x01, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x22, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, - 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x74, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x12, 0x48, 0x0a, 0x0c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x45, 0x0a, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x48, 0x02, 0x52, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, - 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, - 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x67, 0x0a, 0x17, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, - 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x15, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, + 0x2e, 0x76, 0x30, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x48, 0x01, + 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x06, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, - 0x02, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, - 0x0a, 0x0a, 0x6d, 0x69, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x49, 0x44, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x6d, 0x69, 0x64, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x75, 0x72, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x55, 0x52, 0x4c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x75, 0x72, 0x6c, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x45, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, + 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, + 0x09, 0x69, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x64, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, - 0x02, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x56, 0x0a, - 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x42, 0x16, 0x0a, 0x14, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x70, - 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x11, 0x10, - 0x1e, 0x22, 0x8f, 0x01, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x4d, 0x65, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x34, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x2a, 0x65, 0x0a, 0x10, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, - 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, - 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x42, 0x58, 0x0a, 0x10, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, - 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, - 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x12, 0x45, 0x0a, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, + 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, + 0x42, 0x6f, 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x62, 0x6f, + 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x67, 0x0a, 0x17, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, + 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, + 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, + 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x15, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, + 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, + 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x29, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, + 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x69, 0x6d, 0x61, + 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x6d, 0x69, 0x64, 0x5f, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, + 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x49, 0x44, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, + 0x02, 0x52, 0x09, 0x6d, 0x69, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, + 0x75, 0x72, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x55, 0x52, 0x4c, 0x44, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x75, 0x72, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x12, 0x45, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, + 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, + 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x74, 0x69, 0x6d, + 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x56, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, + 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0f, + 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, + 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x70, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, + 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x4a, + 0x04, 0x08, 0x03, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x11, 0x10, 0x1e, 0x22, 0x8f, 0x01, 0x0a, 0x0e, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x47, + 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x65, 0x0a, + 0x10, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, + 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, + 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x41, + 0x44, 0x59, 0x10, 0x02, 0x2a, 0x4b, 0x0a, 0x1b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, + 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, + 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x45, 0x44, 0x10, + 0x01, 0x42, 0x58, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, + 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -903,64 +966,65 @@ func file_feast_core_FeatureSet_proto_rawDescGZIP() []byte { return file_feast_core_FeatureSet_proto_rawDescData } -var file_feast_core_FeatureSet_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_feast_core_FeatureSet_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_feast_core_FeatureSet_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_feast_core_FeatureSet_proto_goTypes = []interface{}{ (FeatureSetStatus)(0), // 0: feast.core.FeatureSetStatus - (*FeatureSet)(nil), // 1: feast.core.FeatureSet - (*FeatureSetSpec)(nil), // 2: feast.core.FeatureSetSpec - (*EntitySpec)(nil), // 3: feast.core.EntitySpec - (*FeatureSpec)(nil), // 4: feast.core.FeatureSpec - (*FeatureSetMeta)(nil), // 5: feast.core.FeatureSetMeta - nil, // 6: feast.core.FeatureSetSpec.LabelsEntry - nil, // 7: feast.core.FeatureSpec.LabelsEntry - (*duration.Duration)(nil), // 8: google.protobuf.Duration - (*Source)(nil), // 9: feast.core.Source - (types.ValueType_Enum)(0), // 10: feast.types.ValueType.Enum - (*v0.FeaturePresence)(nil), // 11: tensorflow.metadata.v0.FeaturePresence - (*v0.FeaturePresenceWithinGroup)(nil), // 12: tensorflow.metadata.v0.FeaturePresenceWithinGroup - (*v0.FixedShape)(nil), // 13: tensorflow.metadata.v0.FixedShape - (*v0.ValueCount)(nil), // 14: tensorflow.metadata.v0.ValueCount - (*v0.IntDomain)(nil), // 15: tensorflow.metadata.v0.IntDomain - (*v0.FloatDomain)(nil), // 16: tensorflow.metadata.v0.FloatDomain - (*v0.StringDomain)(nil), // 17: tensorflow.metadata.v0.StringDomain - (*v0.BoolDomain)(nil), // 18: tensorflow.metadata.v0.BoolDomain - (*v0.StructDomain)(nil), // 19: tensorflow.metadata.v0.StructDomain - (*v0.NaturalLanguageDomain)(nil), // 20: tensorflow.metadata.v0.NaturalLanguageDomain - (*v0.ImageDomain)(nil), // 21: tensorflow.metadata.v0.ImageDomain - (*v0.MIDDomain)(nil), // 22: tensorflow.metadata.v0.MIDDomain - (*v0.URLDomain)(nil), // 23: tensorflow.metadata.v0.URLDomain - (*v0.TimeDomain)(nil), // 24: tensorflow.metadata.v0.TimeDomain - (*v0.TimeOfDayDomain)(nil), // 25: tensorflow.metadata.v0.TimeOfDayDomain - (*timestamp.Timestamp)(nil), // 26: google.protobuf.Timestamp + (FeatureSetJobDeliveryStatus)(0), // 1: feast.core.FeatureSetJobDeliveryStatus + (*FeatureSet)(nil), // 2: feast.core.FeatureSet + (*FeatureSetSpec)(nil), // 3: feast.core.FeatureSetSpec + (*EntitySpec)(nil), // 4: feast.core.EntitySpec + (*FeatureSpec)(nil), // 5: feast.core.FeatureSpec + (*FeatureSetMeta)(nil), // 6: feast.core.FeatureSetMeta + nil, // 7: feast.core.FeatureSetSpec.LabelsEntry + nil, // 8: feast.core.FeatureSpec.LabelsEntry + (*duration.Duration)(nil), // 9: google.protobuf.Duration + (*Source)(nil), // 10: feast.core.Source + (types.ValueType_Enum)(0), // 11: feast.types.ValueType.Enum + (*v0.FeaturePresence)(nil), // 12: tensorflow.metadata.v0.FeaturePresence + (*v0.FeaturePresenceWithinGroup)(nil), // 13: tensorflow.metadata.v0.FeaturePresenceWithinGroup + (*v0.FixedShape)(nil), // 14: tensorflow.metadata.v0.FixedShape + (*v0.ValueCount)(nil), // 15: tensorflow.metadata.v0.ValueCount + (*v0.IntDomain)(nil), // 16: tensorflow.metadata.v0.IntDomain + (*v0.FloatDomain)(nil), // 17: tensorflow.metadata.v0.FloatDomain + (*v0.StringDomain)(nil), // 18: tensorflow.metadata.v0.StringDomain + (*v0.BoolDomain)(nil), // 19: tensorflow.metadata.v0.BoolDomain + (*v0.StructDomain)(nil), // 20: tensorflow.metadata.v0.StructDomain + (*v0.NaturalLanguageDomain)(nil), // 21: tensorflow.metadata.v0.NaturalLanguageDomain + (*v0.ImageDomain)(nil), // 22: tensorflow.metadata.v0.ImageDomain + (*v0.MIDDomain)(nil), // 23: tensorflow.metadata.v0.MIDDomain + (*v0.URLDomain)(nil), // 24: tensorflow.metadata.v0.URLDomain + (*v0.TimeDomain)(nil), // 25: tensorflow.metadata.v0.TimeDomain + (*v0.TimeOfDayDomain)(nil), // 26: tensorflow.metadata.v0.TimeOfDayDomain + (*timestamp.Timestamp)(nil), // 27: google.protobuf.Timestamp } var file_feast_core_FeatureSet_proto_depIdxs = []int32{ - 2, // 0: feast.core.FeatureSet.spec:type_name -> feast.core.FeatureSetSpec - 5, // 1: feast.core.FeatureSet.meta:type_name -> feast.core.FeatureSetMeta - 3, // 2: feast.core.FeatureSetSpec.entities:type_name -> feast.core.EntitySpec - 4, // 3: feast.core.FeatureSetSpec.features:type_name -> feast.core.FeatureSpec - 8, // 4: feast.core.FeatureSetSpec.max_age:type_name -> google.protobuf.Duration - 9, // 5: feast.core.FeatureSetSpec.source:type_name -> feast.core.Source - 6, // 6: feast.core.FeatureSetSpec.labels:type_name -> feast.core.FeatureSetSpec.LabelsEntry - 10, // 7: feast.core.EntitySpec.value_type:type_name -> feast.types.ValueType.Enum - 10, // 8: feast.core.FeatureSpec.value_type:type_name -> feast.types.ValueType.Enum - 7, // 9: feast.core.FeatureSpec.labels:type_name -> feast.core.FeatureSpec.LabelsEntry - 11, // 10: feast.core.FeatureSpec.presence:type_name -> tensorflow.metadata.v0.FeaturePresence - 12, // 11: feast.core.FeatureSpec.group_presence:type_name -> tensorflow.metadata.v0.FeaturePresenceWithinGroup - 13, // 12: feast.core.FeatureSpec.shape:type_name -> tensorflow.metadata.v0.FixedShape - 14, // 13: feast.core.FeatureSpec.value_count:type_name -> tensorflow.metadata.v0.ValueCount - 15, // 14: feast.core.FeatureSpec.int_domain:type_name -> tensorflow.metadata.v0.IntDomain - 16, // 15: feast.core.FeatureSpec.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain - 17, // 16: feast.core.FeatureSpec.string_domain:type_name -> tensorflow.metadata.v0.StringDomain - 18, // 17: feast.core.FeatureSpec.bool_domain:type_name -> tensorflow.metadata.v0.BoolDomain - 19, // 18: feast.core.FeatureSpec.struct_domain:type_name -> tensorflow.metadata.v0.StructDomain - 20, // 19: feast.core.FeatureSpec.natural_language_domain:type_name -> tensorflow.metadata.v0.NaturalLanguageDomain - 21, // 20: feast.core.FeatureSpec.image_domain:type_name -> tensorflow.metadata.v0.ImageDomain - 22, // 21: feast.core.FeatureSpec.mid_domain:type_name -> tensorflow.metadata.v0.MIDDomain - 23, // 22: feast.core.FeatureSpec.url_domain:type_name -> tensorflow.metadata.v0.URLDomain - 24, // 23: feast.core.FeatureSpec.time_domain:type_name -> tensorflow.metadata.v0.TimeDomain - 25, // 24: feast.core.FeatureSpec.time_of_day_domain:type_name -> tensorflow.metadata.v0.TimeOfDayDomain - 26, // 25: feast.core.FeatureSetMeta.created_timestamp:type_name -> google.protobuf.Timestamp + 3, // 0: feast.core.FeatureSet.spec:type_name -> feast.core.FeatureSetSpec + 6, // 1: feast.core.FeatureSet.meta:type_name -> feast.core.FeatureSetMeta + 4, // 2: feast.core.FeatureSetSpec.entities:type_name -> feast.core.EntitySpec + 5, // 3: feast.core.FeatureSetSpec.features:type_name -> feast.core.FeatureSpec + 9, // 4: feast.core.FeatureSetSpec.max_age:type_name -> google.protobuf.Duration + 10, // 5: feast.core.FeatureSetSpec.source:type_name -> feast.core.Source + 7, // 6: feast.core.FeatureSetSpec.labels:type_name -> feast.core.FeatureSetSpec.LabelsEntry + 11, // 7: feast.core.EntitySpec.value_type:type_name -> feast.types.ValueType.Enum + 11, // 8: feast.core.FeatureSpec.value_type:type_name -> feast.types.ValueType.Enum + 8, // 9: feast.core.FeatureSpec.labels:type_name -> feast.core.FeatureSpec.LabelsEntry + 12, // 10: feast.core.FeatureSpec.presence:type_name -> tensorflow.metadata.v0.FeaturePresence + 13, // 11: feast.core.FeatureSpec.group_presence:type_name -> tensorflow.metadata.v0.FeaturePresenceWithinGroup + 14, // 12: feast.core.FeatureSpec.shape:type_name -> tensorflow.metadata.v0.FixedShape + 15, // 13: feast.core.FeatureSpec.value_count:type_name -> tensorflow.metadata.v0.ValueCount + 16, // 14: feast.core.FeatureSpec.int_domain:type_name -> tensorflow.metadata.v0.IntDomain + 17, // 15: feast.core.FeatureSpec.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain + 18, // 16: feast.core.FeatureSpec.string_domain:type_name -> tensorflow.metadata.v0.StringDomain + 19, // 17: feast.core.FeatureSpec.bool_domain:type_name -> tensorflow.metadata.v0.BoolDomain + 20, // 18: feast.core.FeatureSpec.struct_domain:type_name -> tensorflow.metadata.v0.StructDomain + 21, // 19: feast.core.FeatureSpec.natural_language_domain:type_name -> tensorflow.metadata.v0.NaturalLanguageDomain + 22, // 20: feast.core.FeatureSpec.image_domain:type_name -> tensorflow.metadata.v0.ImageDomain + 23, // 21: feast.core.FeatureSpec.mid_domain:type_name -> tensorflow.metadata.v0.MIDDomain + 24, // 22: feast.core.FeatureSpec.url_domain:type_name -> tensorflow.metadata.v0.URLDomain + 25, // 23: feast.core.FeatureSpec.time_domain:type_name -> tensorflow.metadata.v0.TimeDomain + 26, // 24: feast.core.FeatureSpec.time_of_day_domain:type_name -> tensorflow.metadata.v0.TimeOfDayDomain + 27, // 25: feast.core.FeatureSetMeta.created_timestamp:type_name -> google.protobuf.Timestamp 0, // 26: feast.core.FeatureSetMeta.status:type_name -> feast.core.FeatureSetStatus 27, // [27:27] is the sub-list for method output_type 27, // [27:27] is the sub-list for method input_type @@ -1060,7 +1124,7 @@ func file_feast_core_FeatureSet_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_feast_core_FeatureSet_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 7, NumExtensions: 0, NumServices: 0, diff --git a/sdk/go/protos/feast/core/IngestionJob.pb.go b/sdk/go/protos/feast/core/IngestionJob.pb.go index a54b23c4498..c8d3478ac9a 100644 --- a/sdk/go/protos/feast/core/IngestionJob.pb.go +++ b/sdk/go/protos/feast/core/IngestionJob.pb.go @@ -212,6 +212,128 @@ func (x *IngestionJob) GetStore() *Store { return nil } +// Config for bi-directional communication channel between Core Service and Ingestion Job +type SpecsStreamingUpdateConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // out-channel for publishing new FeatureSetSpecs (by Core). + // IngestionJob use it as source of existing FeatureSetSpecs and new real-time updates + Source *KafkaSourceConfig `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` + // ack-channel for sending acknowledgments when new FeatureSetSpecs is installed in Job + Ack *KafkaSourceConfig `protobuf:"bytes,2,opt,name=ack,proto3" json:"ack,omitempty"` +} + +func (x *SpecsStreamingUpdateConfig) Reset() { + *x = SpecsStreamingUpdateConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_feast_core_IngestionJob_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpecsStreamingUpdateConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpecsStreamingUpdateConfig) ProtoMessage() {} + +func (x *SpecsStreamingUpdateConfig) ProtoReflect() protoreflect.Message { + mi := &file_feast_core_IngestionJob_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SpecsStreamingUpdateConfig.ProtoReflect.Descriptor instead. +func (*SpecsStreamingUpdateConfig) Descriptor() ([]byte, []int) { + return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{1} +} + +func (x *SpecsStreamingUpdateConfig) GetSource() *KafkaSourceConfig { + if x != nil { + return x.Source + } + return nil +} + +func (x *SpecsStreamingUpdateConfig) GetAck() *KafkaSourceConfig { + if x != nil { + return x.Ack + } + return nil +} + +type FeatureSetSpecAck struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FeatureSetReference string `protobuf:"bytes,1,opt,name=feature_set_reference,json=featureSetReference,proto3" json:"feature_set_reference,omitempty"` + FeatureSetVersion int32 `protobuf:"varint,2,opt,name=feature_set_version,json=featureSetVersion,proto3" json:"feature_set_version,omitempty"` + JobName string `protobuf:"bytes,3,opt,name=job_name,json=jobName,proto3" json:"job_name,omitempty"` +} + +func (x *FeatureSetSpecAck) Reset() { + *x = FeatureSetSpecAck{} + if protoimpl.UnsafeEnabled { + mi := &file_feast_core_IngestionJob_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FeatureSetSpecAck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FeatureSetSpecAck) ProtoMessage() {} + +func (x *FeatureSetSpecAck) ProtoReflect() protoreflect.Message { + mi := &file_feast_core_IngestionJob_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FeatureSetSpecAck.ProtoReflect.Descriptor instead. +func (*FeatureSetSpecAck) Descriptor() ([]byte, []int) { + return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{2} +} + +func (x *FeatureSetSpecAck) GetFeatureSetReference() string { + if x != nil { + return x.FeatureSetReference + } + return "" +} + +func (x *FeatureSetSpecAck) GetFeatureSetVersion() int32 { + if x != nil { + return x.FeatureSetVersion + } + return 0 +} + +func (x *FeatureSetSpecAck) GetJobName() string { + if x != nil { + return x.JobName + } + return "" +} + var File_feast_core_IngestionJob_proto protoreflect.FileDescriptor var file_feast_core_IngestionJob_proto_rawDesc = []byte{ @@ -239,22 +361,40 @@ var file_feast_core_IngestionJob_proto_rawDesc = []byte{ 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x2a, 0x8f, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, - 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, - 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, - 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0b, - 0x0a, 0x07, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, - 0x44, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, - 0x44, 0x45, 0x44, 0x10, 0x08, 0x42, 0x5a, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x11, 0x49, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, - 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, - 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x72, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x1a, 0x53, 0x70, 0x65, 0x63, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x03, 0x61, 0x63, 0x6b, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x22, 0x92, 0x01, 0x0a, 0x11, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x41, 0x63, 0x6b, + 0x12, 0x32, 0x0a, 0x15, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x13, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, + 0x73, 0x65, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x11, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x2a, + 0x8f, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, + 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0d, 0x0a, + 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, + 0x41, 0x42, 0x4f, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x42, + 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, + 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x10, + 0x08, 0x42, 0x5a, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x11, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x6f, 0x62, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -270,24 +410,29 @@ func file_feast_core_IngestionJob_proto_rawDescGZIP() []byte { } var file_feast_core_IngestionJob_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_core_IngestionJob_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_feast_core_IngestionJob_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_feast_core_IngestionJob_proto_goTypes = []interface{}{ - (IngestionJobStatus)(0), // 0: feast.core.IngestionJobStatus - (*IngestionJob)(nil), // 1: feast.core.IngestionJob - (*FeatureSet)(nil), // 2: feast.core.FeatureSet - (*Source)(nil), // 3: feast.core.Source - (*Store)(nil), // 4: feast.core.Store + (IngestionJobStatus)(0), // 0: feast.core.IngestionJobStatus + (*IngestionJob)(nil), // 1: feast.core.IngestionJob + (*SpecsStreamingUpdateConfig)(nil), // 2: feast.core.SpecsStreamingUpdateConfig + (*FeatureSetSpecAck)(nil), // 3: feast.core.FeatureSetSpecAck + (*FeatureSet)(nil), // 4: feast.core.FeatureSet + (*Source)(nil), // 5: feast.core.Source + (*Store)(nil), // 6: feast.core.Store + (*KafkaSourceConfig)(nil), // 7: feast.core.KafkaSourceConfig } var file_feast_core_IngestionJob_proto_depIdxs = []int32{ 0, // 0: feast.core.IngestionJob.status:type_name -> feast.core.IngestionJobStatus - 2, // 1: feast.core.IngestionJob.feature_sets:type_name -> feast.core.FeatureSet - 3, // 2: feast.core.IngestionJob.source:type_name -> feast.core.Source - 4, // 3: feast.core.IngestionJob.store:type_name -> feast.core.Store - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 4, // 1: feast.core.IngestionJob.feature_sets:type_name -> feast.core.FeatureSet + 5, // 2: feast.core.IngestionJob.source:type_name -> feast.core.Source + 6, // 3: feast.core.IngestionJob.store:type_name -> feast.core.Store + 7, // 4: feast.core.SpecsStreamingUpdateConfig.source:type_name -> feast.core.KafkaSourceConfig + 7, // 5: feast.core.SpecsStreamingUpdateConfig.ack:type_name -> feast.core.KafkaSourceConfig + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_feast_core_IngestionJob_proto_init() } @@ -311,6 +456,30 @@ func file_feast_core_IngestionJob_proto_init() { return nil } } + file_feast_core_IngestionJob_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpecsStreamingUpdateConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_feast_core_IngestionJob_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FeatureSetSpecAck); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -318,7 +487,7 @@ func file_feast_core_IngestionJob_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_feast_core_IngestionJob_proto_rawDesc, NumEnums: 1, - NumMessages: 1, + NumMessages: 3, NumExtensions: 0, NumServices: 0, }, diff --git a/sdk/go/protos/feast/core/Store.pb.go b/sdk/go/protos/feast/core/Store.pb.go index 829e2e7c180..9a339a6b173 100644 --- a/sdk/go/protos/feast/core/Store.pb.go +++ b/sdk/go/protos/feast/core/Store.pb.go @@ -598,6 +598,8 @@ type Store_Subscription struct { // - my-feature-set* can be used to match all features prefixed by "my-feature-set" // - my-feature-set-6 can be used to select a single feature set Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // All matches with exclude enabled will be filtered out instead of added + Exclude bool `protobuf:"varint,4,opt,name=exclude,proto3" json:"exclude,omitempty"` } func (x *Store_Subscription) Reset() { @@ -646,12 +648,19 @@ func (x *Store_Subscription) GetName() string { return "" } +func (x *Store_Subscription) GetExclude() bool { + if x != nil { + return x.Exclude + } + return false +} + var File_feast_core_Store_proto protoreflect.FileDescriptor var file_feast_core_Store_proto_rawDesc = []byte{ 0x0a, 0x16, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x22, 0x81, 0x0a, 0x0a, 0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, + 0x63, 0x6f, 0x72, 0x65, 0x22, 0x9b, 0x0a, 0x0a, 0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, @@ -721,23 +730,24 @@ var file_feast_core_Store_proto_rawDesc = []byte{ 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x4d, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x52, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x42, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x5c, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x53, 0x0a, 0x09, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x44, 0x49, 0x53, 0x10, 0x01, 0x12, 0x0c, - 0x0a, 0x08, 0x42, 0x49, 0x47, 0x51, 0x55, 0x45, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, - 0x43, 0x41, 0x53, 0x53, 0x41, 0x4e, 0x44, 0x52, 0x41, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, - 0x45, 0x44, 0x49, 0x53, 0x5f, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x10, 0x04, 0x42, 0x08, - 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x53, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0a, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4a, 0x04, 0x08, + 0x02, 0x10, 0x03, 0x22, 0x53, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, + 0x05, 0x52, 0x45, 0x44, 0x49, 0x53, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x49, 0x47, 0x51, + 0x55, 0x45, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x41, 0x53, 0x53, 0x41, 0x4e, + 0x44, 0x52, 0x41, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x43, + 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x10, 0x04, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x42, 0x53, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, + 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/sdk/go/protos/feast/serving/ServingService.pb.go b/sdk/go/protos/feast/serving/ServingService.pb.go index c8b09a352b5..50e2f3fe2b6 100644 --- a/sdk/go/protos/feast/serving/ServingService.pb.go +++ b/sdk/go/protos/feast/serving/ServingService.pb.go @@ -495,6 +495,10 @@ type GetOnlineFeaturesRequest struct { // Option to omit entities from the response. If true, only feature // values will be returned. OmitEntitiesInResponse bool `protobuf:"varint,3,opt,name=omit_entities_in_response,json=omitEntitiesInResponse,proto3" json:"omit_entities_in_response,omitempty"` + // Optional field to specify project name override. If specified, uses the + // given project for retrieval. Overrides the projects specified in + // Feature References if both are specified. + Project string `protobuf:"bytes,5,opt,name=project,proto3" json:"project,omitempty"` } func (x *GetOnlineFeaturesRequest) Reset() { @@ -550,6 +554,13 @@ func (x *GetOnlineFeaturesRequest) GetOmitEntitiesInResponse() bool { return false } +func (x *GetOnlineFeaturesRequest) GetProject() string { + if x != nil { + return x.Project + } + return "" +} + type GetOnlineFeaturesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1161,7 +1172,7 @@ var file_feast_serving_ServingService_proto_rawDesc = []byte{ 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x4a, - 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xe1, 0x03, 0x0a, 0x18, + 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xfb, 0x03, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x61, @@ -1176,162 +1187,164 @@ var file_feast_serving_ServingService_proto_rawDesc = []byte{ 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6f, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0xf8, 0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x6f, 0x77, 0x12, 0x45, 0x0a, 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x55, 0x0a, 0x06, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x2e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x1a, 0x4d, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xdd, 0x04, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, - 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0xf8, + 0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x12, 0x45, 0x0a, 0x10, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x55, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x89, 0x03, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x12, 0x5e, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, - 0x1a, 0x4d, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, - 0x71, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x34, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x5b, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, - 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4e, - 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, - 0x54, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x41, 0x47, 0x45, 0x10, 0x04, 0x22, - 0x9b, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, - 0x73, 0x65, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0d, - 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x40, 0x0a, - 0x18, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, 0x62, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, - 0x35, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, - 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0x36, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0xe2, - 0x01, 0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, - 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x69, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, - 0x69, 0x6c, 0x65, 0x55, 0x72, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, - 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x0d, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, - 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x1a, 0x65, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x69, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x72, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x0b, - 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x64, 0x61, - 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, - 0x73, 0x65, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2a, 0x6f, 0x0a, 0x10, 0x46, 0x65, - 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, - 0x0a, 0x1a, 0x46, 0x45, 0x41, 0x53, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x1d, - 0x0a, 0x19, 0x46, 0x45, 0x41, 0x53, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, - 0x18, 0x46, 0x45, 0x41, 0x53, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x07, 0x4a, - 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, - 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, - 0x44, 0x10, 0x01, 0x2a, 0x68, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, 0x42, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, - 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, - 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x4f, 0x42, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x2a, 0x3b, 0x0a, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x13, 0x44, - 0x41, 0x54, 0x41, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x46, 0x4f, 0x52, - 0x4d, 0x41, 0x54, 0x5f, 0x41, 0x56, 0x52, 0x4f, 0x10, 0x01, 0x32, 0x92, 0x03, 0x0a, 0x0e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6c, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x12, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x4d, 0x0a, 0x0b, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x04, 0x0a, 0x19, 0x47, 0x65, + 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, + 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x1a, 0x89, 0x03, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x12, 0x58, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x40, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, - 0x6f, 0x62, 0x12, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, - 0x2e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x5e, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x41, - 0x50, 0x49, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x5e, 0x0a, 0x08, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, + 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x1a, 0x4d, 0x0a, 0x0b, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x71, 0x0a, 0x0d, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x66, 0x65, + 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5b, 0x0a, 0x0b, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x53, + 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, + 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, + 0x4e, 0x44, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, 0x54, 0x53, 0x49, 0x44, 0x45, 0x5f, + 0x4d, 0x41, 0x58, 0x5f, 0x41, 0x47, 0x45, 0x10, 0x04, 0x22, 0x9b, 0x01, 0x0a, 0x17, 0x47, 0x65, + 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, + 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, + 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x40, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0x35, 0x0a, 0x0d, 0x47, 0x65, 0x74, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, + 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, + 0x22, 0x36, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, + 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0xe2, 0x01, 0x0a, 0x03, 0x4a, 0x6f, 0x62, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, + 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, + 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x4a, 0x6f, 0x62, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x69, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x72, 0x69, + 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xd4, 0x01, + 0x0a, 0x0d, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x4a, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, + 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0x65, 0x0a, 0x0a, 0x46, + 0x69, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x75, 0x72, 0x69, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x55, 0x72, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x66, 0x65, + 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, + 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2a, 0x6f, 0x0a, 0x10, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x46, 0x45, 0x41, 0x53, + 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x45, 0x41, 0x53, + 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, + 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x45, 0x41, 0x53, 0x54, + 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, + 0x54, 0x43, 0x48, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x14, 0x0a, 0x10, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, + 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01, 0x2a, 0x68, 0x0a, + 0x09, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, + 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, + 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, + 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x2a, 0x3b, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x46, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x46, 0x4f, + 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x14, + 0x0a, 0x10, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x41, 0x56, + 0x52, 0x4f, 0x10, 0x01, 0x32, 0x92, 0x03, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x46, 0x65, + 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, + 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, + 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, + 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, + 0x10, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, + 0x67, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x45, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x12, 0x1c, 0x2e, 0x66, + 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4a, 0x6f, + 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x5e, 0x0a, 0x13, 0x66, 0x65, 0x61, + 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x42, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x41, 0x50, 0x49, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, + 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, + 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, + 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( From 9d0cf1db3612f7819d65359b527cc98e2b2ac706 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 12:48:52 +0800 Subject: [PATCH 05/23] Update Go SDK to use project field and remove strip project code --- go.sum | 1 + sdk/go/client.go | 23 ----------------------- sdk/go/client_test.go | 21 +-------------------- sdk/go/request.go | 32 +++++++++++--------------------- sdk/go/request_test.go | 5 ++--- 5 files changed, 15 insertions(+), 67 deletions(-) diff --git a/go.sum b/go.sum index 50e81322e75..7038e78cbc0 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,7 @@ github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/feast-dev/feast/sdk/go v0.0.0-20200516052424-09ff3dda724c h1:jltCNN1tpaFxCslQtHUfU5u5qodH/D8rqPmxvRWGNWM= github.com/feast-dev/feast/sdk/go v0.0.0-20200516052424-09ff3dda724c/go.mod h1:F3sMDmJ9hxjlh0Z7fM6/atvMJd8moahKxUF1LCzVthQ= +github.com/feast-dev/feast/sdk/go v0.5.0 h1:h4UiFgqeWrw9voPqigwiSYWl/vjUn2mgoUAFIa29s3A= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/getkin/kin-openapi v0.1.1-0.20190507152207-d3180292eead/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= diff --git a/sdk/go/client.go b/sdk/go/client.go index 617c37a6f10..eb9fb5bc81b 100644 --- a/sdk/go/client.go +++ b/sdk/go/client.go @@ -6,7 +6,6 @@ import ( "github.com/opentracing/opentracing-go" "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" "google.golang.org/grpc" "go.opencensus.io/plugin/ocgrpc" @@ -58,28 +57,6 @@ func (fc *GrpcClient) GetOnlineFeatures(ctx context.Context, req *OnlineFeatures entityRefs[ref] = struct{}{} } } - - // strip projects from feature refs recieved - for _, fieldValues := range resp.GetFieldValues() { - stripFields := make(map[string]*types.Value, len(fieldValues.Fields)) - stripStatuses := make(map[string]serving.GetOnlineFeaturesResponse_FieldStatus, len(fieldValues.Statuses)) - for refStr, _ := range fieldValues.Fields { - _, isEntity := entityRefs[refStr] - stripRefStr := refStr - if !isEntity { // is feature ref - featureRef, err := parseFeatureRef(refStr, true) - if err != nil { - return nil, err - } - stripRefStr = toFeatureRefStr(featureRef) - } - - stripFields[stripRefStr] = fieldValues.Fields[refStr] - stripStatuses[stripRefStr] = fieldValues.Statuses[refStr] - } - fieldValues.Fields, fieldValues.Statuses = stripFields, stripStatuses - } - return &OnlineFeaturesResponse{RawResponse: resp}, err } diff --git a/sdk/go/client_test.go b/sdk/go/client_test.go index 49fbe83266c..ab04cdeaa15 100644 --- a/sdk/go/client_test.go +++ b/sdk/go/client_test.go @@ -34,25 +34,6 @@ func TestGetOnlineFeatures(t *testing.T) { }, Project: "driver_project", }, - // check GetOnlineFeatures() should strip projects returned from serving - recieve: OnlineFeaturesResponse{ - RawResponse: &serving.GetOnlineFeaturesResponse{ - FieldValues: []*serving.GetOnlineFeaturesResponse_FieldValues{ - { - Fields: map[string]*types.Value{ - "driver_project/driver:rating": Int64Val(1), - "driver_project/rating": Int64Val(1), - "driver_project/null_value": {}, - }, - Statuses: map[string]serving.GetOnlineFeaturesResponse_FieldStatus{ - "driver_project/driver:rating": serving.GetOnlineFeaturesResponse_PRESENT, - "driver_project/rating": serving.GetOnlineFeaturesResponse_PRESENT, - "driver_project/null_value": serving.GetOnlineFeaturesResponse_NULL_VALUE, - }, - }, - }, - }, - }, want: OnlineFeaturesResponse{ RawResponse: &serving.GetOnlineFeaturesResponse{ FieldValues: []*serving.GetOnlineFeaturesResponse_FieldValues{ @@ -83,7 +64,7 @@ func TestGetOnlineFeatures(t *testing.T) { ctx := context.Background() _, traceCtx := opentracing.StartSpanFromContext(ctx, "get_online_features") rawRequest, _ := tc.req.buildRequest() - resp := tc.recieve.RawResponse + resp := tc.want.RawResponse cli.EXPECT().GetOnlineFeatures(traceCtx, rawRequest).Return(resp, nil).Times(1) client := &GrpcClient{ diff --git a/sdk/go/request.go b/sdk/go/request.go index a11999ae890..010545d6c4e 100644 --- a/sdk/go/request.go +++ b/sdk/go/request.go @@ -23,7 +23,8 @@ type OnlineFeaturesRequest struct { // Entities is the list of entity rows to retrieve features on. Each row is a map of entity name to entity value. Entities []Row - // Project specifies the project would contain the feature sets where the requested features belong to. + // Project optionally specifies the project override. If specified, uses given project for retrieval. + // Overrides the projects specified in Feature References if also specified. Project string // whether to omit the entities fields in the response. @@ -32,7 +33,7 @@ type OnlineFeaturesRequest struct { // Builds the feast-specified request payload from the wrapper. func (r OnlineFeaturesRequest) buildRequest() (*serving.GetOnlineFeaturesRequest, error) { - featureRefs, err := buildFeatureRefs(r.Features, r.Project) + featureRefs, err := buildFeatureRefs(r.Features) if err != nil { return nil, err } @@ -46,30 +47,26 @@ func (r OnlineFeaturesRequest) buildRequest() (*serving.GetOnlineFeaturesRequest } return &serving.GetOnlineFeaturesRequest{ - Features: featureRefs, - EntityRows: entityRows, - OmitEntitiesInResponse: r.OmitEntities, + Features: featureRefs, + EntityRows: entityRows, + OmitEntitiesInResponse: r.OmitEntities, + Project: r.Project, }, nil } // Creates a slice of FeatureReferences from string representation in // the format featureset:feature. // featureRefStrs - string feature references to parse. -// project - Optionally sets the project in parsed FeatureReferences. Otherwise pass "" // Returns parsed FeatureReferences. // Returns an error when the format of the string feature reference is invalid -func buildFeatureRefs(featureRefStrs []string, project string) ([]*serving.FeatureReference, error) { +func buildFeatureRefs(featureRefStrs []string) ([]*serving.FeatureReference, error) { var featureRefs []*serving.FeatureReference for _, featureRefStr := range featureRefStrs { - featureRef, err := parseFeatureRef(featureRefStr, false) + featureRef, err := parseFeatureRef(featureRefStr) if err != nil { return nil, err } - // apply project if specified - if len(project) != 0 { - featureRef.Project = project - } featureRefs = append(featureRefs, featureRef) } return featureRefs, nil @@ -77,23 +74,16 @@ func buildFeatureRefs(featureRefStrs []string, project string) ([]*serving.Featu // Parses a string FeatureReference into FeatureReference proto // featureRefStr - the string feature reference to parse. -// ignoreProject - if true would ignore if project is specified in the given featureRefStr -// Otherwise, would return an error if project is detected in featureRefStr. // Returns parsed FeatureReference. // Returns an error when the format of the string feature reference is invalid -func parseFeatureRef(featureRefStr string, ignoreProject bool) (*serving.FeatureReference, error) { +func parseFeatureRef(featureRefStr string) (*serving.FeatureReference, error) { if len(featureRefStr) == 0 { return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr) } var featureRef serving.FeatureReference if strings.Contains(featureRefStr, "/") { - if ignoreProject { - projectSplit := strings.Split(featureRefStr, "/") - featureRefStr = projectSplit[1] - } else { - return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr) - } + return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr) } // parse featureset if specified if strings.Contains(featureRefStr, ":") { diff --git a/sdk/go/request_test.go b/sdk/go/request_test.go index 70e1f0d8f5e..943fd37fee7 100644 --- a/sdk/go/request_test.go +++ b/sdk/go/request_test.go @@ -34,13 +34,11 @@ func TestGetOnlineFeaturesRequest(t *testing.T) { want: &serving.GetOnlineFeaturesRequest{ Features: []*serving.FeatureReference{ { - Project: "driver_project", FeatureSet: "driver", Name: "driver_id", }, { - Project: "driver_project", - Name: "driver_id", + Name: "driver_id", }, }, EntityRows: []*serving.GetOnlineFeaturesRequest_EntityRow{ @@ -64,6 +62,7 @@ func TestGetOnlineFeaturesRequest(t *testing.T) { }, }, OmitEntitiesInResponse: false, + Project: "driver_project", }, wantErr: false, err: nil, From 2892788538f6bb3bb5b138e30e3d97936f739b6b Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 13:14:43 +0800 Subject: [PATCH 06/23] Update Java SDK to use project and remove strip project code. --- .../java/com/gojek/feast/FeastClient.java | 23 +++++-------- .../java/com/gojek/feast/RequestUtil.java | 29 ++++------------ .../java/com/gojek/feast/FeastClientTest.java | 33 +++++++------------ .../java/com/gojek/feast/RequestUtilTest.java | 17 +++------- 4 files changed, 31 insertions(+), 71 deletions(-) diff --git a/sdk/java/src/main/java/com/gojek/feast/FeastClient.java b/sdk/java/src/main/java/com/gojek/feast/FeastClient.java index 9ac91616847..374db0d2af2 100644 --- a/sdk/java/src/main/java/com/gojek/feast/FeastClient.java +++ b/sdk/java/src/main/java/com/gojek/feast/FeastClient.java @@ -16,7 +16,6 @@ */ package com.gojek.feast; -import feast.common.models.Feature; import feast.proto.serving.ServingAPIProto.FeatureReference; import feast.proto.serving.ServingAPIProto.GetFeastServingInfoRequest; import feast.proto.serving.ServingAPIProto.GetFeastServingInfoResponse; @@ -83,8 +82,8 @@ public List getOnlineFeatures(List featureRefs, List rows) { * featureSet:feature, where 'featureSet' and 'feature' refer to the FeatureSet and Feature * names respectively. Only the Feature name is required. * @param rows list of {@link Row} to select the entities to retrieve the features for - * @param project {@link String} Specifies the project which contains the FeatureSets which the - * Feature requested belong to. + * @param project {@link String} Specifies the project override. If specifed uses the project for + * retrieval. Overrides the projects set in Feature References if also specified. * @return list of {@link Row} containing retrieved data fields. */ public List getOnlineFeatures(List featureRefs, List rows, String project) { @@ -118,7 +117,7 @@ public List getOnlineFeatures(List featureRefs, List rows, Str */ public List getOnlineFeatures( List featureRefs, List rows, String project, boolean omitEntitiesInResponse) { - List features = RequestUtil.createFeatureRefs(featureRefs, project); + List features = RequestUtil.createFeatureRefs(featureRefs); // build entity rows and collect entity references HashSet entityRefs = new HashSet<>(); List entityRows = @@ -138,6 +137,7 @@ public List getOnlineFeatures( GetOnlineFeaturesRequest.newBuilder() .addAllFeatures(features) .addAllEntityRows(entityRows) + .setProject(project) .setOmitEntitiesInResponse(omitEntitiesInResponse) .build()); @@ -146,17 +146,10 @@ public List getOnlineFeatures( fieldValues -> { Row row = Row.create(); for (String fieldName : fieldValues.getFieldsMap().keySet()) { - String stripFieldName = fieldName; - if (!entityRefs.contains(fieldName)) { - // Strip project from string Feature References from returned from serving - FeatureReference featureRef = - RequestUtil.parseFeatureRef(fieldName, true).build(); - stripFieldName = Feature.getFeatureStringRef(featureRef); - row.set( - stripFieldName, - fieldValues.getFieldsMap().get(fieldName), - fieldValues.getStatusesMap().get(fieldName)); - } + row.set( + fieldName, + fieldValues.getFieldsMap().get(fieldName), + fieldValues.getStatusesMap().get(fieldName)); } return row; }) diff --git a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java index 08a2a535737..38a60dd1f90 100644 --- a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java +++ b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java @@ -27,24 +27,17 @@ public class RequestUtil { * Create feature references protos from given string feature reference. * * @param featureRefStrings to create Feature Reference protos from - * @param project specifies to the project set in parsed Feature Reference protos otherwise "" * @return List of parsed {@link FeatureReference} protos */ - public static List createFeatureRefs( - List featureRefStrings, String project) { + public static List createFeatureRefs(List featureRefStrings) { if (featureRefStrings == null) { throw new IllegalArgumentException("featureRefs cannot be null"); } List featureRefs = featureRefStrings.stream() - .map(refStr -> parseFeatureRef(refStr, false)) + .map(refStr -> parseFeatureRef(refStr)) .collect(Collectors.toList()); - // apply project override if specified - if (!project.isEmpty()) { - featureRefs = - featureRefs.stream().map(ref -> ref.setProject(project)).collect(Collectors.toList()); - } return featureRefs.stream().map(ref -> ref.build()).collect(Collectors.toList()); } @@ -53,29 +46,19 @@ public static List createFeatureRefs( * Parse a feature reference proto builder from the given featureRefString * * @param featureRefString string feature reference to parse from. - * @param ignoreProject If true, would ignore if project is specified in given ref string. - * Otherwise, throwws a {@link IllegalArgumentException} if project is specified. * @return a parsed {@link FeatureReference.Builder} */ - public static FeatureReference.Builder parseFeatureRef( - String featureRefString, boolean ignoreProject) { + public static FeatureReference.Builder parseFeatureRef(String featureRefString) { featureRefString = featureRefString.trim(); if (featureRefString.isEmpty()) { throw new IllegalArgumentException("Cannot parse a empty feature reference"); } - FeatureReference.Builder featureRef = FeatureReference.newBuilder(); - - // parse project if specified if (featureRefString.contains("/")) { - if (ignoreProject) { - String[] projectSplit = featureRefString.split("/"); - featureRefString = projectSplit[1]; - } else { - throw new IllegalArgumentException( - String.format("Unsupported feature reference: %s", featureRefString)); - } + throw new IllegalArgumentException( + String.format("Unsupported feature reference: %s", featureRefString)); } + FeatureReference.Builder featureRef = FeatureReference.newBuilder(); // parse featureset if specified if (featureRefString.contains(":")) { String[] featureSetSplit = featureRefString.split(":"); diff --git a/sdk/java/src/test/java/com/gojek/feast/FeastClientTest.java b/sdk/java/src/test/java/com/gojek/feast/FeastClientTest.java index 5cb756f8de6..84d92466571 100644 --- a/sdk/java/src/test/java/com/gojek/feast/FeastClientTest.java +++ b/sdk/java/src/test/java/com/gojek/feast/FeastClientTest.java @@ -118,23 +118,14 @@ public void shouldGetOnlineFeatures() { private static GetOnlineFeaturesRequest getFakeRequest() { // setup mock serving service stub return GetOnlineFeaturesRequest.newBuilder() - .addFeatures( - FeatureReference.newBuilder() - .setProject("driver_project") - .setFeatureSet("driver") - .setName("name") - .build()) - .addFeatures( - FeatureReference.newBuilder().setProject("driver_project").setName("rating").build()) - .addFeatures( - FeatureReference.newBuilder() - .setProject("driver_project") - .setName("null_value") - .build()) + .addFeatures(FeatureReference.newBuilder().setFeatureSet("driver").setName("name").build()) + .addFeatures(FeatureReference.newBuilder().setName("rating").build()) + .addFeatures(FeatureReference.newBuilder().setName("null_value").build()) .addEntityRows( EntityRow.newBuilder() .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) .putFields("driver_id", intValue(1))) + .setProject("driver_project") .build(); } @@ -142,14 +133,14 @@ private static GetOnlineFeaturesResponse getFakeResponse() { return GetOnlineFeaturesResponse.newBuilder() .addFieldValues( FieldValues.newBuilder() - .putFields("driver_project/driver_id", intValue(1)) - .putStatuses("driver_project/driver_id", FieldStatus.PRESENT) - .putFields("driver_project/driver:name", strValue("david")) - .putStatuses("driver_project/driver:name", FieldStatus.PRESENT) - .putFields("driver_project/rating", intValue(3)) - .putStatuses("driver_project/rating", FieldStatus.PRESENT) - .putFields("driver_project/null_value", Value.newBuilder().build()) - .putStatuses("driver_project/null_value", FieldStatus.NULL_VALUE) + .putFields("driver_id", intValue(1)) + .putStatuses("driver_id", FieldStatus.PRESENT) + .putFields("driver:name", strValue("david")) + .putStatuses("driver:name", FieldStatus.PRESENT) + .putFields("rating", intValue(3)) + .putStatuses("rating", FieldStatus.PRESENT) + .putFields("null_value", Value.newBuilder().build()) + .putStatuses("null_value", FieldStatus.NULL_VALUE) .build()) .build(); } diff --git a/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java b/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java index 11e15c6cec3..1148710d5a6 100644 --- a/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java +++ b/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java @@ -40,22 +40,15 @@ private static Stream provideValidFeatureRefs() { Arguments.of( Arrays.asList("driver:driver_id", "driver_id"), Arrays.asList( - FeatureReference.newBuilder() - .setProject("driver_project") - .setFeatureSet("driver") - .setName("driver_id") - .build(), - FeatureReference.newBuilder() - .setProject("driver_project") - .setName("driver_id") - .build()))); + FeatureReference.newBuilder().setFeatureSet("driver").setName("driver_id").build(), + FeatureReference.newBuilder().setName("driver_id").build()))); } @ParameterizedTest @MethodSource("provideValidFeatureRefs") void createFeatureSets_ShouldReturnFeatureSetsForValidFeatureRefs( List input, List expected) { - List actual = RequestUtil.createFeatureRefs(input, "driver_project"); + List actual = RequestUtil.createFeatureRefs(input); // Order of the actual and expected featureSets do no not matter actual.sort(Comparator.comparing(FeatureReference::getName)); expected.sort(Comparator.comparing(FeatureReference::getName)); @@ -90,12 +83,12 @@ private static Stream provideInvalidFeatureRefs() { @ParameterizedTest @MethodSource("provideInvalidFeatureRefs") void createFeatureSets_ShouldThrowExceptionForInvalidFeatureRefs(List input) { - assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, "")); + assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input)); } @ParameterizedTest @NullSource void createFeatureSets_ShouldThrowExceptionForNullFeatureRefs(List input) { - assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, "")); + assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input)); } } From 6f402bd7c78f53ab9d0ddb41009108ff5d7d0ace Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 14:19:08 +0800 Subject: [PATCH 07/23] Fix python lint --- sdk/python/feast/client.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk/python/feast/client.py b/sdk/python/feast/client.py index 8e840b3cb87..4e2c7fb8e11 100644 --- a/sdk/python/feast/client.py +++ b/sdk/python/feast/client.py @@ -689,11 +689,6 @@ def get_online_features( project=project if project is not None else self.project, ) ) - - entity_refs = { - key for entity_row in entity_rows for key in entity_row.fields.keys() - } - except grpc.RpcError as e: raise grpc.RpcError(e.details()) From 271d82e27fdead07740851b29b0e62162189cdd8 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Tue, 23 Jun 2020 14:28:16 +0800 Subject: [PATCH 08/23] Revert ignore project flag in python SDK's FeatureRef.from_str() --- sdk/python/feast/feature.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sdk/python/feast/feature.py b/sdk/python/feast/feature.py index 67d309d0f16..054bf5ecc58 100644 --- a/sdk/python/feast/feature.py +++ b/sdk/python/feast/feature.py @@ -97,13 +97,18 @@ def from_str(cls, feature_ref_str: str, ignore_project: bool = False): Args: feature_ref_str: String representation of the feature reference + ignore_project: Ignore projects in given string feature reference + instead throwing an error Returns: FeatureRef that refers to the given feature """ proto = FeatureRefProto() if "/" in feature_ref_str: - raise ValueError(f"Unsupported feature reference: {feature_ref_str}") + if ignore_project: + _, feature_ref_str = feature_ref_str.split("/") + else: + raise ValueError(f"Unsupported feature reference: {feature_ref_str}") # parse feature set name if specified if ":" in feature_ref_str: From 3aecc8ec97b4a97c1cb4790c0411b9f07b63205f Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 13:58:43 +0800 Subject: [PATCH 09/23] Reorder basic e2e tests to ensure that list features and entities tests do not interfere with otheer tests --- tests/e2e/bq/bq-batch-retrieval.py | 90 ++++++++++++------- tests/e2e/bq/feature-stats.py | 2 +- tests/e2e/conftest.py | 4 +- tests/e2e/redis/basic-ingest-redis-serving.py | 16 ++-- 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/tests/e2e/bq/bq-batch-retrieval.py b/tests/e2e/bq/bq-batch-retrieval.py index 3918f69fb3a..488f1197193 100644 --- a/tests/e2e/bq/bq-batch-retrieval.py +++ b/tests/e2e/bq/bq-batch-retrieval.py @@ -184,7 +184,9 @@ def test_batch_get_batch_features_with_file(client): client.ingest(file_fs1, features_1_df, timeout=480) # Rename column (datetime -> event_timestamp) - features_1_df['datetime'] + pd.Timedelta(seconds=1) # adds buffer to avoid rounding errors + features_1_df["datetime"] + pd.Timedelta( + seconds=1 + ) # adds buffer to avoid rounding errors features_1_df = features_1_df.rename(columns={"datetime": "event_timestamp"}) to_avro( @@ -230,7 +232,9 @@ def test_batch_get_batch_features_with_gs_path(client, gcs_path): client.ingest(gcs_fs1, features_1_df, timeout=360) # Rename column (datetime -> event_timestamp) - features_1_df['datetime'] + pd.Timedelta(seconds=1) # adds buffer to avoid rounding errors + features_1_df["datetime"] + pd.Timedelta( + seconds=1 + ) # adds buffer to avoid rounding errors features_1_df = features_1_df.rename(columns={"datetime": "event_timestamp"}) # Output file to local @@ -342,7 +346,9 @@ def check(): feature_refs=["feature_value4"], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( + by=["entity_id"] + ) print(output.head(10)) assert np.allclose( @@ -352,7 +358,10 @@ def check(): output["additional_string_col"].to_list() == entity_df["additional_string_col"].to_list() ) - assert output["feature_value4"].to_list() == features_df["feature_value4"].to_list() + assert ( + output["feature_value4"].to_list() + == features_df["feature_value4"].to_list() + ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) wait_for(check, timedelta(minutes=5)) @@ -440,10 +449,7 @@ def test_batch_multiple_featureset_joins(client): def check(): feature_retrieval_job = client.get_batch_features( entity_rows=entity_df, - feature_refs=[ - "feature_value6", - "feature_set_2:other_feature_value7", - ], + feature_refs=["feature_value6", "feature_set_2:other_feature_value7",], project=PROJECT_NAME, ) output = feature_retrieval_job.to_dataframe(timeout_sec=180) @@ -453,7 +459,12 @@ def check(): int(i) for i in output["feature_value6"].to_list() ] assert ( +<<<<<<< HEAD output["other_entity_id"].to_list() == output["feature_set_2__other_feature_value7"].to_list() +======= + output["other_entity_id"].to_list() + == output["feature_set_2__other_feature_value7"].to_list() +>>>>>>> Reorder basic e2e tests to ensure that list features and entities tests do not interfere with otheer tests ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) @@ -516,7 +527,11 @@ def infra_teardown(pytestconfig, core_url, serving_url): print("Cleaning up not required") +<<<<<<< HEAD ''' +======= +""" +>>>>>>> Reorder basic e2e tests to ensure that list features and entities tests do not interfere with otheer tests This suite of tests tests the apply feature set - update feature set - retrieve event sequence. It ensures that when a feature set is updated, tombstoned features are no longer retrieved, and added features are null for previously ingested @@ -524,7 +539,8 @@ def infra_teardown(pytestconfig, core_url, serving_url): It is marked separately because of the length of time required to perform this test, due to bigquery schema caching for streaming writes. -''' +""" + @pytest.fixture(scope="module") @@ -563,18 +579,23 @@ def test_update_featureset_apply_featureset_and_ingest_first_subset( def check(): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[:5], - feature_refs=[ - "update_feature1", - "update_feature2", - ], - project=PROJECT_NAME + feature_refs=["update_feature1", "update_feature2",], + project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( + by=["entity_id"] + ) print(output.head()) - assert output["update_feature1"].to_list() == subset_df["update_feature1"].to_list() - assert output["update_feature2"].to_list() == subset_df["update_feature2"].to_list() + assert ( + output["update_feature1"].to_list() + == subset_df["update_feature1"].to_list() + ) + assert ( + output["update_feature2"].to_list() + == subset_df["update_feature2"].to_list() + ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) @@ -621,20 +642,27 @@ def test_update_featureset_update_featureset_and_ingest_second_subset( def check(): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[5:], - feature_refs=[ - "update_feature1", - "update_feature3", - "update_feature4", - ], + feature_refs=["update_feature1", "update_feature3", "update_feature4",], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( + by=["entity_id"] + ) print(output.head()) - assert output["update_feature1"].to_list() == subset_df["update_feature1"].to_list() - assert output["update_feature3"].to_list() == subset_df["update_feature3"].to_list() - assert output["update_feature4"].to_list() == subset_df["update_feature4"].to_list() + assert ( + output["update_feature1"].to_list() + == subset_df["update_feature1"].to_list() + ) + assert ( + output["update_feature3"].to_list() + == subset_df["update_feature3"].to_list() + ) + assert ( + output["update_feature4"].to_list() + == subset_df["update_feature4"].to_list() + ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) wait_for(check, timedelta(minutes=5)) @@ -662,14 +690,12 @@ def test_update_featureset_retrieve_all_fields(client, update_featureset_datafra def test_update_featureset_retrieve_valid_fields(client, update_featureset_dataframe): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]], - feature_refs=[ - "update_feature1", - "update_feature3", - "update_feature4", - ], + feature_refs=["update_feature1", "update_feature3", "update_feature4",], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( + by=["entity_id"] + ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) print(output.head(10)) assert ( diff --git a/tests/e2e/bq/feature-stats.py b/tests/e2e/bq/feature-stats.py index 72778e8f28d..b145f891fe4 100644 --- a/tests/e2e/bq/feature-stats.py +++ b/tests/e2e/bq/feature-stats.py @@ -25,7 +25,7 @@ PROJECT_NAME = "batch_" + uuid.uuid4().hex.upper()[0:6] STORE_NAME = "historical" -os.environ['CUDA_VISIBLE_DEVICES'] = "0" +os.environ["CUDA_VISIBLE_DEVICES"] = "0" @pytest.fixture(scope="module") diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index 89b08023347..392f6501d9b 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -2,5 +2,7 @@ def pytest_addoption(parser): parser.addoption("--core_url", action="store", default="localhost:6565") parser.addoption("--serving_url", action="store", default="localhost:6566") parser.addoption("--allow_dirty", action="store", default="False") - parser.addoption("--gcs_path", action="store", default="gs://feast-templocation-kf-feast/") + parser.addoption( + "--gcs_path", action="store", default="gs://feast-templocation-kf-feast/" + ) parser.addoption("--enable_auth", action="store", default="False") diff --git a/tests/e2e/redis/basic-ingest-redis-serving.py b/tests/e2e/redis/basic-ingest-redis-serving.py index 618cc45d9a1..f3b1dacc621 100644 --- a/tests/e2e/redis/basic-ingest-redis-serving.py +++ b/tests/e2e/redis/basic-ingest-redis-serving.py @@ -125,9 +125,9 @@ def client(core_url, serving_url, allow_dirty, enable_auth): # Get client for core and serving # if enable_auth is True, Google Id token will be # passed in the metadata for authentication. - client = Client(core_url=core_url, + client = Client(core_url=core_url, serving_url=serving_url, - core_enable_auth=enable_auth, + core_enable_auth=enable_auth, core_auth_provider="google") client.create_project(PROJECT_NAME) @@ -253,8 +253,8 @@ def try_get_features(): } ) ], - feature_refs=feature_refs) - # type: GetOnlineFeaturesResponse + feature_refs=feature_refs, + )# type: GetOnlineFeaturesResponse is_ok = all([check_online_response(ref, cust_trans_df, response) for ref in feature_refs]) return response, is_ok @@ -679,7 +679,7 @@ def test_all_types_infer_register_ingest_file_success(client, @pytest.mark.timeout(200) -@pytest.mark.run(order=42) +@pytest.mark.run(order=50) def test_list_entities_and_features(client): customer_entity = Entity("customer_id", ValueType.INT64) driver_entity = Entity("driver_id", ValueType.INT64) @@ -730,10 +730,10 @@ def test_list_entities_and_features(client): # Test for listing of features # Case 1: Filter by: project, entities and labels filter_by_project_entity_labels_actual = client.list_features_by_ref(project=PROJECT_NAME, entities=["customer_id"], labels={"key1":"val1"}) - + # Case 2: Filter by: project, entities filter_by_project_entity_actual = client.list_features_by_ref(project=PROJECT_NAME, entities=["driver_id"]) - + # Case 3: Filter by: project, labels filter_by_project_labels_actual = client.list_features_by_ref(project=PROJECT_NAME, labels={"key1":"val1"}) @@ -742,7 +742,7 @@ def test_list_entities_and_features(client): assert set(filter_by_project_labels_expected) == set(filter_by_project_labels_actual) @pytest.mark.timeout(900) -@pytest.mark.run(order=50) +@pytest.mark.run(order=60) def test_sources_deduplicate_ingest_jobs(client): source = KafkaSource("localhost:9092", "feast-features") alt_source = KafkaSource("localhost:9092", "feast-data") From 7aa22be3d2542a4af9249612fde6f7f6cd88be61 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 14:02:56 +0800 Subject: [PATCH 10/23] Remove redudant nested if condition in Serving's RedisOnlineRetriever --- .../redis/retriever/RedisOnlineRetriever.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisOnlineRetriever.java b/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisOnlineRetriever.java index 2b09f7346bb..ef80b06799b 100644 --- a/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisOnlineRetriever.java +++ b/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisOnlineRetriever.java @@ -151,17 +151,15 @@ private List> getFeaturesFromRedis( // decode feature rows from data bytes using decoder. FeatureRow featureRow = FeatureRow.parseFrom(featureRowBytes); - if (decoder.isEncoded(featureRow)) { - if (decoder.isEncodingValid(featureRow)) { - featureRow = decoder.decode(featureRow); - } else { - // decoding feature row failed: data corruption could have occurred - throw Status.DATA_LOSS - .withDescription( - "Failed to decode FeatureRow from bytes retrieved from redis" - + ": Possible data corruption") - .asRuntimeException(); - } + if (decoder.isEncoded(featureRow) && decoder.isEncodingValid(featureRow)) { + featureRow = decoder.decode(featureRow); + } else { + // decoding feature row failed: data corruption could have occurred + throw Status.DATA_LOSS + .withDescription( + "Failed to decode FeatureRow from bytes retrieved from redis" + + ": Possible data corruption") + .asRuntimeException(); } featureRows.add(Optional.of(featureRow)); } From f260f007d4dcbb0e859f5d427d49bdb2ac71ee2f Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 14:04:13 +0800 Subject: [PATCH 11/23] Added support for project field in getFeatureSets() method in Serving's CachedSpecService --- sdk/python/feast/client.py | 2 +- .../serving/specs/CachedSpecService.java | 120 +++++++++++------- 2 files changed, 76 insertions(+), 46 deletions(-) diff --git a/sdk/python/feast/client.py b/sdk/python/feast/client.py index 4e2c7fb8e11..3a7dfb0b781 100644 --- a/sdk/python/feast/client.py +++ b/sdk/python/feast/client.py @@ -684,7 +684,7 @@ def get_online_features( response = self._serving_service.GetOnlineFeatures( GetOnlineFeaturesRequest( omit_entities_in_response=omit_entities, - features=_build_feature_references(feature_ref_strs=feature_refs,), + features=_build_feature_references(feature_ref_strs=feature_refs), entity_rows=entity_rows, project=project if project is not None else self.project, ) diff --git a/serving/src/main/java/feast/serving/specs/CachedSpecService.java b/serving/src/main/java/feast/serving/specs/CachedSpecService.java index f49e8faf0ba..bbbd537847d 100644 --- a/serving/src/main/java/feast/serving/specs/CachedSpecService.java +++ b/serving/src/main/java/feast/serving/specs/CachedSpecService.java @@ -103,69 +103,99 @@ public FeatureSetSpec getFeatureSetSpec(String featureSetRef) throws ExecutionEx return featureSetCache.get(featureSetRef); } + /** + * Get FeatureSetSpecs for the given features references. See {@link #getFeatureSets(List, + * String)} for full documentation. + */ + public List getFeatureSets(List featureReferences) { + return getFeatureSets(featureReferences, ""); + } + /** * Get FeatureSetSpecs for the given features references. If the project is unspecified in the - * given references, autofills the default project. Throws a {@link SpecRetrievalException}. If - * multiple feature sets match given string reference, + * given references or project override, autofills the default project. Throws a {@link + * SpecRetrievalException} if multiple feature sets match given string reference. * + * @param project name override. If specified would take the spec request in the context of the + * given project only. Has higher precedence compared to project specifed in Feature Reference + * if both are specified. * @return FeatureSetRequest containing the specs, and their respective feature references */ - public List getFeatureSets(List featureReferences) { + public List getFeatureSets( + List featureReferences, String project) { List featureSetRequests = new ArrayList<>(); featureReferences.stream() .map( featureReference -> { - // map feature reference to coresponding feature set name - String fsName = - featureToFeatureSetMapping.get(getFeatureStringWithProjectRef(featureReference)); - if (fsName == null) { - throw new SpecRetrievalException( - String.format( - "Unable to find Feature Set for the given Feature Reference: %s", - getFeatureStringWithProjectRef(featureReference))); - } else if (fsName == FEATURE_SET_CONFLICT_FLAG) { - throw new SpecRetrievalException( - String.format( - "Given Feature Reference is amibigous as it matches multiple Feature Sets: %s." - + "Please specify a more specific Feature Reference (ie specify the project or feature set)", - getFeatureStringWithProjectRef(featureReference))); + // apply project override when finding feature set for feature + FeatureReference queryFeatureRef = featureReference; + if (!project.isEmpty()) { + queryFeatureRef = featureReference.toBuilder().setProject(project).build(); } + + String fsName = mapFeatureToFeatureSetName(queryFeatureRef); return Pair.of(fsName, featureReference); }) .collect(groupingBy(Pair::getLeft)) .forEach( - (fsName, featureRefs) -> { - try { - FeatureSetSpec featureSetSpec = featureSetCache.get(fsName); - List requestedFeatures = - featureRefs.stream().map(Pair::getRight).collect(Collectors.toList()); - - // check that requested features reference point to different features in the - // featureset. - HashSet featureNames = new HashSet<>(); - requestedFeatures.forEach( - ref -> { - if (featureNames.contains(ref.getName())) { - throw new SpecRetrievalException( - "Multiple Feature References referencing the same feature in a featureset is not allowed."); - } - featureNames.add(ref.getName()); - }); - - FeatureSetRequest featureSetRequest = - FeatureSetRequest.newBuilder() - .setSpec(featureSetSpec) - .addAllFeatureReferences(requestedFeatures) - .build(); - featureSetRequests.add(featureSetRequest); - } catch (ExecutionException e) { - throw new SpecRetrievalException( - String.format("Unable to find featureSet with name: %s", fsName), e); - } + (fsName, fsNamesAndfeatureRefs) -> { + List featureRefs = + fsNamesAndfeatureRefs.stream().map(Pair::getRight).collect(Collectors.toList()); + featureSetRequests.add(buildFeatureSetRequest(fsName, featureRefs)); }); return featureSetRequests; } + /** Build a Feature Set request from the Feature Set specified by name and Feature References */ + private FeatureSetRequest buildFeatureSetRequest( + String featureSetName, List featureReferences) { + // get feature set for name + FeatureSetSpec featureSetSpec; + try { + featureSetSpec = featureSetCache.get(featureSetName); + } catch (ExecutionException e) { + throw new SpecRetrievalException( + String.format("Unable to find featureSet with name: %s", featureSetName), e); + } + + // check that requested features reference point to different features in the + // featureset. + HashSet featureNames = new HashSet<>(); + featureReferences.forEach( + ref -> { + if (featureNames.contains(ref.getName())) { + throw new SpecRetrievalException( + "Multiple Feature References referencing the same feature in a featureset is not allowed."); + } + featureNames.add(ref.getName()); + }); + + return FeatureSetRequest.newBuilder() + .setSpec(featureSetSpec) + .addAllFeatureReferences(featureReferences) + .build(); + } + + /** Maps given Feature Reference to the containing Feature Set's name */ + private String mapFeatureToFeatureSetName(FeatureReference featureReference) { + // map feature reference to coresponding feature set name + String fsName = + featureToFeatureSetMapping.get(getFeatureStringWithProjectRef(featureReference)); + if (fsName == null) { + throw new SpecRetrievalException( + String.format( + "Unable to find Feature Set for the given Feature Reference: %s", + getFeatureStringWithProjectRef(featureReference))); + } else if (fsName == FEATURE_SET_CONFLICT_FLAG) { + throw new SpecRetrievalException( + String.format( + "Given Feature Reference is amibigous as it matches multiple Feature Sets: %s." + + "Please specify a more specific Feature Reference (ie specify the project or feature set)", + getFeatureStringWithProjectRef(featureReference))); + } + return fsName; + } + /** * Reload the store configuration from the given config path, then retrieve the necessary specs * from core to preload the cache. From 8aca99906807df858afa9ed8c00453940e433d92 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 14:05:21 +0800 Subject: [PATCH 12/23] Fixed issue where Serving's OnlineServingService was only handling one feature set Caused by passing entire get online request in unpackValueMap(), when in fact it should have been individual featureSetRequests. Caused features that was not in the first feature row to be nulled out. --- .../serving/service/OnlineServingService.java | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/serving/src/main/java/feast/serving/service/OnlineServingService.java b/serving/src/main/java/feast/serving/service/OnlineServingService.java index b14faa334bc..17dfb4052b4 100644 --- a/serving/src/main/java/feast/serving/service/OnlineServingService.java +++ b/serving/src/main/java/feast/serving/service/OnlineServingService.java @@ -87,8 +87,20 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ }); } - List featureSetRequests = getFeatureSetRequests(request); - for (FeatureSetRequest featureSetRequest : getFeatureSetRequests(request)) { + List featureSetRequests = + specService.getFeatureSets(request.getFeaturesList(), request.getProject()); + for (FeatureSetRequest featureSetRequest : featureSetRequests) { + System.out.println("-------------------------------------------"); + System.out.println( + "Feature Set: " + FeatureSet.getFeatureSetStringRef(featureSetRequest.getSpec())); + System.out.println("Feature references: "); + featureSetRequest + .getFeatureReferences() + .forEach( + featureRef -> { + System.out.println(Feature.getFeatureStringRef(featureRef)); + }); + // Pull feature rows for given entity rows from the feature/featureset specified in feature // set request. // from the configured online @@ -112,7 +124,7 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ boolean isOutsideMaxAge = checkOutsideMaxAge(featureSetRequest, entityRow, featureRow); Map valueMap = - unpackValueMap(featureRow, request, isOutsideMaxAge); + unpackValueMap(featureRow, featureSetRequest, isOutsideMaxAge); entityValuesMap.get(entityRow).putAll(valueMap); // Generate metadata for feature values and merge into entityFieldsMap @@ -147,46 +159,25 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ } } - /** - * Compile {@link FeatureSetRequest}s from the given {@link GetOnlineFeaturesRequest}. Applies - * project override if specified and queries spec service to map features requested into feature - * set requests. - * - * @param request supplied by the client. - * @return list of{@link FeatureSetRequest}s compiled from the given online feature request. - */ - private List getFeatureSetRequests(GetOnlineFeaturesRequest request) { - List featureReferences = - request.getFeaturesList().stream() - .map( - featureRef -> { - if (!request.getProject().isEmpty()) { - return featureRef.toBuilder().setProject(request.getProject()).build(); - } - return featureRef; - }) - .collect(Collectors.toList()); - - return specService.getFeatureSets(featureReferences); - } - /** * Unpack feature values using data from the given feature row for features specified in the given - * online feature request. + * feature set request. * * @param featureRow optional to unpack for feature values. - * @param request online feature request for which the feature row was retrieved. + * @param featureSetRequest feature set request for which the feature row is retrieved for. * @param isOutsideMaxAge whether which the feature row contains values that is outside max age. * @return valueMap mapping string feature name to feature value for the given feature set * request. */ private static Map unpackValueMap( - Optional featureRow, GetOnlineFeaturesRequest request, boolean isOutsideMaxAge) { + Optional featureRow, + FeatureSetRequest featureSetRequest, + boolean isOutsideMaxAge) { Map valueMap = new HashMap<>(); // In order to return values containing the same feature references provided by the user, // we reuse the feature references in the request as the keys in field builder map Map nameRefMap = - request.getFeaturesList().stream() + featureSetRequest.getFeatureReferences().stream() .collect( Collectors.toMap(FeatureReference::getName, featureReference -> featureReference)); if (featureRow.isPresent()) { From 4151fe1d67c9de814bee2f0c9e0466c064586035 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 15:18:17 +0800 Subject: [PATCH 13/23] Revert removal of getFeatureRefsByName() in FeatureSetRequest --- .../feast/serving/service/OnlineServingService.java | 10 ++-------- .../feast/storage/api/retriever/FeatureSetRequest.java | 7 +++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/serving/src/main/java/feast/serving/service/OnlineServingService.java b/serving/src/main/java/feast/serving/service/OnlineServingService.java index 17dfb4052b4..ece127f3dc1 100644 --- a/serving/src/main/java/feast/serving/service/OnlineServingService.java +++ b/serving/src/main/java/feast/serving/service/OnlineServingService.java @@ -90,10 +90,6 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ List featureSetRequests = specService.getFeatureSets(request.getFeaturesList(), request.getProject()); for (FeatureSetRequest featureSetRequest : featureSetRequests) { - System.out.println("-------------------------------------------"); - System.out.println( - "Feature Set: " + FeatureSet.getFeatureSetStringRef(featureSetRequest.getSpec())); - System.out.println("Feature references: "); featureSetRequest .getFeatureReferences() .forEach( @@ -176,10 +172,8 @@ private static Map unpackValueMap( Map valueMap = new HashMap<>(); // In order to return values containing the same feature references provided by the user, // we reuse the feature references in the request as the keys in field builder map - Map nameRefMap = - featureSetRequest.getFeatureReferences().stream() - .collect( - Collectors.toMap(FeatureReference::getName, featureReference -> featureReference)); + Map nameRefMap = featureSetRequest.getFeatureRefsByName(); + if (featureRow.isPresent()) { // unpack feature row's feature values and populate value map Map featureValueMap = diff --git a/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java b/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java index 869d0027b5a..3482529a97d 100644 --- a/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java +++ b/storage/api/src/main/java/feast/storage/api/retriever/FeatureSetRequest.java @@ -21,6 +21,8 @@ import feast.proto.core.FeatureSetProto.FeatureSetSpec; import feast.proto.serving.ServingAPIProto.FeatureReference; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @AutoValue public abstract class FeatureSetRequest { @@ -50,4 +52,9 @@ public Builder addFeatureReference(FeatureReference featureReference) { public abstract FeatureSetRequest build(); } + + public Map getFeatureRefsByName() { + return getFeatureReferences().stream() + .collect(Collectors.toMap(FeatureReference::getName, featureReference -> featureReference)); + } } From a5370b95bd9e017195c6d4bee8360051c1d64a07 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 17:13:55 +0800 Subject: [PATCH 14/23] Fix java unit tests --- .../java/feast/serving/service/OnlineServingService.java | 7 ------- .../feast/serving/service/OnlineServingServiceTest.java | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/serving/src/main/java/feast/serving/service/OnlineServingService.java b/serving/src/main/java/feast/serving/service/OnlineServingService.java index ece127f3dc1..a357904e32f 100644 --- a/serving/src/main/java/feast/serving/service/OnlineServingService.java +++ b/serving/src/main/java/feast/serving/service/OnlineServingService.java @@ -90,13 +90,6 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequest requ List featureSetRequests = specService.getFeatureSets(request.getFeaturesList(), request.getProject()); for (FeatureSetRequest featureSetRequest : featureSetRequests) { - featureSetRequest - .getFeatureReferences() - .forEach( - featureRef -> { - System.out.println(Feature.getFeatureStringRef(featureRef)); - }); - // Pull feature rows for given entity rows from the feature/featureset specified in feature // set request. // from the configured online diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java index 014a93099f1..403fc73ee7b 100644 --- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java +++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java @@ -221,7 +221,7 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfKeysNotPresent() { .build()), Optional.empty()); - when(specService.getFeatureSets(request.getFeaturesList())) + when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); From 76f9a0de6284cce075317edd8bf8d6f40ea99a93 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 17:17:37 +0800 Subject: [PATCH 15/23] Fix unresolved conflicts in e2e batch tests --- .../service/OnlineServingServiceTest.java | 20 +++++++------------ tests/e2e/bq/bq-batch-retrieval.py | 14 ++----------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java index 403fc73ee7b..6192cb63757 100644 --- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java +++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java @@ -43,7 +43,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatchers; @@ -141,7 +140,7 @@ public void shouldReturnResponseWithValuesAndMetadataIfKeysPresent() { .setSpec(getFeatureSetSpec()) .build(); - when(specService.getFeatureSets(request.getFeaturesList())) + when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); @@ -334,7 +333,7 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfMaxAgeIsExceeded() { .setSpec(spec) .build(); - when(specService.getFeatureSets(request.getFeaturesList())) + when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); @@ -443,7 +442,7 @@ public void shouldFilterOutUndesiredRows() { .setSpec(getFeatureSetSpec()) .build(); - when(specService.getFeatureSets(request.getFeaturesList())) + when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); @@ -513,21 +512,16 @@ public void shouldApplyProjectOverrideInRequest() { .setName("feature2") .setValue(intValue(1)) .build())) - .setFeatureSet("default/featureSet") + .setFeatureSet("project/featureSet") .build())); - List projectOverrideFeatureReferences = - request.getFeaturesList().stream() - .map(featureRef -> featureRef.toBuilder().setProject("project").build()) - .collect(Collectors.toList()); - FeatureSetRequest featureSetRequest = FeatureSetRequest.newBuilder() - .addAllFeatureReferences(projectOverrideFeatureReferences) + .addAllFeatureReferences(request.getFeaturesList()) .setSpec(getFeatureSetSpec()) .build(); - when(specService.getFeatureSets(projectOverrideFeatureReferences)) + when(specService.getFeatureSets(request.getFeaturesList(), "project")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); @@ -564,7 +558,7 @@ private FeatureSetSpec getFeatureSetSpec() { .setName("featureSet") .addEntities(EntitySpec.newBuilder().setName("entity1")) .addEntities(EntitySpec.newBuilder().setName("entity2")) - .setMaxAge(Duration.newBuilder().setSeconds(30)) // default + .setMaxAge(Duration.newBuilder().setSeconds(30)) .build(); } } diff --git a/tests/e2e/bq/bq-batch-retrieval.py b/tests/e2e/bq/bq-batch-retrieval.py index 488f1197193..178d000f5dd 100644 --- a/tests/e2e/bq/bq-batch-retrieval.py +++ b/tests/e2e/bq/bq-batch-retrieval.py @@ -459,12 +459,8 @@ def check(): int(i) for i in output["feature_value6"].to_list() ] assert ( -<<<<<<< HEAD - output["other_entity_id"].to_list() == output["feature_set_2__other_feature_value7"].to_list() -======= output["other_entity_id"].to_list() == output["feature_set_2__other_feature_value7"].to_list() ->>>>>>> Reorder basic e2e tests to ensure that list features and entities tests do not interfere with otheer tests ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) @@ -527,13 +523,9 @@ def infra_teardown(pytestconfig, core_url, serving_url): print("Cleaning up not required") -<<<<<<< HEAD -''' -======= """ ->>>>>>> Reorder basic e2e tests to ensure that list features and entities tests do not interfere with otheer tests -This suite of tests tests the apply feature set - update feature set - retrieve -event sequence. It ensures that when a feature set is updated, tombstoned features +This suite of tests tests the apply feature set - update feature set - retrieve +event sequence. It ensures that when a feature set is updated, tombstoned features are no longer retrieved, and added features are null for previously ingested rows. @@ -541,8 +533,6 @@ def infra_teardown(pytestconfig, core_url, serving_url): to perform this test, due to bigquery schema caching for streaming writes. """ - - @pytest.fixture(scope="module") def update_featureset_dataframe(): n_rows = 10 From 8943342befa44730961266cd7f4eabb7390cb949 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 17:55:02 +0800 Subject: [PATCH 16/23] Revert format on batch e2e test --- tests/e2e/bq/bq-batch-retrieval.py | 90 ++++++++++++------------------ 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/tests/e2e/bq/bq-batch-retrieval.py b/tests/e2e/bq/bq-batch-retrieval.py index 178d000f5dd..3918f69fb3a 100644 --- a/tests/e2e/bq/bq-batch-retrieval.py +++ b/tests/e2e/bq/bq-batch-retrieval.py @@ -184,9 +184,7 @@ def test_batch_get_batch_features_with_file(client): client.ingest(file_fs1, features_1_df, timeout=480) # Rename column (datetime -> event_timestamp) - features_1_df["datetime"] + pd.Timedelta( - seconds=1 - ) # adds buffer to avoid rounding errors + features_1_df['datetime'] + pd.Timedelta(seconds=1) # adds buffer to avoid rounding errors features_1_df = features_1_df.rename(columns={"datetime": "event_timestamp"}) to_avro( @@ -232,9 +230,7 @@ def test_batch_get_batch_features_with_gs_path(client, gcs_path): client.ingest(gcs_fs1, features_1_df, timeout=360) # Rename column (datetime -> event_timestamp) - features_1_df["datetime"] + pd.Timedelta( - seconds=1 - ) # adds buffer to avoid rounding errors + features_1_df['datetime'] + pd.Timedelta(seconds=1) # adds buffer to avoid rounding errors features_1_df = features_1_df.rename(columns={"datetime": "event_timestamp"}) # Output file to local @@ -346,9 +342,7 @@ def check(): feature_refs=["feature_value4"], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( - by=["entity_id"] - ) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) print(output.head(10)) assert np.allclose( @@ -358,10 +352,7 @@ def check(): output["additional_string_col"].to_list() == entity_df["additional_string_col"].to_list() ) - assert ( - output["feature_value4"].to_list() - == features_df["feature_value4"].to_list() - ) + assert output["feature_value4"].to_list() == features_df["feature_value4"].to_list() clean_up_remote_files(feature_retrieval_job.get_avro_files()) wait_for(check, timedelta(minutes=5)) @@ -449,7 +440,10 @@ def test_batch_multiple_featureset_joins(client): def check(): feature_retrieval_job = client.get_batch_features( entity_rows=entity_df, - feature_refs=["feature_value6", "feature_set_2:other_feature_value7",], + feature_refs=[ + "feature_value6", + "feature_set_2:other_feature_value7", + ], project=PROJECT_NAME, ) output = feature_retrieval_job.to_dataframe(timeout_sec=180) @@ -459,8 +453,7 @@ def check(): int(i) for i in output["feature_value6"].to_list() ] assert ( - output["other_entity_id"].to_list() - == output["feature_set_2__other_feature_value7"].to_list() + output["other_entity_id"].to_list() == output["feature_set_2__other_feature_value7"].to_list() ) clean_up_remote_files(feature_retrieval_job.get_avro_files()) @@ -523,15 +516,16 @@ def infra_teardown(pytestconfig, core_url, serving_url): print("Cleaning up not required") -""" -This suite of tests tests the apply feature set - update feature set - retrieve -event sequence. It ensures that when a feature set is updated, tombstoned features +''' +This suite of tests tests the apply feature set - update feature set - retrieve +event sequence. It ensures that when a feature set is updated, tombstoned features are no longer retrieved, and added features are null for previously ingested rows. It is marked separately because of the length of time required to perform this test, due to bigquery schema caching for streaming writes. -""" +''' + @pytest.fixture(scope="module") def update_featureset_dataframe(): @@ -569,23 +563,18 @@ def test_update_featureset_apply_featureset_and_ingest_first_subset( def check(): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[:5], - feature_refs=["update_feature1", "update_feature2",], - project=PROJECT_NAME, + feature_refs=[ + "update_feature1", + "update_feature2", + ], + project=PROJECT_NAME ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( - by=["entity_id"] - ) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) print(output.head()) - assert ( - output["update_feature1"].to_list() - == subset_df["update_feature1"].to_list() - ) - assert ( - output["update_feature2"].to_list() - == subset_df["update_feature2"].to_list() - ) + assert output["update_feature1"].to_list() == subset_df["update_feature1"].to_list() + assert output["update_feature2"].to_list() == subset_df["update_feature2"].to_list() clean_up_remote_files(feature_retrieval_job.get_avro_files()) @@ -632,27 +621,20 @@ def test_update_featureset_update_featureset_and_ingest_second_subset( def check(): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[5:], - feature_refs=["update_feature1", "update_feature3", "update_feature4",], + feature_refs=[ + "update_feature1", + "update_feature3", + "update_feature4", + ], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( - by=["entity_id"] - ) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) print(output.head()) - assert ( - output["update_feature1"].to_list() - == subset_df["update_feature1"].to_list() - ) - assert ( - output["update_feature3"].to_list() - == subset_df["update_feature3"].to_list() - ) - assert ( - output["update_feature4"].to_list() - == subset_df["update_feature4"].to_list() - ) + assert output["update_feature1"].to_list() == subset_df["update_feature1"].to_list() + assert output["update_feature3"].to_list() == subset_df["update_feature3"].to_list() + assert output["update_feature4"].to_list() == subset_df["update_feature4"].to_list() clean_up_remote_files(feature_retrieval_job.get_avro_files()) wait_for(check, timedelta(minutes=5)) @@ -680,12 +662,14 @@ def test_update_featureset_retrieve_all_fields(client, update_featureset_datafra def test_update_featureset_retrieve_valid_fields(client, update_featureset_dataframe): feature_retrieval_job = client.get_batch_features( entity_rows=update_featureset_dataframe[["datetime", "entity_id"]], - feature_refs=["update_feature1", "update_feature3", "update_feature4",], + feature_refs=[ + "update_feature1", + "update_feature3", + "update_feature4", + ], project=PROJECT_NAME, ) - output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values( - by=["entity_id"] - ) + output = feature_retrieval_job.to_dataframe(timeout_sec=180).sort_values(by=["entity_id"]) clean_up_remote_files(feature_retrieval_job.get_avro_files()) print(output.head(10)) assert ( From b6429fa0217e57e728a9fb5e1958abffed28dcaf Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 18:17:38 +0800 Subject: [PATCH 17/23] Revert row count used for testing --- sdk/python/tests/test_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/python/tests/test_client.py b/sdk/python/tests/test_client.py index 75e43f32a38..9a492c1721e 100644 --- a/sdk/python/tests/test_client.py +++ b/sdk/python/tests/test_client.py @@ -263,7 +263,7 @@ def test_version(self, mocked_client, mocker): [pytest.lazy_fixture("mock_client"), pytest.lazy_fixture("secure_mock_client")], ) def test_get_online_features(self, mocked_client, mocker): - ROW_COUNT = 1 + ROW_COUNT = 300 mocked_client._serving_service_stub = Serving.ServingServiceStub( grpc.insecure_channel("") From 3bd1cd9e83c39bb4fe01a6cfad5968b43481cb20 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Wed, 24 Jun 2020 21:28:29 +0800 Subject: [PATCH 18/23] Refactor Serving's OnlineServingServiceTest to reduce code deduplication --- .../service/OnlineServingServiceTest.java | 386 ++++++------------ 1 file changed, 131 insertions(+), 255 deletions(-) diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java index 6192cb63757..e8a0ea88c92 100644 --- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java +++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java @@ -59,80 +59,91 @@ public class OnlineServingServiceTest { private OnlineServingService onlineServingService; + List testFeatureRows; + @Before public void setUp() { initMocks(this); onlineServingService = new OnlineServingService(retriever, specService, tracer); + + // create fake feature rows for testing. + testFeatureRows = + Lists.newArrayList( + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder() + .setName("entity1") + .setValue(intValue(1)) + .build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("a")) + .build(), + FieldProto.Field.newBuilder() + .setName("feature1") + .setValue(intValue(1)) + .build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(1)) + .build())) + .setFeatureSet("featureSet") + .build(), + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder() + .setName("entity1") + .setValue(intValue(2)) + .build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("b")) + .build(), + FieldProto.Field.newBuilder() + .setName("feature1") + .setValue(intValue(2)) + .build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(2)) + .build())) + .setFeatureSet("featureSet") + .build(), + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(50)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder() + .setName("entity1") + .setValue(intValue(2)) + .build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("b")) + .build(), + FieldProto.Field.newBuilder() + .setName("feature1") + .setValue(intValue(2)) + .build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(2)) + .build())) + .setFeatureSet("featureSet") + .build()); } @Test public void shouldReturnResponseWithValuesAndMetadataIfKeysPresent() { GetOnlineFeaturesRequest request = - GetOnlineFeaturesRequest.newBuilder() - .setOmitEntitiesInResponse(false) - .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) - .addFeatures( - FeatureReference.newBuilder().setName("feature2").setProject("project").build()) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(1)) - .putFields("entity2", strValue("a"))) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(2)) - .putFields("entity2", strValue("b"))) - .build(); - - List> featureRows = - Lists.newArrayList( - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("a")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .setFeatureSet("featureSet") - .build()), - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("b")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(2)) - .build())) - .setFeatureSet("featureSet") - .build())); + getOnlineFeaturesRequest( + List.of( + FeatureReference.newBuilder().setName("feature1").build(), + FeatureReference.newBuilder().setName("feature2").setProject("project").build())); FeatureSetRequest featureSetRequest = FeatureSetRequest.newBuilder() @@ -140,10 +151,14 @@ public void shouldReturnResponseWithValuesAndMetadataIfKeysPresent() { .setSpec(getFeatureSetSpec()) .build(); + List> featureRows = + List.of(Optional.of(testFeatureRows.get(0)), Optional.of(testFeatureRows.get(1))); + when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); when(retriever.getOnlineFeatures(request.getEntityRowsList(), featureSetRequest)) .thenReturn(featureRows); + when(tracer.buildSpan(ArgumentMatchers.any())).thenReturn(Mockito.mock(SpanBuilder.class)); GetOnlineFeaturesResponse expected = @@ -179,21 +194,10 @@ public void shouldReturnResponseWithValuesAndMetadataIfKeysPresent() { public void shouldReturnResponseWithUnsetValuesAndMetadataIfKeysNotPresent() { // some keys not present, should have empty values GetOnlineFeaturesRequest request = - GetOnlineFeaturesRequest.newBuilder() - .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) - .addFeatures( - FeatureReference.newBuilder().setName("feature2").setProject("project").build()) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(1)) - .putFields("entity2", strValue("a"))) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(2)) - .putFields("entity2", strValue("b"))) - .build(); + getOnlineFeaturesRequest( + List.of( + FeatureReference.newBuilder().setName("feature1").build(), + FeatureReference.newBuilder().setName("feature2").setProject("project").build())); FeatureSetRequest featureSetRequest = FeatureSetRequest.newBuilder() @@ -202,23 +206,7 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfKeysNotPresent() { .build(); List> featureRows = - Lists.newArrayList( - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .setFeatureSet("project/featureSet") - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .build()), - Optional.empty()); + List.of(Optional.of(testFeatureRows.get(0)), Optional.empty()); when(specService.getFeatureSets(request.getFeaturesList(), "")) .thenReturn(Collections.singletonList(featureSetRequest)); @@ -259,71 +247,13 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfKeysNotPresent() { public void shouldReturnResponseWithUnsetValuesAndMetadataIfMaxAgeIsExceeded() { // keys present, but considered stale when compared to maxAge GetOnlineFeaturesRequest request = - GetOnlineFeaturesRequest.newBuilder() - .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) - .addFeatures( - FeatureReference.newBuilder().setName("feature2").setProject("project").build()) - .setOmitEntitiesInResponse(false) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(1)) - .putFields("entity2", strValue("a"))) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(2)) - .putFields("entity2", strValue("b"))) - .build(); + getOnlineFeaturesRequest( + List.of( + FeatureReference.newBuilder().setName("feature1").build(), + FeatureReference.newBuilder().setName("feature2").setProject("project").build())); List> featureRows = - Lists.newArrayList( - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("a")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .setFeatureSet("project/featureSet") - .build()), - Optional.of( - FeatureRow.newBuilder() // this feature row should have its values nulled - .setEventTimestamp(Timestamp.newBuilder().setSeconds(50)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("b")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("project/feature2") - .setValue(intValue(2)) - .build())) - .setFeatureSet("project/featureSet") - .build())); + List.of(Optional.of(testFeatureRows.get(0)), Optional.of(testFeatureRows.get(2))); FeatureSetSpec spec = getFeatureSetSpec().toBuilder().setMaxAge(Duration.newBuilder().setSeconds(1)).build(); @@ -372,69 +302,11 @@ public void shouldReturnResponseWithUnsetValuesAndMetadataIfMaxAgeIsExceeded() { public void shouldFilterOutUndesiredRows() { // requested rows less than the rows available in the featureset GetOnlineFeaturesRequest request = - GetOnlineFeaturesRequest.newBuilder() - .setOmitEntitiesInResponse(false) - .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(1)) - .putFields("entity2", strValue("a"))) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(2)) - .putFields("entity2", strValue("b"))) - .build(); + getOnlineFeaturesRequest( + List.of(FeatureReference.newBuilder().setName("feature1").build())); List> featureRows = - Lists.newArrayList( - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("a")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .setFeatureSet("featureSet") - .build()), - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("b")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(2)) - .build())) - .setFeatureSet("featureSet") - .build())); + List.of(Optional.of(testFeatureRows.get(0)), Optional.of(testFeatureRows.get(1))); FeatureSetRequest featureSetRequest = FeatureSetRequest.newBuilder() @@ -476,44 +348,19 @@ public void shouldFilterOutUndesiredRows() { @Test public void shouldApplyProjectOverrideInRequest() { GetOnlineFeaturesRequest request = - GetOnlineFeaturesRequest.newBuilder() - .setOmitEntitiesInResponse(false) + getOnlineFeaturesRequest( + List.of( + FeatureReference.newBuilder().setName("feature1").build(), + FeatureReference.newBuilder() + .setName("feature2") + .setProject("project") + .build())) + .toBuilder() .setProject("project") - .addFeatures(FeatureReference.newBuilder().setName("feature1").build()) - .addFeatures( - FeatureReference.newBuilder().setName("feature2").setProject("project").build()) - .addEntityRows( - EntityRow.newBuilder() - .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) - .putFields("entity1", intValue(1)) - .putFields("entity2", strValue("a"))) .build(); List> featureRows = - Lists.newArrayList( - Optional.of( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("a")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .setFeatureSet("project/featureSet") - .build())); + List.of(Optional.of(testFeatureRows.get(0)), Optional.of(testFeatureRows.get(1))); FeatureSetRequest featureSetRequest = FeatureSetRequest.newBuilder() @@ -540,6 +387,17 @@ public void shouldApplyProjectOverrideInRequest() { .putFields("project/feature2", intValue(1)) .putStatuses("project/feature2", FieldStatus.PRESENT) .build()) + .addFieldValues( + FieldValues.newBuilder() + .putFields("entity1", intValue(2)) + .putStatuses("entity1", FieldStatus.PRESENT) + .putFields("entity2", strValue("b")) + .putStatuses("entity2", FieldStatus.PRESENT) + .putFields("feature1", intValue(2)) + .putStatuses("feature1", FieldStatus.PRESENT) + .putFields("project/feature2", intValue(2)) + .putStatuses("project/feature2", FieldStatus.PRESENT) + .build()) .build(); GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request); assertThat(actual, equalTo(expected)); @@ -561,4 +419,22 @@ private FeatureSetSpec getFeatureSetSpec() { .setMaxAge(Duration.newBuilder().setSeconds(30)) .build(); } + + private GetOnlineFeaturesRequest getOnlineFeaturesRequest( + List featureReferences) { + return GetOnlineFeaturesRequest.newBuilder() + .setOmitEntitiesInResponse(false) + .addAllFeatures(featureReferences) + .addEntityRows( + EntityRow.newBuilder() + .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) + .putFields("entity1", intValue(1)) + .putFields("entity2", strValue("a"))) + .addEntityRows( + EntityRow.newBuilder() + .setEntityTimestamp(Timestamp.newBuilder().setSeconds(100)) + .putFields("entity1", intValue(2)) + .putFields("entity2", strValue("b"))) + .build(); + } } From b969caef4705c1226293e39db56f065fbb46b249 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Thu, 25 Jun 2020 11:15:20 +0800 Subject: [PATCH 19/23] Make exception on parse feature reference more explict --- sdk/java/src/main/java/com/gojek/feast/RequestUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java index 38a60dd1f90..d7886b48d6e 100644 --- a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java +++ b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java @@ -55,7 +55,8 @@ public static FeatureReference.Builder parseFeatureRef(String featureRefString) } if (featureRefString.contains("/")) { throw new IllegalArgumentException( - String.format("Unsupported feature reference: %s", featureRefString)); + String.format("Unsupported feature reference: Specifying project in string" + + " Feature References is not longer supported: %s", featureRefString)); } FeatureReference.Builder featureRef = FeatureReference.newBuilder(); From 1ccaf740c8249f07c1e2ee7690f439559ddce637 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Thu, 25 Jun 2020 11:18:23 +0800 Subject: [PATCH 20/23] Clarify the functionality of CachedSpecService getFeatureSets()'s projectOverride parameter in docs --- .../main/java/com/gojek/feast/RequestUtil.java | 6 ++++-- .../feast/serving/specs/CachedSpecService.java | 18 +++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java index d7886b48d6e..c2290c6d11d 100644 --- a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java +++ b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java @@ -55,8 +55,10 @@ public static FeatureReference.Builder parseFeatureRef(String featureRefString) } if (featureRefString.contains("/")) { throw new IllegalArgumentException( - String.format("Unsupported feature reference: Specifying project in string" - + " Feature References is not longer supported: %s", featureRefString)); + String.format( + "Unsupported feature reference: Specifying project in string" + + " Feature References is not longer supported: %s", + featureRefString)); } FeatureReference.Builder featureRef = FeatureReference.newBuilder(); diff --git a/serving/src/main/java/feast/serving/specs/CachedSpecService.java b/serving/src/main/java/feast/serving/specs/CachedSpecService.java index bbbd537847d..228325ca30f 100644 --- a/serving/src/main/java/feast/serving/specs/CachedSpecService.java +++ b/serving/src/main/java/feast/serving/specs/CachedSpecService.java @@ -116,21 +116,22 @@ public List getFeatureSets(List featureRefe * given references or project override, autofills the default project. Throws a {@link * SpecRetrievalException} if multiple feature sets match given string reference. * - * @param project name override. If specified would take the spec request in the context of the - * given project only. Has higher precedence compared to project specifed in Feature Reference - * if both are specified. + * @param projectOverride If specified would take the spec request in the context of the given + * project only. Otherwise if "", will default to determining the project from the individual + * references. Has higher precedence compared to project specifed in Feature Reference if both + * are specified. * @return FeatureSetRequest containing the specs, and their respective feature references */ public List getFeatureSets( - List featureReferences, String project) { + List featureReferences, String projectOverride) { List featureSetRequests = new ArrayList<>(); featureReferences.stream() .map( featureReference -> { // apply project override when finding feature set for feature FeatureReference queryFeatureRef = featureReference; - if (!project.isEmpty()) { - queryFeatureRef = featureReference.toBuilder().setProject(project).build(); + if (!projectOverride.isEmpty()) { + queryFeatureRef = featureReference.toBuilder().setProject(projectOverride).build(); } String fsName = mapFeatureToFeatureSetName(queryFeatureRef); @@ -146,7 +147,10 @@ public List getFeatureSets( return featureSetRequests; } - /** Build a Feature Set request from the Feature Set specified by name and Feature References */ + /** + * Build a Feature Set request from the Feature Set specified by given name and givenFeature + * References + */ private FeatureSetRequest buildFeatureSetRequest( String featureSetName, List featureReferences) { // get feature set for name From 80c11388a1312049c8c5ca196f19700d5c26bd06 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Thu, 25 Jun 2020 12:18:21 +0800 Subject: [PATCH 21/23] Add javadoc to CachedSpecService's buildFeatureSetRequest() method --- .../serving/specs/CachedSpecService.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/serving/src/main/java/feast/serving/specs/CachedSpecService.java b/serving/src/main/java/feast/serving/specs/CachedSpecService.java index 228325ca30f..f7ca646fdc2 100644 --- a/serving/src/main/java/feast/serving/specs/CachedSpecService.java +++ b/serving/src/main/java/feast/serving/specs/CachedSpecService.java @@ -134,32 +134,36 @@ public List getFeatureSets( queryFeatureRef = featureReference.toBuilder().setProject(projectOverride).build(); } - String fsName = mapFeatureToFeatureSetName(queryFeatureRef); - return Pair.of(fsName, featureReference); + String featureSetRefStr = mapFeatureToFeatureSetReference(queryFeatureRef); + return Pair.of(featureSetRefStr, featureReference); }) .collect(groupingBy(Pair::getLeft)) .forEach( - (fsName, fsNamesAndfeatureRefs) -> { + (featureSetRefStr, fsRefStrAndFeatureRefs) -> { List featureRefs = - fsNamesAndfeatureRefs.stream().map(Pair::getRight).collect(Collectors.toList()); - featureSetRequests.add(buildFeatureSetRequest(fsName, featureRefs)); + fsRefStrAndFeatureRefs.stream().map(Pair::getRight).collect(Collectors.toList()); + featureSetRequests.add(buildFeatureSetRequest(featureSetRefStr, featureRefs)); }); return featureSetRequests; } /** - * Build a Feature Set request from the Feature Set specified by given name and givenFeature - * References + * Build a Feature Set request from the Feature Set specified by given Feature Set reference + * and given Feature References. + * + * @param featureSetRefStr string feature set reference specifying the feature set that contains requested features + * @param featureReferences list of feature references specifying the containing feature set references. + * */ private FeatureSetRequest buildFeatureSetRequest( - String featureSetName, List featureReferences) { + String featureSetRefStr, List featureReferences) { // get feature set for name FeatureSetSpec featureSetSpec; try { - featureSetSpec = featureSetCache.get(featureSetName); + featureSetSpec = featureSetCache.get(featureSetRefStr); } catch (ExecutionException e) { throw new SpecRetrievalException( - String.format("Unable to find featureSet with name: %s", featureSetName), e); + String.format("Unable to find featureSet with name: %s", featureSetRefStr), e); } // check that requested features reference point to different features in the @@ -180,24 +184,24 @@ private FeatureSetRequest buildFeatureSetRequest( .build(); } - /** Maps given Feature Reference to the containing Feature Set's name */ - private String mapFeatureToFeatureSetName(FeatureReference featureReference) { - // map feature reference to coresponding feature set name - String fsName = + /** Maps given Feature Reference to the containing Feature Set's string reference */ + private String mapFeatureToFeatureSetReference(FeatureReference featureReference) { + // map feature reference to coresponding feature set string reference + String featureSetRefStr = featureToFeatureSetMapping.get(getFeatureStringWithProjectRef(featureReference)); - if (fsName == null) { + if (featureSetRefStr == null) { throw new SpecRetrievalException( String.format( "Unable to find Feature Set for the given Feature Reference: %s", getFeatureStringWithProjectRef(featureReference))); - } else if (fsName == FEATURE_SET_CONFLICT_FLAG) { + } else if (featureSetRefStr == FEATURE_SET_CONFLICT_FLAG) { throw new SpecRetrievalException( String.format( "Given Feature Reference is amibigous as it matches multiple Feature Sets: %s." + "Please specify a more specific Feature Reference (ie specify the project or feature set)", getFeatureStringWithProjectRef(featureReference))); } - return fsName; + return featureSetRefStr; } /** From ef430a9f7199213cceb6a1cd8ae34c015a282159 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Thu, 25 Jun 2020 12:24:06 +0800 Subject: [PATCH 22/23] Fix java lint --- .../java/feast/serving/specs/CachedSpecService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/serving/src/main/java/feast/serving/specs/CachedSpecService.java b/serving/src/main/java/feast/serving/specs/CachedSpecService.java index f7ca646fdc2..6d2d2d543ab 100644 --- a/serving/src/main/java/feast/serving/specs/CachedSpecService.java +++ b/serving/src/main/java/feast/serving/specs/CachedSpecService.java @@ -148,12 +148,13 @@ public List getFeatureSets( } /** - * Build a Feature Set request from the Feature Set specified by given Feature Set reference - * and given Feature References. - * - * @param featureSetRefStr string feature set reference specifying the feature set that contains requested features - * @param featureReferences list of feature references specifying the containing feature set references. + * Build a Feature Set request from the Feature Set specified by given Feature Set reference and + * given Feature References. * + * @param featureSetRefStr string feature set reference specifying the feature set that contains + * requested features + * @param featureReferences list of feature references specifying the containing feature set + * references. */ private FeatureSetRequest buildFeatureSetRequest( String featureSetRefStr, List featureReferences) { From a0a9a263f6ffe43305a5bdd9967e534fe1952f64 Mon Sep 17 00:00:00 2001 From: Zhu Zhanyan Date: Thu, 25 Jun 2020 13:01:10 +0800 Subject: [PATCH 23/23] Further reduce duplication in OnlineServingServiceTest. --- .../service/OnlineServingServiceTest.java | 112 +++++++----------- 1 file changed, 44 insertions(+), 68 deletions(-) diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java index e8a0ea88c92..f2a8038a973 100644 --- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java +++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java @@ -40,6 +40,7 @@ import feast.storage.connectors.redis.retriever.RedisOnlineRetriever; import io.opentracing.Tracer; import io.opentracing.Tracer.SpanBuilder; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -67,74 +68,49 @@ public void setUp() { onlineServingService = new OnlineServingService(retriever, specService, tracer); // create fake feature rows for testing. - testFeatureRows = - Lists.newArrayList( - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("a")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(1)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(1)) - .build())) - .setFeatureSet("featureSet") - .build(), - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("b")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(2)) - .build())) - .setFeatureSet("featureSet") - .build(), - FeatureRow.newBuilder() - .setEventTimestamp(Timestamp.newBuilder().setSeconds(50)) - .addAllFields( - Lists.newArrayList( - FieldProto.Field.newBuilder() - .setName("entity1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("entity2") - .setValue(strValue("b")) - .build(), - FieldProto.Field.newBuilder() - .setName("feature1") - .setValue(intValue(2)) - .build(), - FieldProto.Field.newBuilder() - .setName("feature2") - .setValue(intValue(2)) - .build())) - .setFeatureSet("featureSet") - .build()); + testFeatureRows = new ArrayList<>(); + testFeatureRows.add( + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder().setName("entity1").setValue(intValue(1)).build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("a")) + .build(), + FieldProto.Field.newBuilder().setName("feature1").setValue(intValue(1)).build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(1)) + .build())) + .setFeatureSet("featureSet") + .build()); + + testFeatureRows.add( + FeatureRow.newBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(100)) + .addAllFields( + Lists.newArrayList( + FieldProto.Field.newBuilder().setName("entity1").setValue(intValue(2)).build(), + FieldProto.Field.newBuilder() + .setName("entity2") + .setValue(strValue("b")) + .build(), + FieldProto.Field.newBuilder().setName("feature1").setValue(intValue(2)).build(), + FieldProto.Field.newBuilder() + .setName("feature2") + .setValue(intValue(2)) + .build())) + .setFeatureSet("featureSet") + .build()); + + testFeatureRows.add( + testFeatureRows + .get(1) + .toBuilder() + .setEventTimestamp(Timestamp.newBuilder().setSeconds(50)) + .build()); } @Test