diff --git a/core/src/main/java/feast/core/grpc/CoreServiceImpl.java b/core/src/main/java/feast/core/grpc/CoreServiceImpl.java
index 0c7ea5828e7..412d3d31198 100644
--- a/core/src/main/java/feast/core/grpc/CoreServiceImpl.java
+++ b/core/src/main/java/feast/core/grpc/CoreServiceImpl.java
@@ -183,6 +183,17 @@ public void archiveProject(
accessManagementService.archiveProject(request.getName());
responseObserver.onNext(ArchiveProjectResponse.getDefaultInstance());
responseObserver.onCompleted();
+ } catch (IllegalArgumentException e) {
+ log.error("Recieved an invalid request on calling archiveProject method:", e);
+ responseObserver.onError(
+ Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .withCause(e)
+ .asRuntimeException());
+ } catch (UnsupportedOperationException e) {
+ log.error("Attempted to archive an unsupported project:", e);
+ responseObserver.onError(
+ Status.UNIMPLEMENTED.withDescription(e.getMessage()).withCause(e).asRuntimeException());
} catch (Exception e) {
log.error("Exception has occurred in the createProject method: ", e);
responseObserver.onError(
diff --git a/core/src/main/java/feast/core/model/FeatureSet.java b/core/src/main/java/feast/core/model/FeatureSet.java
index 3008c37a3f9..f7b2dc7cd49 100644
--- a/core/src/main/java/feast/core/model/FeatureSet.java
+++ b/core/src/main/java/feast/core/model/FeatureSet.java
@@ -39,7 +39,6 @@
uniqueConstraints = @UniqueConstraint(columnNames = {"name", "project_name"}))
public class FeatureSet extends AbstractTimestampEntity {
- // Id of the featureSet, defined as project/feature_set_name:feature_set_version
@Id @GeneratedValue private long id;
// Name of the featureSet
diff --git a/core/src/main/java/feast/core/model/Project.java b/core/src/main/java/feast/core/model/Project.java
index d6e6149394b..c55830c8248 100644
--- a/core/src/main/java/feast/core/model/Project.java
+++ b/core/src/main/java/feast/core/model/Project.java
@@ -34,6 +34,7 @@
@Entity
@Table(name = "projects")
public class Project {
+ public static final String DEFAULT_NAME = "default";
// Name of the project
@Id
diff --git a/core/src/main/java/feast/core/service/AccessManagementService.java b/core/src/main/java/feast/core/service/AccessManagementService.java
index df92750e94f..5b02d6f3c4a 100644
--- a/core/src/main/java/feast/core/service/AccessManagementService.java
+++ b/core/src/main/java/feast/core/service/AccessManagementService.java
@@ -28,12 +28,15 @@
@Slf4j
@Service
public class AccessManagementService {
-
private ProjectRepository projectRepository;
@Autowired
public AccessManagementService(ProjectRepository projectRepository) {
this.projectRepository = projectRepository;
+ // create default project if it does not yet exist.
+ if (!projectRepository.existsById(Project.DEFAULT_NAME)) {
+ this.createProject(Project.DEFAULT_NAME);
+ }
}
/**
@@ -61,6 +64,9 @@ public void archiveProject(String name) {
if (!project.isPresent()) {
throw new IllegalArgumentException(String.format("Could not find project: \"%s\"", name));
}
+ if (name.equals(Project.DEFAULT_NAME)) {
+ throw new UnsupportedOperationException("Archiving the default project is not allowed.");
+ }
Project p = project.get();
p.setArchived(true);
projectRepository.saveAndFlush(p);
diff --git a/core/src/main/java/feast/core/service/SpecService.java b/core/src/main/java/feast/core/service/SpecService.java
index 767b3fe6920..01cd264c761 100644
--- a/core/src/main/java/feast/core/service/SpecService.java
+++ b/core/src/main/java/feast/core/service/SpecService.java
@@ -80,7 +80,8 @@ public SpecService(
/**
* Get a feature set matching the feature name and version and project. The feature set name and
* project are required, but version can be omitted by providing 0 for its value. If the version
- * is omitted, the latest feature set will be provided.
+ * is omitted, the latest feature set will be provided. If the project is omitted, the default
+ * would be used.
*
* @param request: GetFeatureSetRequest Request containing filter parameters.
* @return Returns a GetFeatureSetResponse containing a feature set..
@@ -94,8 +95,9 @@ public GetFeatureSetResponse getFeatureSet(GetFeatureSetRequest request)
if (request.getName().isEmpty()) {
throw new IllegalArgumentException("No feature set name provided");
}
+ // Autofill default project if project is not specified
if (request.getProject().isEmpty()) {
- throw new IllegalArgumentException("No project provided");
+ request = request.toBuilder().setProject(Project.DEFAULT_NAME).build();
}
FeatureSet featureSet;
@@ -117,7 +119,8 @@ public GetFeatureSetResponse getFeatureSet(GetFeatureSetRequest request)
* projects.
*
*
Project name can be explicitly provided, or an asterisk can be provided to match all
- * projects. It is not possible to provide a combination of asterisks/wildcards and text.
+ * projects. It is not possible to provide a combination of asterisks/wildcards and text. If the
+ * project name is omitted, the default project would be used.
*
*
The feature set name in the filter accepts an asterisk as a wildcard. All matching feature
* sets will be returned. Regex is not supported. Explicitly defining a feature set name is not
@@ -131,14 +134,19 @@ public ListFeatureSetsResponse listFeatureSets(ListFeatureSetsRequest.Filter fil
String name = filter.getFeatureSetName();
String project = filter.getProject();
- if (project.isEmpty() || name.isEmpty()) {
+ if (name.isEmpty()) {
throw new IllegalArgumentException(
- "Invalid listFeatureSetRequest, missing arguments. Must provide project and feature set name.");
+ "Invalid listFeatureSetRequest, missing arguments. Must provide feature set name:");
}
checkValidCharactersAllowAsterisk(name, "featureSetName");
checkValidCharactersAllowAsterisk(project, "projectName");
+ // Autofill default project if project not specified
+ if (project.isEmpty()) {
+ project = Project.DEFAULT_NAME;
+ }
+
List featureSets = new ArrayList() {};
if (project.contains("*")) {
@@ -227,12 +235,21 @@ public ListStoresResponse listStores(ListStoresRequest.Filter filter) {
*
* This function is idempotent. If no changes are detected in the incoming featureSet's schema,
* this method will update the incoming featureSet spec with the latest version stored in the
- * repository, and return that.
+ * repository, and return that. If project is not specified in the given featureSet, will assign
+ * the featureSet to the'default' project.
*
* @param newFeatureSet Feature set that will be created or updated.
*/
public ApplyFeatureSetResponse applyFeatureSet(FeatureSetProto.FeatureSet newFeatureSet)
throws InvalidProtocolBufferException {
+ // Autofill default project if not specified
+ if (newFeatureSet.getSpec().getProject().isEmpty()) {
+ newFeatureSet =
+ newFeatureSet
+ .toBuilder()
+ .setSpec(newFeatureSet.getSpec().toBuilder().setProject(Project.DEFAULT_NAME).build())
+ .build();
+ }
// Validate incoming feature set
FeatureSetValidator.validateSpec(newFeatureSet);
diff --git a/core/src/test/java/feast/core/job/JobUpdateTaskTest.java b/core/src/test/java/feast/core/job/JobUpdateTaskTest.java
index 3225dcd76e5..d1826738019 100644
--- a/core/src/test/java/feast/core/job/JobUpdateTaskTest.java
+++ b/core/src/test/java/feast/core/job/JobUpdateTaskTest.java
@@ -53,8 +53,7 @@ public class JobUpdateTaskTest {
private static final FeatureSetProto.FeatureSet.Builder fsBuilder =
FeatureSetProto.FeatureSet.newBuilder().setMeta(FeatureSetMeta.newBuilder());
- private static final FeatureSetSpec.Builder specBuilder =
- FeatureSetSpec.newBuilder().setProject("project1");
+ private static final FeatureSetSpec.Builder specBuilder = FeatureSetSpec.newBuilder();
@Mock private JobManager jobManager;
diff --git a/core/src/test/java/feast/core/service/AccessManagementServiceTest.java b/core/src/test/java/feast/core/service/AccessManagementServiceTest.java
new file mode 100644
index 00000000000..15be203709f
--- /dev/null
+++ b/core/src/test/java/feast/core/service/AccessManagementServiceTest.java
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright 2018-2019 The Feast Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package feast.core.service;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import feast.core.dao.ProjectRepository;
+import feast.core.model.Project;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+
+public class AccessManagementServiceTest {
+ @Rule public ExpectedException expectedException = ExpectedException.none();
+ // mocks
+ @Mock private ProjectRepository projectRepository;
+ // dummy models
+ private Project defaultProject;
+ private Project testProject;
+
+ // test target
+ private AccessManagementService accessService;
+
+ @Before
+ public void setup() {
+ initMocks(this);
+ // setup dummy models for testing
+ this.defaultProject = new Project(Project.DEFAULT_NAME);
+ this.testProject = new Project("project");
+ // setup test target
+ when(this.projectRepository.existsById(Project.DEFAULT_NAME)).thenReturn(false);
+ this.accessService = new AccessManagementService(this.projectRepository);
+ }
+
+ @Test
+ public void testDefaultProjectCreateInConstructor() {
+ verify(this.projectRepository).saveAndFlush(this.defaultProject);
+ }
+
+ @Test
+ public void testArchiveProject() {
+ when(this.projectRepository.findById("project")).thenReturn(Optional.of(this.testProject));
+ this.accessService.archiveProject("project");
+ this.testProject.setArchived(true);
+ verify(this.projectRepository).saveAndFlush(this.testProject);
+ // reset archived flag
+ this.testProject.setArchived(false);
+ }
+
+ @Test
+ public void shouldNotArchiveDefaultProject() {
+ expectedException.expect(IllegalArgumentException.class);
+ this.accessService.archiveProject(Project.DEFAULT_NAME);
+ }
+}
diff --git a/core/src/test/java/feast/core/service/JobServiceTest.java b/core/src/test/java/feast/core/service/JobServiceTest.java
index 87b32d1a208..ff056287f9b 100644
--- a/core/src/test/java/feast/core/service/JobServiceTest.java
+++ b/core/src/test/java/feast/core/service/JobServiceTest.java
@@ -69,7 +69,6 @@ public class JobServiceTest {
// test target
public JobService jobService;
- /* unit test setup */
@Before
public void setup() {
initMocks(this);
@@ -107,7 +106,6 @@ public void setup() {
new JobService(this.jobRepository, this.specService, Arrays.asList(this.jobManager));
}
- // setup fake spec service
public void setupSpecService() {
try {
ListFeatureSetsResponse response =
@@ -124,7 +122,6 @@ public void setupSpecService() {
}
}
- // setup fake job repository
public void setupJobRepository() {
when(this.jobRepository.findById(this.job.getId())).thenReturn(Optional.of(this.job));
when(this.jobRepository.findByStoreName(this.dataStore.getName()))
@@ -134,14 +131,12 @@ public void setupJobRepository() {
when(this.jobRepository.findAll()).thenReturn(Arrays.asList(this.job));
}
- // TODO: setup fake job manager
public void setupJobManager() {
when(this.jobManager.getRunnerType()).thenReturn(Runner.DATAFLOW);
when(this.jobManager.restartJob(this.job))
.thenReturn(this.newDummyJob(this.job.getId(), this.job.getExtId(), JobStatus.PENDING));
}
- // dummy model constructorss
private FeatureSet newDummyFeatureSet(String name, int version, String project) {
Feature feature = TestObjectFactory.CreateFeature(name + "_feature", Enum.INT64);
Entity entity = TestObjectFactory.CreateEntity(name + "_entity", Enum.STRING);
@@ -203,7 +198,6 @@ private List newDummyListRequestFilters() {
.build());
}
- /* unit tests */
private ListIngestionJobsResponse tryListJobs(ListIngestionJobsRequest request) {
ListIngestionJobsResponse response = null;
try {
@@ -216,7 +210,6 @@ private ListIngestionJobsResponse tryListJobs(ListIngestionJobsRequest request)
return response;
}
- // list jobs
@Test
public void testListJobsById() {
ListIngestionJobsRequest.Filter filter =
@@ -275,7 +268,6 @@ public void testListIngestionJobByFeatureSetReference() {
assertThat(this.tryListJobs(request).getJobs(0), equalTo(this.ingestionJob));
}
- // stop jobs
private StopIngestionJobResponse tryStopJob(
StopIngestionJobRequest request, boolean expectError) {
StopIngestionJobResponse response = null;
diff --git a/core/src/test/java/feast/core/service/SpecServiceTest.java b/core/src/test/java/feast/core/service/SpecServiceTest.java
index 5a9c7c161f3..e584ee71e00 100644
--- a/core/src/test/java/feast/core/service/SpecServiceTest.java
+++ b/core/src/test/java/feast/core/service/SpecServiceTest.java
@@ -1,6 +1,6 @@
/*
* SPDX-License-Identifier: Apache-2.0
- * Copyright 2018-2019 The Feast Authors
+ * Copyright 2018-2020 The Feast Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
import feast.proto.core.CoreServiceProto.ApplyFeatureSetResponse;
import feast.proto.core.CoreServiceProto.ApplyFeatureSetResponse.Status;
import feast.proto.core.CoreServiceProto.GetFeatureSetRequest;
+import feast.proto.core.CoreServiceProto.GetFeatureSetResponse;
import feast.proto.core.CoreServiceProto.ListFeatureSetsRequest.Filter;
import feast.proto.core.CoreServiceProto.ListFeatureSetsResponse;
import feast.proto.core.CoreServiceProto.ListStoresRequest;
@@ -105,11 +106,13 @@ public void setUp() {
Feature f3f1 = TestObjectFactory.CreateFeature("f3f1", Enum.INT64);
Feature f3f2 = TestObjectFactory.CreateFeature("f3f2", Enum.INT64);
Entity f3e1 = TestObjectFactory.CreateEntity("f3e1", Enum.STRING);
- FeatureSet featureSet3v1 =
+ FeatureSet featureSet3 =
TestObjectFactory.CreateFeatureSet(
"f3", "project1", Arrays.asList(f3e1), Arrays.asList(f3f2, f3f1));
- featureSets = Arrays.asList(featureSet1, featureSet2);
+ FeatureSet featureSet4 = newDummyFeatureSet("f4", Project.DEFAULT_NAME);
+ featureSets = Arrays.asList(featureSet1, featureSet2, featureSet3, featureSet4);
+
when(featureSetRepository.findAll()).thenReturn(featureSets);
when(featureSetRepository.findAllByOrderByNameAsc()).thenReturn(featureSets);
when(featureSetRepository.findFeatureSetByNameAndProject_Name("f1", "project1"))
@@ -160,15 +163,6 @@ public void shouldGetAllFeatureSetsIfOnlyWildcardsProvided()
assertThat(actual, equalTo(expected));
}
- @Test
- public void listFeatureSetShouldFailIfFeatureSetProvidedWithoutProject()
- throws InvalidProtocolBufferException {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage(
- "Invalid listFeatureSetRequest, missing arguments. Must provide project and feature set name.");
- specService.listFeatureSets(Filter.newBuilder().setFeatureSetName("f1").build());
- }
-
@Test
public void shouldGetAllFeatureSetsMatchingNameWithWildcardSearch()
throws InvalidProtocolBufferException {
@@ -511,6 +505,26 @@ public void applyFeatureSetShouldCreateProjectWhenNotAlreadyExists()
equalTo(incomingFeatureSet.getSpec().getProject()));
}
+ @Test
+ public void applyFeatureSetShouldUsedDefaultProjectIfUnspecified()
+ throws InvalidProtocolBufferException {
+ Feature f3f1 = TestObjectFactory.CreateFeature("f3f1", Enum.INT64);
+ Feature f3f2 = TestObjectFactory.CreateFeature("f3f2", Enum.INT64);
+ Entity f3e1 = TestObjectFactory.CreateEntity("f3e1", Enum.STRING);
+
+ // In protov3, unspecified project defaults to ""
+ FeatureSetProto.FeatureSet incomingFeatureSet =
+ TestObjectFactory.CreateFeatureSet("f3", "", Arrays.asList(f3e1), Arrays.asList(f3f2, f3f1))
+ .toProto();
+ ApplyFeatureSetResponse applyFeatureSetResponse =
+ specService.applyFeatureSet(incomingFeatureSet);
+ assertThat(applyFeatureSetResponse.getStatus(), equalTo(Status.CREATED));
+
+ assertThat(
+ applyFeatureSetResponse.getFeatureSet().getSpec().getProject(),
+ equalTo(Project.DEFAULT_NAME));
+ }
+
@Test
public void applyFeatureSetShouldFailWhenProjectIsArchived()
throws InvalidProtocolBufferException {
@@ -661,10 +675,20 @@ public void shouldDoNothingIfNoChange() throws InvalidProtocolBufferException {
}
@Test
- public void shouldFailIfGetFeatureSetWithoutProject() throws InvalidProtocolBufferException {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("No project provided");
- specService.getFeatureSet(GetFeatureSetRequest.newBuilder().setName("f1").build());
+ public void getOrListFeatureSetShouldUseDefaultProjectIfProjectUnspecified()
+ throws InvalidProtocolBufferException {
+ when(featureSetRepository.findFeatureSetByNameAndProject_Name("f4", Project.DEFAULT_NAME))
+ .thenReturn(featureSets.get(3));
+ FeatureSet expected = featureSets.get(3);
+ // check getFeatureSet()
+ GetFeatureSetResponse getResponse =
+ specService.getFeatureSet(GetFeatureSetRequest.newBuilder().setName("f4").build());
+ assertThat(getResponse.getFeatureSet(), equalTo(expected.toProto()));
+
+ // check listFeatureSets()
+ ListFeatureSetsResponse listResponse =
+ specService.listFeatureSets(Filter.newBuilder().setFeatureSetName("f4").build());
+ assertThat(listResponse.getFeatureSetsList(), equalTo(Arrays.asList(expected.toProto())));
}
private FeatureSet newDummyFeatureSet(String name, String project) {
diff --git a/protos/feast/core/CoreService.proto b/protos/feast/core/CoreService.proto
index e81a260731b..3cd3c756830 100644
--- a/protos/feast/core/CoreService.proto
+++ b/protos/feast/core/CoreService.proto
@@ -65,8 +65,8 @@ service CoreService {
rpc UpdateStore (UpdateStoreRequest) returns (UpdateStoreResponse);
// Creates a project. Projects serve as namespaces within which resources like features will be
- // created. Both feature set names as well as field names must be unique within a project. Project
- // names themselves must be globally unique.
+ // created. Feature set names as must be unique within a project while field (Feature/Entity) names
+ // must be unique within a Feature Set. Project names themselves must be globally unique.
rpc CreateProject (CreateProjectRequest) returns (CreateProjectResponse);
// Archives a project. Archived projects will continue to exist and function, but won't be visible
@@ -99,7 +99,7 @@ service CoreService {
// Request for a single feature set
message GetFeatureSetRequest {
- // Name of project the feature set belongs to (required)
+ // Name of project the feature set belongs to. If omitted will default to 'default' project.
string project = 3;
// Name of feature set (required).
@@ -122,6 +122,7 @@ message ListFeatureSetsRequest {
// If an asterisk is provided, filtering on projects will be disabled. All projects will
// be matched. 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'.
string project = 3;
// Name of the desired feature set. Asterisks can be used as wildcards in the name.
@@ -153,6 +154,9 @@ message ListStoresResponse {
}
message ApplyFeatureSetRequest {
+ // Feature set version
+ // If project is unspecified, will default to 'default' project.
+ // If project specified does not exist, the project would be automatically created.
feast.core.FeatureSet feature_set = 1;
}
diff --git a/protos/feast/serving/ServingService.proto b/protos/feast/serving/ServingService.proto
index edef4a4a228..cd7d51bd59c 100644
--- a/protos/feast/serving/ServingService.proto
+++ b/protos/feast/serving/ServingService.proto
@@ -19,7 +19,6 @@ syntax = "proto3";
package feast.serving;
import "google/protobuf/timestamp.proto";
-import "google/protobuf/duration.proto";
import "feast/types/Value.proto";
option java_package = "feast.proto.serving";
@@ -63,18 +62,19 @@ message GetFeastServingInfoResponse {
}
message FeatureReference {
- // Project name
+ // Project name. This field is optional, if unspecified will default to 'default'.
string project = 1;
// Feature name
string name = 2;
- // The features will be retrieved if:
- // entity_timestamp - max_age <= event_timestamp <= entity_timestamp
- //
- // If unspecified the default max_age specified in FeatureSetSpec will
- // be used.
- google.protobuf.Duration max_age = 4;
+ // Feature set name specifying the feature set of this referenced feature.
+ // This field is optional if the feature referenced is unique across the project
+ // in which case the feature set would be automatically infered
+ string feature_set = 5;
+
+ // Feature version and max_age was removed in v0.5.0
+ reserved 3, 4;
}
message GetOnlineFeaturesRequest {
diff --git a/sdk/go/client.go b/sdk/go/client.go
index edb135e4655..38c9e2fb7e5 100644
--- a/sdk/go/client.go
+++ b/sdk/go/client.go
@@ -6,6 +6,7 @@ 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"
@@ -50,6 +51,31 @@ func (fc *GrpcClient) GetOnlineFeatures(ctx context.Context, req *OnlineFeatures
}
resp, err := fc.cli.GetOnlineFeatures(ctx, featuresRequest)
+ // collect unqiue entity refs from entity rows
+ var entityRefs map[string]struct{}
+ for _, entityRows := range req.Entities {
+ for ref, _ := range entityRows {
+ entityRefs[ref] = struct{}{}
+ }
+ }
+
+ // strip projects from to projects
+ for _, fieldValue := range resp.GetFieldValues() {
+ var stripFields map[string]*types.Value
+ for refStr, value := range fieldValue.Fields {
+ _, isEntity := entityRefs[refStr]
+ if !isEntity { // is feature ref
+ featureRef, err := parseFeatureRef(refStr, true)
+ if err != nil {
+ return nil, err
+ }
+ stripRefStr := toFeatureRefStr(featureRef)
+ stripFields[stripRefStr] = value
+ }
+ }
+ fieldValue.Fields = stripFields
+ }
+
return &OnlineFeaturesResponse{RawResponse: resp}, err
}
diff --git a/sdk/go/protos/feast/core/CoreService.pb.go b/sdk/go/protos/feast/core/CoreService.pb.go
index 1af820f50bb..75f988ed528 100644
--- a/sdk/go/protos/feast/core/CoreService.pb.go
+++ b/sdk/go/protos/feast/core/CoreService.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/CoreService.proto
@@ -45,6 +45,7 @@ const (
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
+// TODO: 0 should correspond to invalid rather than NO_CHANGE
type ApplyFeatureSetResponse_Status int32
const (
@@ -155,7 +156,7 @@ type GetFeatureSetRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // Name of project the feature set belongs to (required)
+ // Name of project the feature set belongs to. If omitted will default to 'default' project.
Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"`
// Name of feature set (required).
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
@@ -449,6 +450,9 @@ type ApplyFeatureSetRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
+ // Feature set version
+ // If project is unspecified, will default to 'default' project.
+ // If project specified does not exist, the project would be automatically created.
FeatureSet *FeatureSet `protobuf:"bytes,1,opt,name=feature_set,json=featureSet,proto3" json:"feature_set,omitempty"`
}
@@ -1280,6 +1284,7 @@ type ListFeatureSetsRequest_Filter struct {
// If an asterisk is provided, filtering on projects will be disabled. All projects will
// be matched. 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"`
// Name of the desired feature set. Asterisks can be used as wildcards in the name.
// Matching on names is only permitted if a specific project is defined. It is disallowed
@@ -1650,13 +1655,13 @@ var file_feast_core_CoreService_proto_rawDesc = []byte{
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, 0x4f, 0x0a, 0x0a, 0x66, 0x65,
- 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x10, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65,
- 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 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 (
@@ -2146,7 +2151,7 @@ type CoreServiceClient interface {
// All changes except the following are valid:
// - Changes to feature set id (name, project)
// - Changes to entities
- // - Changes to feature type
+ // - Changes to feature name and type
ApplyFeatureSet(ctx context.Context, in *ApplyFeatureSetRequest, opts ...grpc.CallOption) (*ApplyFeatureSetResponse, error)
// Updates core with the configuration of the store.
//
@@ -2154,8 +2159,8 @@ type CoreServiceClient interface {
// start or update the necessary feature population jobs for the updated store.
UpdateStore(ctx context.Context, in *UpdateStoreRequest, opts ...grpc.CallOption) (*UpdateStoreResponse, error)
// Creates a project. Projects serve as namespaces within which resources like features will be
- // created. Both feature set names as well as field names must be unique within a project. Project
- // names themselves must be globally unique.
+ // created. Feature set names as must be unique within a project while field (Feature/Entity) names
+ // must be unique within a Feature Set. Project names themselves must be globally unique.
CreateProject(ctx context.Context, in *CreateProjectRequest, opts ...grpc.CallOption) (*CreateProjectResponse, error)
// Archives a project. Archived projects will continue to exist and function, but won't be visible
// through the Core API. Any existing ingestion or serving requests will continue to function,
@@ -2322,7 +2327,7 @@ type CoreServiceServer interface {
// All changes except the following are valid:
// - Changes to feature set id (name, project)
// - Changes to entities
- // - Changes to feature type
+ // - Changes to feature name and type
ApplyFeatureSet(context.Context, *ApplyFeatureSetRequest) (*ApplyFeatureSetResponse, error)
// Updates core with the configuration of the store.
//
@@ -2330,8 +2335,8 @@ type CoreServiceServer interface {
// start or update the necessary feature population jobs for the updated store.
UpdateStore(context.Context, *UpdateStoreRequest) (*UpdateStoreResponse, error)
// Creates a project. Projects serve as namespaces within which resources like features will be
- // created. Both feature set names as well as field names must be unique within a project. Project
- // names themselves must be globally unique.
+ // created. Feature set names as must be unique within a project while field (Feature/Entity) names
+ // must be unique within a Feature Set. Project names themselves must be globally unique.
CreateProject(context.Context, *CreateProjectRequest) (*CreateProjectResponse, error)
// Archives a project. Archived projects will continue to exist and function, but won't be visible
// through the Core API. Any existing ingestion or serving requests will continue to function,
diff --git a/sdk/go/protos/feast/core/FeatureSet.pb.go b/sdk/go/protos/feast/core/FeatureSet.pb.go
index 7f072114b61..3c6441f2ac9 100644
--- a/sdk/go/protos/feast/core/FeatureSet.pb.go
+++ b/sdk/go/protos/feast/core/FeatureSet.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/FeatureSet.proto
@@ -325,6 +325,8 @@ type FeatureSpec struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Value type of the feature.
ValueType types.ValueType_Enum `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=feast.types.ValueType_Enum" json:"value_type,omitempty"`
+ // Labels for user defined metadata on a feature
+ Labels map[string]string `protobuf:"bytes,16,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Types that are assignable to PresenceConstraints:
// *FeatureSpec_Presence
// *FeatureSpec_GroupPresence
@@ -352,8 +354,6 @@ type FeatureSpec struct {
// *FeatureSpec_TimeDomain
// *FeatureSpec_TimeOfDayDomain
DomainInfo isFeatureSpec_DomainInfo `protobuf_oneof:"domain_info"`
- // Labels for user defined metadata on a feature
- Labels map[string]string `protobuf:"bytes,19,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 *FeatureSpec) Reset() {
@@ -402,6 +402,13 @@ func (x *FeatureSpec) GetValueType() types.ValueType_Enum {
return types.ValueType_INVALID
}
+func (x *FeatureSpec) GetLabels() map[string]string {
+ if x != nil {
+ return x.Labels
+ }
+ return nil
+}
+
func (m *FeatureSpec) GetPresenceConstraints() isFeatureSpec_PresenceConstraints {
if m != nil {
return m.PresenceConstraints
@@ -535,25 +542,18 @@ func (x *FeatureSpec) GetTimeOfDayDomain() *v0.TimeOfDayDomain {
return nil
}
-func (x *FeatureSpec) GetLabels() map[string]string {
- if x != nil {
- return x.Labels
- }
- return nil
-}
-
type isFeatureSpec_PresenceConstraints interface {
isFeatureSpec_PresenceConstraints()
}
type FeatureSpec_Presence struct {
// Constraints on the presence of this feature in the examples.
- Presence *v0.FeaturePresence `protobuf:"bytes,3,opt,name=presence,proto3,oneof"`
+ Presence *v0.FeaturePresence `protobuf:"bytes,30,opt,name=presence,proto3,oneof"`
}
type FeatureSpec_GroupPresence struct {
// Only used in the context of a "group" context, e.g., inside a sequence.
- GroupPresence *v0.FeaturePresenceWithinGroup `protobuf:"bytes,4,opt,name=group_presence,json=groupPresence,proto3,oneof"`
+ GroupPresence *v0.FeaturePresenceWithinGroup `protobuf:"bytes,31,opt,name=group_presence,json=groupPresence,proto3,oneof"`
}
func (*FeatureSpec_Presence) isFeatureSpec_PresenceConstraints() {}
@@ -567,13 +567,13 @@ type isFeatureSpec_ShapeType interface {
type FeatureSpec_Shape struct {
// The feature has a fixed shape corresponding to a multi-dimensional
// tensor.
- Shape *v0.FixedShape `protobuf:"bytes,5,opt,name=shape,proto3,oneof"`
+ Shape *v0.FixedShape `protobuf:"bytes,32,opt,name=shape,proto3,oneof"`
}
type FeatureSpec_ValueCount struct {
// The feature doesn't have a well defined shape. All we know are limits on
// the minimum and maximum number of values.
- ValueCount *v0.ValueCount `protobuf:"bytes,6,opt,name=value_count,json=valueCount,proto3,oneof"`
+ ValueCount *v0.ValueCount `protobuf:"bytes,33,opt,name=value_count,json=valueCount,proto3,oneof"`
}
func (*FeatureSpec_Shape) isFeatureSpec_ShapeType() {}
@@ -586,53 +586,53 @@ type isFeatureSpec_DomainInfo interface {
type FeatureSpec_Domain struct {
// Reference to a domain defined at the schema level.
- Domain string `protobuf:"bytes,7,opt,name=domain,proto3,oneof"`
+ Domain string `protobuf:"bytes,34,opt,name=domain,proto3,oneof"`
}
type FeatureSpec_IntDomain struct {
// Inline definitions of domains.
- IntDomain *v0.IntDomain `protobuf:"bytes,8,opt,name=int_domain,json=intDomain,proto3,oneof"`
+ IntDomain *v0.IntDomain `protobuf:"bytes,35,opt,name=int_domain,json=intDomain,proto3,oneof"`
}
type FeatureSpec_FloatDomain struct {
- FloatDomain *v0.FloatDomain `protobuf:"bytes,9,opt,name=float_domain,json=floatDomain,proto3,oneof"`
+ FloatDomain *v0.FloatDomain `protobuf:"bytes,36,opt,name=float_domain,json=floatDomain,proto3,oneof"`
}
type FeatureSpec_StringDomain struct {
- StringDomain *v0.StringDomain `protobuf:"bytes,10,opt,name=string_domain,json=stringDomain,proto3,oneof"`
+ StringDomain *v0.StringDomain `protobuf:"bytes,37,opt,name=string_domain,json=stringDomain,proto3,oneof"`
}
type FeatureSpec_BoolDomain struct {
- BoolDomain *v0.BoolDomain `protobuf:"bytes,11,opt,name=bool_domain,json=boolDomain,proto3,oneof"`
+ BoolDomain *v0.BoolDomain `protobuf:"bytes,38,opt,name=bool_domain,json=boolDomain,proto3,oneof"`
}
type FeatureSpec_StructDomain struct {
- StructDomain *v0.StructDomain `protobuf:"bytes,12,opt,name=struct_domain,json=structDomain,proto3,oneof"`
+ StructDomain *v0.StructDomain `protobuf:"bytes,39,opt,name=struct_domain,json=structDomain,proto3,oneof"`
}
type FeatureSpec_NaturalLanguageDomain struct {
// Supported semantic domains.
- NaturalLanguageDomain *v0.NaturalLanguageDomain `protobuf:"bytes,13,opt,name=natural_language_domain,json=naturalLanguageDomain,proto3,oneof"`
+ NaturalLanguageDomain *v0.NaturalLanguageDomain `protobuf:"bytes,40,opt,name=natural_language_domain,json=naturalLanguageDomain,proto3,oneof"`
}
type FeatureSpec_ImageDomain struct {
- ImageDomain *v0.ImageDomain `protobuf:"bytes,14,opt,name=image_domain,json=imageDomain,proto3,oneof"`
+ ImageDomain *v0.ImageDomain `protobuf:"bytes,41,opt,name=image_domain,json=imageDomain,proto3,oneof"`
}
type FeatureSpec_MidDomain struct {
- MidDomain *v0.MIDDomain `protobuf:"bytes,15,opt,name=mid_domain,json=midDomain,proto3,oneof"`
+ MidDomain *v0.MIDDomain `protobuf:"bytes,42,opt,name=mid_domain,json=midDomain,proto3,oneof"`
}
type FeatureSpec_UrlDomain struct {
- UrlDomain *v0.URLDomain `protobuf:"bytes,16,opt,name=url_domain,json=urlDomain,proto3,oneof"`
+ UrlDomain *v0.URLDomain `protobuf:"bytes,43,opt,name=url_domain,json=urlDomain,proto3,oneof"`
}
type FeatureSpec_TimeDomain struct {
- TimeDomain *v0.TimeDomain `protobuf:"bytes,17,opt,name=time_domain,json=timeDomain,proto3,oneof"`
+ TimeDomain *v0.TimeDomain `protobuf:"bytes,44,opt,name=time_domain,json=timeDomain,proto3,oneof"`
}
type FeatureSpec_TimeOfDayDomain struct {
- TimeOfDayDomain *v0.TimeOfDayDomain `protobuf:"bytes,18,opt,name=time_of_day_domain,json=timeOfDayDomain,proto3,oneof"`
+ TimeOfDayDomain *v0.TimeOfDayDomain `protobuf:"bytes,45,opt,name=time_of_day_domain,json=timeOfDayDomain,proto3,oneof"`
}
func (*FeatureSpec_Domain) isFeatureSpec_DomainInfo() {}
@@ -743,7 +743,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, 0x82, 0x03, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x88, 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,
@@ -767,122 +767,124 @@ var file_feast_core_FeatureSet_proto_rawDesc = []byte{
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, 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, 0x94, 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, 0x45, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73,
- 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e,
+ 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, 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, 0x04, 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, 0x05, 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, 0x06, 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, 0x07, 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, 0x08, 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, 0x09, 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, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
+ 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, 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, 0x0b, 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, 0x0c, 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, 0x0d, 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, 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, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66,
+ 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,
- 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, 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x13, 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, 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, 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, 0x4c, 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, 0x10, 0x0a,
- 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x42,
- 0x4e, 0x0a, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, 0x46,
- 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x2f,
- 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b,
- 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,
+ 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,
+ 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, 0x4c, 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,
+ 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,
}
var (
@@ -938,22 +940,22 @@ var file_feast_core_FeatureSet_proto_depIdxs = []int32{
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
- 11, // 9: feast.core.FeatureSpec.presence:type_name -> tensorflow.metadata.v0.FeaturePresence
- 12, // 10: feast.core.FeatureSpec.group_presence:type_name -> tensorflow.metadata.v0.FeaturePresenceWithinGroup
- 13, // 11: feast.core.FeatureSpec.shape:type_name -> tensorflow.metadata.v0.FixedShape
- 14, // 12: feast.core.FeatureSpec.value_count:type_name -> tensorflow.metadata.v0.ValueCount
- 15, // 13: feast.core.FeatureSpec.int_domain:type_name -> tensorflow.metadata.v0.IntDomain
- 16, // 14: feast.core.FeatureSpec.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain
- 17, // 15: feast.core.FeatureSpec.string_domain:type_name -> tensorflow.metadata.v0.StringDomain
- 18, // 16: feast.core.FeatureSpec.bool_domain:type_name -> tensorflow.metadata.v0.BoolDomain
- 19, // 17: feast.core.FeatureSpec.struct_domain:type_name -> tensorflow.metadata.v0.StructDomain
- 20, // 18: feast.core.FeatureSpec.natural_language_domain:type_name -> tensorflow.metadata.v0.NaturalLanguageDomain
- 21, // 19: feast.core.FeatureSpec.image_domain:type_name -> tensorflow.metadata.v0.ImageDomain
- 22, // 20: feast.core.FeatureSpec.mid_domain:type_name -> tensorflow.metadata.v0.MIDDomain
- 23, // 21: feast.core.FeatureSpec.url_domain:type_name -> tensorflow.metadata.v0.URLDomain
- 24, // 22: feast.core.FeatureSpec.time_domain:type_name -> tensorflow.metadata.v0.TimeDomain
- 25, // 23: feast.core.FeatureSpec.time_of_day_domain:type_name -> tensorflow.metadata.v0.TimeOfDayDomain
- 7, // 24: feast.core.FeatureSpec.labels:type_name -> feast.core.FeatureSpec.LabelsEntry
+ 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
0, // 26: feast.core.FeatureSetMeta.status:type_name -> feast.core.FeatureSetStatus
27, // [27:27] is the sub-list for method output_type
diff --git a/sdk/go/protos/feast/core/FeatureSetReference.pb.go b/sdk/go/protos/feast/core/FeatureSetReference.pb.go
index 1667565bd23..3da39ad922a 100644
--- a/sdk/go/protos/feast/core/FeatureSetReference.pb.go
+++ b/sdk/go/protos/feast/core/FeatureSetReference.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/FeatureSetReference.proto
@@ -105,15 +105,16 @@ var file_feast_core_FeatureSetReference_proto_rawDesc = []byte{
0x0a, 0x24, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61,
0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f,
- 0x72, 0x65, 0x22, 0x43, 0x0a, 0x13, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74,
+ 0x72, 0x65, 0x22, 0x49, 0x0a, 0x13, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74,
0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f,
0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a,
0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x57, 0x0a, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74,
- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x18, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65,
- 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a,
- 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65,
- 0x6b, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x42, 0x61, 0x0a,
+ 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72,
+ 0x65, 0x42, 0x18, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66,
+ 0x65, 0x72, 0x65, 0x6e, 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,
}
diff --git a/sdk/go/protos/feast/core/IngestionJob.pb.go b/sdk/go/protos/feast/core/IngestionJob.pb.go
index 3623d95d885..bf30f25168f 100644
--- a/sdk/go/protos/feast/core/IngestionJob.pb.go
+++ b/sdk/go/protos/feast/core/IngestionJob.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/IngestionJob.proto
@@ -248,12 +248,13 @@ var file_feast_core_IngestionJob_proto_rawDesc = []byte{
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, 0x50, 0x0a, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 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, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
- 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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,
+ 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 (
diff --git a/sdk/go/protos/feast/core/Runner.pb.go b/sdk/go/protos/feast/core/Runner.pb.go
index ae9f7c4e7d3..54e03714d2a 100644
--- a/sdk/go/protos/feast/core/Runner.pb.go
+++ b/sdk/go/protos/feast/core/Runner.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/Runner.proto
@@ -290,12 +290,13 @@ var file_feast_core_Runner_proto_rawDesc = []byte{
0x4e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x64, 0x65,
0x61, 0x64, 0x4c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65,
0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x61, 0x64, 0x4c, 0x65, 0x74,
- 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x42, 0x4a, 0x0a, 0x0a,
- 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0b, 0x52, 0x75, 0x6e, 0x6e,
- 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
- 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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,
+ 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x42, 0x54, 0x0a, 0x10,
+ 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65,
+ 0x42, 0x0b, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 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/core/Source.pb.go b/sdk/go/protos/feast/core/Source.pb.go
index 368f50c5acb..b29dc5af96c 100644
--- a/sdk/go/protos/feast/core/Source.pb.go
+++ b/sdk/go/protos/feast/core/Source.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/Source.proto
@@ -266,12 +266,13 @@ var file_feast_core_Source_proto_rawDesc = []byte{
0x28, 0x05, 0x52, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46,
0x61, 0x63, 0x74, 0x6f, 0x72, 0x2a, 0x24, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00,
- 0x12, 0x09, 0x0a, 0x05, 0x4b, 0x41, 0x46, 0x4b, 0x41, 0x10, 0x01, 0x42, 0x4a, 0x0a, 0x0a, 0x66,
- 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0b, 0x53, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
- 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 0x09, 0x0a, 0x05, 0x4b, 0x41, 0x46, 0x4b, 0x41, 0x10, 0x01, 0x42, 0x54, 0x0a, 0x10, 0x66,
+ 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42,
+ 0x0b, 0x53, 0x6f, 0x75, 0x72, 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 (
diff --git a/sdk/go/protos/feast/core/Store.pb.go b/sdk/go/protos/feast/core/Store.pb.go
index f3b7728ab97..866dc71fe94 100644
--- a/sdk/go/protos/feast/core/Store.pb.go
+++ b/sdk/go/protos/feast/core/Store.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/core/Store.proto
@@ -74,6 +74,7 @@ const (
// ====================|==================|================================
// - event_timestamp | TIMESTAMP | event time of the FeatureRow
// - created_timestamp | TIMESTAMP | processing time of the ingestion of the FeatureRow
+ // - ingestion_id | STRING | unique id identifying groups of rows that have been ingested together
// - job_id | STRING | identifier for the job that writes the FeatureRow to the corresponding BigQuery table
//
// BigQuery table created will be partitioned by the field "event_timestamp"
@@ -642,7 +643,7 @@ 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, 0xae, 0x09, 0x0a, 0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12,
+ 0x63, 0x6f, 0x72, 0x65, 0x22, 0xb4, 0x09, 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,
@@ -707,20 +708,21 @@ var file_feast_core_Store_proto_rawDesc = []byte{
0x02, 0x20, 0x01, 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, 0x3c, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73,
+ 0x78, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x42, 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, 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, 0x49, 0x0a, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63,
- 0x6f, 0x72, 0x65, 0x42, 0x0a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a,
- 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65,
- 0x6b, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70,
+ 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,
}
diff --git a/sdk/go/protos/feast/serving/ServingService.pb.go b/sdk/go/protos/feast/serving/ServingService.pb.go
index 0fd8c09bc71..9e5a151b7ee 100644
--- a/sdk/go/protos/feast/serving/ServingService.pb.go
+++ b/sdk/go/protos/feast/serving/ServingService.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/serving/ServingService.proto
@@ -25,7 +25,6 @@ import (
context "context"
types "github.com/feast-dev/feast/sdk/go/protos/feast/types"
proto "github.com/golang/protobuf/proto"
- duration "github.com/golang/protobuf/ptypes/duration"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
@@ -355,16 +354,14 @@ type FeatureReference struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // Project name
+ // Project name. This field is optional, if unspecified will default to 'default'.
Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"`
// Feature name
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
- // The features will be retrieved if:
- // entity_timestamp - max_age <= event_timestamp <= entity_timestamp
- //
- // If unspecified the default max_age specified in FeatureSetSpec will
- // be used.
- MaxAge *duration.Duration `protobuf:"bytes,4,opt,name=max_age,json=maxAge,proto3" json:"max_age,omitempty"`
+ // Feature set name specifying the feature set of this referenced feature.
+ // This field is optional if the feature referenced is unique across the project
+ // in which case the feature set would be automatically infered
+ FeatureSet string `protobuf:"bytes,5,opt,name=feature_set,json=featureSet,proto3" json:"feature_set,omitempty"`
}
func (x *FeatureReference) Reset() {
@@ -413,11 +410,11 @@ func (x *FeatureReference) GetName() string {
return ""
}
-func (x *FeatureReference) GetMaxAge() *duration.Duration {
+func (x *FeatureReference) GetFeatureSet() string {
if x != nil {
- return x.MaxAge
+ return x.FeatureSet
}
- return nil
+ return ""
}
type GetOnlineFeaturesRequest struct {
@@ -1071,8 +1068,6 @@ var file_feast_serving_ServingService_proto_rawDesc = []byte{
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x6e, 0x67, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65,
0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1c, 0x0a,
0x1a, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67,
@@ -1086,165 +1081,165 @@ var file_feast_serving_ServingService_proto_rawDesc = []byte{
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x6f,
0x62, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x6f, 0x62, 0x53, 0x74, 0x61,
- 0x67, 0x69, 0x6e, 0x67, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x74, 0x0a, 0x10,
+ 0x67, 0x69, 0x6e, 0x67, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x10,
0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32,
- 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x41,
- 0x67, 0x65, 0x22, 0xe1, 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, 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, 0x52, 0x0a, 0x0b,
- 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x31, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e,
+ 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,
+ 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,
+ 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, 0x52, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f,
+ 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 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, 0x52, 0x0a, 0x65,
+ 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x6f, 0x6d, 0x69,
+ 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,
+ 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, 0xad, 0x02,
+ 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74,
- 0x79, 0x52, 0x6f, 0x77, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x73,
- 0x12, 0x39, 0x0a, 0x19, 0x6f, 0x6d, 0x69, 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, 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, 0xad, 0x02, 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, 0xb6, 0x01, 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, 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, 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,
+ 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, 0xb6, 0x01, 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, 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, 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, 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,
+ 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, 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, 0x54, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x73, 0x74, 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, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 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 (
@@ -1282,44 +1277,42 @@ var file_feast_serving_ServingService_proto_goTypes = []interface{}{
(*GetOnlineFeaturesResponse_FieldValues)(nil), // 17: feast.serving.GetOnlineFeaturesResponse.FieldValues
nil, // 18: feast.serving.GetOnlineFeaturesResponse.FieldValues.FieldsEntry
(*DatasetSource_FileSource)(nil), // 19: feast.serving.DatasetSource.FileSource
- (*duration.Duration)(nil), // 20: google.protobuf.Duration
- (*timestamp.Timestamp)(nil), // 21: google.protobuf.Timestamp
- (*types.Value)(nil), // 22: feast.types.Value
+ (*timestamp.Timestamp)(nil), // 20: google.protobuf.Timestamp
+ (*types.Value)(nil), // 21: feast.types.Value
}
var file_feast_serving_ServingService_proto_depIdxs = []int32{
0, // 0: feast.serving.GetFeastServingInfoResponse.type:type_name -> feast.serving.FeastServingType
- 20, // 1: feast.serving.FeatureReference.max_age:type_name -> google.protobuf.Duration
- 6, // 2: feast.serving.GetOnlineFeaturesRequest.features:type_name -> feast.serving.FeatureReference
- 15, // 3: feast.serving.GetOnlineFeaturesRequest.entity_rows:type_name -> feast.serving.GetOnlineFeaturesRequest.EntityRow
- 6, // 4: feast.serving.GetBatchFeaturesRequest.features:type_name -> feast.serving.FeatureReference
- 14, // 5: feast.serving.GetBatchFeaturesRequest.dataset_source:type_name -> feast.serving.DatasetSource
- 17, // 6: feast.serving.GetOnlineFeaturesResponse.field_values:type_name -> feast.serving.GetOnlineFeaturesResponse.FieldValues
- 13, // 7: feast.serving.GetBatchFeaturesResponse.job:type_name -> feast.serving.Job
- 13, // 8: feast.serving.GetJobRequest.job:type_name -> feast.serving.Job
- 13, // 9: feast.serving.GetJobResponse.job:type_name -> feast.serving.Job
- 1, // 10: feast.serving.Job.type:type_name -> feast.serving.JobType
- 2, // 11: feast.serving.Job.status:type_name -> feast.serving.JobStatus
- 3, // 12: feast.serving.Job.data_format:type_name -> feast.serving.DataFormat
- 19, // 13: feast.serving.DatasetSource.file_source:type_name -> feast.serving.DatasetSource.FileSource
- 21, // 14: feast.serving.GetOnlineFeaturesRequest.EntityRow.entity_timestamp:type_name -> google.protobuf.Timestamp
- 16, // 15: feast.serving.GetOnlineFeaturesRequest.EntityRow.fields:type_name -> feast.serving.GetOnlineFeaturesRequest.EntityRow.FieldsEntry
- 22, // 16: feast.serving.GetOnlineFeaturesRequest.EntityRow.FieldsEntry.value:type_name -> feast.types.Value
- 18, // 17: feast.serving.GetOnlineFeaturesResponse.FieldValues.fields:type_name -> feast.serving.GetOnlineFeaturesResponse.FieldValues.FieldsEntry
- 22, // 18: feast.serving.GetOnlineFeaturesResponse.FieldValues.FieldsEntry.value:type_name -> feast.types.Value
- 3, // 19: feast.serving.DatasetSource.FileSource.data_format:type_name -> feast.serving.DataFormat
- 4, // 20: feast.serving.ServingService.GetFeastServingInfo:input_type -> feast.serving.GetFeastServingInfoRequest
- 7, // 21: feast.serving.ServingService.GetOnlineFeatures:input_type -> feast.serving.GetOnlineFeaturesRequest
- 8, // 22: feast.serving.ServingService.GetBatchFeatures:input_type -> feast.serving.GetBatchFeaturesRequest
- 11, // 23: feast.serving.ServingService.GetJob:input_type -> feast.serving.GetJobRequest
- 5, // 24: feast.serving.ServingService.GetFeastServingInfo:output_type -> feast.serving.GetFeastServingInfoResponse
- 9, // 25: feast.serving.ServingService.GetOnlineFeatures:output_type -> feast.serving.GetOnlineFeaturesResponse
- 10, // 26: feast.serving.ServingService.GetBatchFeatures:output_type -> feast.serving.GetBatchFeaturesResponse
- 12, // 27: feast.serving.ServingService.GetJob:output_type -> feast.serving.GetJobResponse
- 24, // [24:28] is the sub-list for method output_type
- 20, // [20:24] is the sub-list for method input_type
- 20, // [20:20] is the sub-list for extension type_name
- 20, // [20:20] is the sub-list for extension extendee
- 0, // [0:20] is the sub-list for field type_name
+ 6, // 1: feast.serving.GetOnlineFeaturesRequest.features:type_name -> feast.serving.FeatureReference
+ 15, // 2: feast.serving.GetOnlineFeaturesRequest.entity_rows:type_name -> feast.serving.GetOnlineFeaturesRequest.EntityRow
+ 6, // 3: feast.serving.GetBatchFeaturesRequest.features:type_name -> feast.serving.FeatureReference
+ 14, // 4: feast.serving.GetBatchFeaturesRequest.dataset_source:type_name -> feast.serving.DatasetSource
+ 17, // 5: feast.serving.GetOnlineFeaturesResponse.field_values:type_name -> feast.serving.GetOnlineFeaturesResponse.FieldValues
+ 13, // 6: feast.serving.GetBatchFeaturesResponse.job:type_name -> feast.serving.Job
+ 13, // 7: feast.serving.GetJobRequest.job:type_name -> feast.serving.Job
+ 13, // 8: feast.serving.GetJobResponse.job:type_name -> feast.serving.Job
+ 1, // 9: feast.serving.Job.type:type_name -> feast.serving.JobType
+ 2, // 10: feast.serving.Job.status:type_name -> feast.serving.JobStatus
+ 3, // 11: feast.serving.Job.data_format:type_name -> feast.serving.DataFormat
+ 19, // 12: feast.serving.DatasetSource.file_source:type_name -> feast.serving.DatasetSource.FileSource
+ 20, // 13: feast.serving.GetOnlineFeaturesRequest.EntityRow.entity_timestamp:type_name -> google.protobuf.Timestamp
+ 16, // 14: feast.serving.GetOnlineFeaturesRequest.EntityRow.fields:type_name -> feast.serving.GetOnlineFeaturesRequest.EntityRow.FieldsEntry
+ 21, // 15: feast.serving.GetOnlineFeaturesRequest.EntityRow.FieldsEntry.value:type_name -> feast.types.Value
+ 18, // 16: feast.serving.GetOnlineFeaturesResponse.FieldValues.fields:type_name -> feast.serving.GetOnlineFeaturesResponse.FieldValues.FieldsEntry
+ 21, // 17: feast.serving.GetOnlineFeaturesResponse.FieldValues.FieldsEntry.value:type_name -> feast.types.Value
+ 3, // 18: feast.serving.DatasetSource.FileSource.data_format:type_name -> feast.serving.DataFormat
+ 4, // 19: feast.serving.ServingService.GetFeastServingInfo:input_type -> feast.serving.GetFeastServingInfoRequest
+ 7, // 20: feast.serving.ServingService.GetOnlineFeatures:input_type -> feast.serving.GetOnlineFeaturesRequest
+ 8, // 21: feast.serving.ServingService.GetBatchFeatures:input_type -> feast.serving.GetBatchFeaturesRequest
+ 11, // 22: feast.serving.ServingService.GetJob:input_type -> feast.serving.GetJobRequest
+ 5, // 23: feast.serving.ServingService.GetFeastServingInfo:output_type -> feast.serving.GetFeastServingInfoResponse
+ 9, // 24: feast.serving.ServingService.GetOnlineFeatures:output_type -> feast.serving.GetOnlineFeaturesResponse
+ 10, // 25: feast.serving.ServingService.GetBatchFeatures:output_type -> feast.serving.GetBatchFeaturesResponse
+ 12, // 26: feast.serving.ServingService.GetJob:output_type -> feast.serving.GetJobResponse
+ 23, // [23:27] is the sub-list for method output_type
+ 19, // [19:23] is the sub-list for method input_type
+ 19, // [19:19] is the sub-list for extension type_name
+ 19, // [19:19] is the sub-list for extension extendee
+ 0, // [0:19] is the sub-list for field type_name
}
func init() { file_feast_serving_ServingService_proto_init() }
diff --git a/sdk/go/protos/feast/storage/Redis.pb.go b/sdk/go/protos/feast/storage/Redis.pb.go
index 42fd0077ec8..cfc22a458e5 100644
--- a/sdk/go/protos/feast/storage/Redis.pb.go
+++ b/sdk/go/protos/feast/storage/Redis.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/storage/Redis.proto
@@ -113,12 +113,13 @@ var file_feast_storage_Redis_proto_rawDesc = []byte{
0x12, 0x2e, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73,
0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73,
- 0x42, 0x4f, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
- 0x65, 0x42, 0x0a, 0x52, 0x65, 0x64, 0x69, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x32, 0x67,
- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 0x74, 0x6f, 0x72, 0x61, 0x67,
- 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x42, 0x59, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x0a, 0x52, 0x65, 0x64, 0x69, 0x73, 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, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x33,
}
var (
diff --git a/sdk/go/protos/feast/types/FeatureRow.pb.go b/sdk/go/protos/feast/types/FeatureRow.pb.go
index 696f138459f..3b42b44889e 100644
--- a/sdk/go/protos/feast/types/FeatureRow.pb.go
+++ b/sdk/go/protos/feast/types/FeatureRow.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/types/FeatureRow.proto
@@ -56,6 +56,8 @@ type FeatureRow struct {
// /. This value will be used by the feast ingestion job to filter
// rows, and write the values to the correct tables.
FeatureSet string `protobuf:"bytes,6,opt,name=feature_set,json=featureSet,proto3" json:"feature_set,omitempty"`
+ // Identifier tying this feature row to a specific ingestion job.
+ IngestionId string `protobuf:"bytes,7,opt,name=ingestion_id,json=ingestionId,proto3" json:"ingestion_id,omitempty"`
}
func (x *FeatureRow) Reset() {
@@ -111,6 +113,13 @@ func (x *FeatureRow) GetFeatureSet() string {
return ""
}
+func (x *FeatureRow) GetIngestionId() string {
+ if x != nil {
+ return x.IngestionId
+ }
+ return ""
+}
+
var File_feast_types_FeatureRow_proto protoreflect.FileDescriptor
var file_feast_types_FeatureRow_proto_rawDesc = []byte{
@@ -120,7 +129,7 @@ var file_feast_types_FeatureRow_proto_rawDesc = []byte{
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65,
0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc1, 0x01, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
0x65, 0x52, 0x6f, 0x77, 0x12, 0x2a, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70,
0x65, 0x73, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73,
@@ -130,12 +139,15 @@ var file_feast_types_FeatureRow_proto_rawDesc = []byte{
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
0x5f, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74,
- 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x42, 0x50, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e,
- 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f,
- 0x77, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
- 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e,
+ 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x5a, 0x0a, 0x11, 0x66, 0x65, 0x61,
+ 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0f,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a,
+ 0x34, 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,
+ 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/sdk/go/protos/feast/types/FeatureRowExtended.pb.go b/sdk/go/protos/feast/types/FeatureRowExtended.pb.go
index 8ca9ee1bc90..1692a55dd4f 100644
--- a/sdk/go/protos/feast/types/FeatureRowExtended.pb.go
+++ b/sdk/go/protos/feast/types/FeatureRowExtended.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/types/FeatureRowExtended.proto
@@ -264,13 +264,13 @@ var file_feast_types_FeatureRowExtended_proto_rawDesc = []byte{
0x73, 0x65, 0x65, 0x6e, 0x18, 0x03, 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, 0x66, 0x69, 0x72, 0x73, 0x74, 0x53, 0x65, 0x65,
- 0x6e, 0x42, 0x58, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73,
- 0x42, 0x17, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65,
- 0x6e, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75,
- 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x33,
+ 0x6e, 0x42, 0x62, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x17, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52,
+ 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a,
+ 0x34, 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,
+ 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/sdk/go/protos/feast/types/Field.pb.go b/sdk/go/protos/feast/types/Field.pb.go
index c7b5193db5d..901075e2620 100644
--- a/sdk/go/protos/feast/types/Field.pb.go
+++ b/sdk/go/protos/feast/types/Field.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/types/Field.proto
@@ -106,12 +106,13 @@ var file_feast_types_Field_proto_rawDesc = []byte{
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x42, 0x4b, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e,
- 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f,
- 0x6a, 0x65, 0x6b, 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, 0x74, 0x79,
- 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x55, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0a, 0x46, 0x69, 0x65,
+ 0x6c, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x34, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/sdk/go/protos/feast/types/Value.pb.go b/sdk/go/protos/feast/types/Value.pb.go
index ba530b2dac2..317768fd549 100644
--- a/sdk/go/protos/feast/types/Value.pb.go
+++ b/sdk/go/protos/feast/types/Value.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: feast/types/Value.proto
@@ -819,12 +819,13 @@ var file_feast_types_Value_proto_rawDesc = []byte{
0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x02, 0x52,
0x03, 0x76, 0x61, 0x6c, 0x22, 0x1c, 0x0a, 0x08, 0x42, 0x6f, 0x6f, 0x6c, 0x4c, 0x69, 0x73, 0x74,
0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x08, 0x52, 0x03, 0x76,
- 0x61, 0x6c, 0x42, 0x4b, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65,
- 0x73, 0x42, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x30, 0x67,
- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62,
- 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x61, 0x6c, 0x42, 0x55, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x5a, 0x34, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x33,
}
var (
diff --git a/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go b/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go
index d609c5e89c0..fe4cc3ee47a 100644
--- a/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go
+++ b/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: tensorflow_metadata/proto/v0/path.proto
@@ -112,14 +112,14 @@ var file_tensorflow_metadata_proto_v0_path_proto_rawDesc = []byte{
0x61, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x74, 0x65, 0x6e, 0x73, 0x6f,
0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76,
0x30, 0x22, 0x1a, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x65,
- 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x42, 0x64, 0x0a,
+ 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x42, 0x68, 0x0a,
0x1a, 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e,
- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a, 0x41, 0x67,
- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65, 0x6b, 0x2f,
- 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30,
- 0xf8, 0x01, 0x01,
+ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a, 0x45, 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, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c,
+ 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2f, 0x76, 0x30, 0xf8, 0x01, 0x01,
}
var (
diff --git a/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go b/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go
index ab7ffc7201d..97117947b78 100644
--- a/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go
+++ b/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.21.0
+// protoc-gen-go v1.23.0
// protoc v3.10.0
// source: tensorflow_metadata/proto/v0/schema.proto
@@ -3476,13 +3476,13 @@ var file_tensorflow_metadata_proto_v0_schema_proto_rawDesc = []byte{
0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x01, 0x12,
0x07, 0x0a, 0x03, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41,
0x54, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x10, 0x04, 0x42,
- 0x64, 0x0a, 0x1a, 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f,
+ 0x68, 0x0a, 0x1a, 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f,
0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a,
- 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6a, 0x65,
- 0x6b, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77,
- 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
- 0x76, 0x30, 0xf8, 0x01, 0x01,
+ 0x45, 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, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72,
+ 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0xf8, 0x01, 0x01,
}
var (
diff --git a/sdk/go/request.go b/sdk/go/request.go
index f4e6597a9db..683f17c16ed 100644
--- a/sdk/go/request.go
+++ b/sdk/go/request.go
@@ -7,29 +7,29 @@ import (
)
var (
- // ErrInvalidFeatureName indicates that the user has provided a feature reference with the wrong structure or contents
- ErrInvalidFeatureName = "invalid feature references %s provided, feature names must be in the format /"
+ // ErrInvalidFeatureRef indicates that the user has provided a feature reference
+ // with the wrong structure or contents
+ ErrInvalidFeatureRef = "Invalid Feature Reference %s provided, " +
+ "feature reference must be in the format [featureset:]name"
)
// OnlineFeaturesRequest wrapper on feast.serving.GetOnlineFeaturesRequest.
type OnlineFeaturesRequest struct {
// Features is the list of features to obtain from Feast. Each feature can be given as
- //
- // /
- // The only required components are the feature name and project.
+ // the format feature_set:feature, where "feature_set" & "feature" are feature set name
+ // and feature name respectively. The only required components is feature name.
Features []string
// 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 is the default project to use when looking up features. This is only used when a project is not found
- // within the feature id.
+ // Project specifies the project would contain the feature sets where the requested features belong to.
Project string
}
// Builds the feast-specified request payload from the wrapper.
func (r OnlineFeaturesRequest) buildRequest() (*serving.GetOnlineFeaturesRequest, error) {
- features, err := buildFeatures(r.Features, r.Project)
+ featureRefs, err := buildFeatureRefs(r.Features, r.Project)
if err != nil {
return nil, err
}
@@ -42,41 +42,74 @@ func (r OnlineFeaturesRequest) buildRequest() (*serving.GetOnlineFeaturesRequest
}
}
return &serving.GetOnlineFeaturesRequest{
- Features: features,
+ Features: featureRefs,
EntityRows: entityRows,
}, nil
}
-// buildFeatures create a slice of FeatureReferences from a slice of "/"
-// It returns an error when the format is invalid
-func buildFeatures(featureReferences []string, defaultProject string) ([]*serving.FeatureReference, error) {
- var features []*serving.FeatureReference
+// 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) {
+ var featureRefs []*serving.FeatureReference
- for _, featureRef := range featureReferences {
- var project string
- var name string
+ for _, featureRefStr := range featureRefStrs {
+ featureRef, err := parseFeatureRef(featureRefStr, false)
+ if err != nil {
+ return nil, err
+ }
+ // apply project if specified
+ if len(project) != 0 {
+ featureRef.Project = project
+ }
+ featureRefs = append(featureRefs, featureRef)
+ }
+ return featureRefs, nil
+}
- projectSplit := strings.Split(featureRef, "/")
+// 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) {
+ if len(featureRefStr) == 0 {
+ return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr)
+ }
- if len(projectSplit) == 2 {
- project = projectSplit[0]
- name = projectSplit[1]
- } else if len(projectSplit) == 1 {
- project = defaultProject
- name = projectSplit[0]
+ var featureRef serving.FeatureReference
+ if strings.Contains(featureRefStr, "/") {
+ if ignoreProject {
+ projectSplit := strings.Split(featureRefStr, "/")
+ featureRefStr = projectSplit[1]
} else {
- return nil, fmt.Errorf(ErrInvalidFeatureName, featureRef)
+ return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr)
}
+ }
+ // parse featureset if specified
+ if strings.Contains(featureRefStr, ":") {
+ refSplit := strings.Split(featureRefStr, ":")
+ featureRef.FeatureSet, featureRefStr = refSplit[0], refSplit[1]
+ }
+ featureRef.Name = featureRefStr
- if project == "" || name == "" {
- return nil, fmt.Errorf(ErrInvalidFeatureName, featureRef)
- }
+ return &featureRef, nil
+}
- features = append(features, &serving.FeatureReference{
- Name: name,
- Project: project,
- })
+// Converts a FeatureReference proto into a string
+// featureRef - The FeatureReference to render as string
+// Returns string representation of the given FeatureReference
+func toFeatureRefStr(featureRef *serving.FeatureReference) string {
+ refStr := ""
+ // In protov3, unset string and default to ""
+ if len(featureRef.FeatureSet) > 0 {
+ refStr += featureRef.FeatureSet + ":"
}
+ refStr += featureRef.Name
- return features, nil
+ return refStr
}
diff --git a/sdk/go/request_test.go b/sdk/go/request_test.go
index df11c1ca45e..70e1f0d8f5e 100644
--- a/sdk/go/request_test.go
+++ b/sdk/go/request_test.go
@@ -20,35 +20,27 @@ func TestGetOnlineFeaturesRequest(t *testing.T) {
{
name: "valid",
req: OnlineFeaturesRequest{
- Features: []string{"my_project_1/feature1", "my_project_2/feature1", "my_project_4/feature3", "feature2", "feature2"},
+ Features: []string{
+ "driver:driver_id",
+ "driver_id",
+ },
Entities: []Row{
{"entity1": Int64Val(1), "entity2": StrVal("bob")},
{"entity1": Int64Val(1), "entity2": StrVal("annie")},
{"entity1": Int64Val(1), "entity2": StrVal("jane")},
},
- Project: "my_project_3",
+ Project: "driver_project",
},
want: &serving.GetOnlineFeaturesRequest{
Features: []*serving.FeatureReference{
{
- Project: "my_project_1",
- Name: "feature1",
- },
- {
- Project: "my_project_2",
- Name: "feature1",
- },
- {
- Project: "my_project_4",
- Name: "feature3",
- },
- {
- Project: "my_project_3",
- Name: "feature2",
+ Project: "driver_project",
+ FeatureSet: "driver",
+ Name: "driver_id",
},
{
- Project: "my_project_3",
- Name: "feature2",
+ Project: "driver_project",
+ Name: "driver_id",
},
},
EntityRows: []*serving.GetOnlineFeaturesRequest_EntityRow{
@@ -76,34 +68,6 @@ func TestGetOnlineFeaturesRequest(t *testing.T) {
wantErr: false,
err: nil,
},
- {
- name: "valid_project_in_name",
- req: OnlineFeaturesRequest{
- Features: []string{"project/feature1"},
- Entities: []Row{},
- },
- want: &serving.GetOnlineFeaturesRequest{
- Features: []*serving.FeatureReference{
- {
- Project: "project",
- Name: "feature1",
- },
- },
- EntityRows: []*serving.GetOnlineFeaturesRequest_EntityRow{},
- OmitEntitiesInResponse: false,
- },
- wantErr: false,
- err: nil,
- },
- {
- name: "no_project",
- req: OnlineFeaturesRequest{
- Features: []string{"feature1"},
- Entities: []Row{},
- },
- wantErr: true,
- err: fmt.Errorf(ErrInvalidFeatureName, "feature1"),
- },
{
name: "invalid_feature_name/wrong_format",
req: OnlineFeaturesRequest{
@@ -112,7 +76,7 @@ func TestGetOnlineFeaturesRequest(t *testing.T) {
Project: "my_project",
},
wantErr: true,
- err: fmt.Errorf(ErrInvalidFeatureName, "/fs1:feature1"),
+ err: fmt.Errorf(ErrInvalidFeatureRef, "/fs1:feature1"),
},
}
for _, tc := range tt {
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 c09fe4b922a..c6e7edd0764 100644
--- a/sdk/java/src/main/java/com/gojek/feast/FeastClient.java
+++ b/sdk/java/src/main/java/com/gojek/feast/FeastClient.java
@@ -23,8 +23,10 @@
import feast.proto.serving.ServingAPIProto.GetOnlineFeaturesRequest.EntityRow;
import feast.proto.serving.ServingAPIProto.GetOnlineFeaturesResponse;
import feast.proto.serving.ServingServiceGrpc;
+import feast.proto.types.ValueProto.Value;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -56,61 +58,78 @@ public GetFeastServingInfoResponse getFeastServingInfo() {
return stub.getFeastServingInfo(GetFeastServingInfoRequest.newBuilder().build());
}
+ /**
+ * Get online features from Feast from FeatureSets
+ *
+ * See {@link #getOnlineFeatures(List, List, String, boolean)}
+ *
+ * @param featureRefs list of string feature references to retrieve in the following format
+ * 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.
+ * @return list of {@link Row} containing retrieved data fields.
+ */
+ public List getOnlineFeatures(List featureRefs, List rows) {
+ return getOnlineFeatures(featureRefs, rows, "");
+ }
+
/**
* Get online features from Feast.
*
- * See {@link #getOnlineFeatures(List, List, String)}
+ *
See {@link #getOnlineFeatures(List, List, String, boolean)}
*
- * @param features list of string feature references to retrieve, feature reference follows this
- * format [project]/[name]
+ * @param featureRefs list of string feature references to retrieve in the following format
+ * 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 defaultProject {@link String} Default project to find features in if not provided in
- * feature reference.
- * @return list of {@link Row} containing features
+ * @param project {@link String} Specifies the project which contains the FeatureSets which the
+ * Feature requested belong to.
+ * @return list of {@link Row} containing retrieved data fields.
*/
- public List getOnlineFeatures(List features, List rows, String defaultProject) {
- return getOnlineFeatures(features, rows, defaultProject, false);
+ public List getOnlineFeatures(List featureRefs, List rows, String project) {
+ return getOnlineFeatures(featureRefs, rows, project, false);
}
/**
* Get online features from Feast.
*
- * Example of retrieving online features for the driver project, with features driver_id and
+ *
Example of retrieving online features for the driver featureset, with features driver_id and
* driver_name
*
*
{@code
* FeastClient client = FeastClient.create("localhost", 6566);
- * List requestedFeatureIds = Arrays.asList("driver/driver_id", "driver/driver_name");
+ * List requestedFeatureIds = Arrays.asList("driver:driver_id", "driver:driver_name");
* List requestedRows =
* Arrays.asList(Row.create().set("driver_id", 123), Row.create().set("driver_id", 456));
* List retrievedFeatures = client.getOnlineFeatures(requestedFeatureIds, requestedRows);
* retrievedFeatures.forEach(System.out::println);
* }
*
- * @param featureRefStrings list of feature refs to retrieve, feature refs follow this format
- * [project]/[name]
+ * @param featureRefs list of string feature references to retrieve in the following format
+ * 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 defaultProject {@link String} Default project to find features in if not provided in
- * feature reference.
+ * @param project {@link String} Specifies the project which contains the FeatureSets which the
+ * Feature requested belong to.
* @param omitEntitiesInResponse if true, the returned {@link Row} will not contain field and
* value for the entity
- * @return list of {@link Row} containing features
+ * @return list of {@link Row} containing retrieved data fields.
*/
public List getOnlineFeatures(
- List featureRefStrings,
- List rows,
- String defaultProject,
- boolean omitEntitiesInResponse) {
- List features =
- RequestUtil.createFeatureRefs(featureRefStrings, defaultProject);
+ List featureRefs, List rows, String project, boolean omitEntitiesInResponse) {
+ List features = RequestUtil.createFeatureRefs(featureRefs, project);
+ // build entity rows and collect entity references
+ HashSet entityRefs = new HashSet<>();
List entityRows =
rows.stream()
.map(
- row ->
- EntityRow.newBuilder()
- .setEntityTimestamp(row.getEntityTimestamp())
- .putAllFields(row.getFields())
- .build())
+ row -> {
+ entityRefs.addAll(row.getFields().keySet());
+ return EntityRow.newBuilder()
+ .setEntityTimestamp(row.getEntityTimestamp())
+ .putAllFields(row.getFields())
+ .build();
+ })
.collect(Collectors.toList());
GetOnlineFeaturesResponse response =
@@ -125,7 +144,18 @@ public List getOnlineFeatures(
.map(
field -> {
Row row = Row.create();
- field.getFieldsMap().forEach(row::set);
+ field
+ .getFieldsMap()
+ .forEach(
+ (String name, Value value) -> {
+ // Strip project from string Feature References from returned from serving
+ if (!entityRefs.contains(name)) {
+ FeatureReference featureRef =
+ RequestUtil.parseFeatureRef(name, true).build();
+ name = RequestUtil.renderFeatureRef(featureRef);
+ }
+ row.set(name, value);
+ });
return row;
})
.collect(Collectors.toList());
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 3505f646c2b..3a1a0919d3e 100644
--- a/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java
+++ b/sdk/java/src/main/java/com/gojek/feast/RequestUtil.java
@@ -17,47 +17,89 @@
package com.gojek.feast;
import feast.proto.serving.ServingAPIProto.FeatureReference;
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
@SuppressWarnings("WeakerAccess")
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 defaultProject) {
+ List featureRefStrings, String project) {
if (featureRefStrings == null) {
throw new IllegalArgumentException("featureRefs cannot be null");
}
- List featureRefs = new ArrayList<>();
+ List featureRefs =
+ featureRefStrings.stream()
+ .map(refStr -> parseFeatureRef(refStr, false))
+ .collect(Collectors.toList());
+ // apply project override if specified
+ if (!project.isEmpty()) {
+ featureRefs =
+ featureRefs.stream().map(ref -> ref.setProject(project)).collect(Collectors.toList());
+ }
- for (String featureRefString : featureRefStrings) {
- String project;
- String name;
- String[] projectSplit = featureRefString.split("/");
+ return featureRefs.stream().map(ref -> ref.build()).collect(Collectors.toList());
+ }
- if (projectSplit.length == 1) {
- project = defaultProject;
- name = projectSplit[0];
- } else if (projectSplit.length == 2) {
- project = projectSplit[0];
- name = projectSplit[1];
+ /**
+ * 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) {
+ 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(
- "Feature id '%s' has invalid format. Expected format: /.",
- featureRefString));
+ String.format("Unsupported feature reference: %s", featureRefString));
}
+ }
- if (project.isEmpty() || name.isEmpty() || name.contains(":")) {
- throw new IllegalArgumentException(
- String.format(
- "Feature id '%s' has invalid format. Expected format: /.",
- featureRefString));
- }
+ // parse featureset if specified
+ if (featureRefString.contains(":")) {
+ String[] featureSetSplit = featureRefString.split(":");
+ featureRef.setFeatureSet(featureSetSplit[0]);
+ featureRefString = featureSetSplit[1];
+ }
+ featureRef.setName(featureRefString);
+ return featureRef;
+ }
- featureRefs.add(FeatureReference.newBuilder().setName(name).setProject(project).build());
+ /**
+ * Render a feature reference as string.
+ *
+ * @param featureReference to render as string
+ * @return string represenation of feature reference.
+ */
+ public static String renderFeatureRef(FeatureReference featureReference) {
+ String refStr = "";
+ // In protov3, unset string and int fields default to "" and 0 respectively
+ if (!featureReference.getFeatureSet().isEmpty()) {
+ refStr += featureReference.getFeatureSet() + ":";
}
- return featureRefs;
+ refStr = refStr + featureReference.getName();
+
+ return refStr;
}
}
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 c066ffa0b30..f10d82b8726 100644
--- a/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java
+++ b/sdk/java/src/test/java/com/gojek/feast/RequestUtilTest.java
@@ -22,9 +22,9 @@
import com.google.protobuf.TextFormat;
import feast.proto.serving.ServingAPIProto.FeatureReference;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -33,51 +33,27 @@
class RequestUtilTest {
- private static Stream provideValidFeatureIds() {
+ private static Stream provideValidFeatureRefs() {
return Stream.of(
Arguments.of(
- Collections.singletonList("driver_project/driver_id"),
- Collections.singletonList(
- FeatureReference.newBuilder()
- .setProject("driver_project")
- .setName("driver_id")
- .build())),
- Arguments.of(
- Arrays.asList("driver_project/driver_id", "driver_project/driver_name"),
+ 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_name")
- .build())),
- Arguments.of(
- Arrays.asList(
- "driver_project/driver_id",
- "driver_project/driver_name",
- "booking_project/driver_name"),
- Arrays.asList(
FeatureReference.newBuilder()
.setProject("driver_project")
.setName("driver_id")
- .build(),
- FeatureReference.newBuilder()
- .setProject("driver_project")
- .setName("driver_name")
- .build(),
- FeatureReference.newBuilder()
- .setProject("booking_project")
- .setName("driver_name")
.build())));
}
@ParameterizedTest
- @MethodSource("provideValidFeatureIds")
- void createFeatureSets_ShouldReturnFeatureSetsForValidFeatureIds(
+ @MethodSource("provideValidFeatureRefs")
+ void createFeatureSets_ShouldReturnFeatureSetsForValidFeatureRefs(
List input, List expected) {
- List actual = RequestUtil.createFeatureRefs(input, "my-project");
+ List actual = RequestUtil.createFeatureRefs(input, "driver_project");
// Order of the actual and expected featureSets do no not matter
actual.sort(Comparator.comparing(FeatureReference::getName));
expected.sort(Comparator.comparing(FeatureReference::getName));
@@ -89,23 +65,35 @@ void createFeatureSets_ShouldReturnFeatureSetsForValidFeatureIds(
}
}
+ @ParameterizedTest
+ @MethodSource("provideValidFeatureRefs")
+ void renderFeatureRef_ShouldReturnFeatureRefString(
+ List expected, List input) {
+ input =
+ input.stream()
+ .map(ref -> ref.toBuilder().clearProject().build())
+ .collect(Collectors.toList());
+ List actual =
+ input.stream().map(ref -> RequestUtil.renderFeatureRef(ref)).collect(Collectors.toList());
+ assertEquals(expected.size(), actual.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), actual.get(i));
+ }
+ }
+
private static Stream provideInvalidFeatureRefs() {
- return Stream.of(
- Arguments.of(Collections.singletonList("/noproject")),
- Arguments.of(Collections.singletonList("")));
+ return Stream.of(Arguments.of(List.of("project/feature", "")));
}
@ParameterizedTest
@MethodSource("provideInvalidFeatureRefs")
void createFeatureSets_ShouldThrowExceptionForInvalidFeatureRefs(List input) {
- assertThrows(
- IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, "my-project"));
+ assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, ""));
}
@ParameterizedTest
@NullSource
void createFeatureSets_ShouldThrowExceptionForNullFeatureRefs(List input) {
- assertThrows(
- IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, "my-project"));
+ assertThrows(IllegalArgumentException.class, () -> RequestUtil.createFeatureRefs(input, ""));
}
}
diff --git a/sdk/python/feast/cli.py b/sdk/python/feast/cli.py
index 2fd5a4cdf56..87f12301f86 100644
--- a/sdk/python/feast/cli.py
+++ b/sdk/python/feast/cli.py
@@ -137,6 +137,7 @@ def feature_set_list():
@feature_set.command("apply")
+# TODO: add project option to overwrite project setting.
@click.option(
"--filename",
"-f",
diff --git a/sdk/python/feast/client.py b/sdk/python/feast/client.py
index 89a89fd2a8d..50e3a65bad2 100644
--- a/sdk/python/feast/client.py
+++ b/sdk/python/feast/client.py
@@ -36,6 +36,7 @@
CONFIG_PROJECT_KEY,
CONFIG_SERVING_SECURE_KEY,
CONFIG_SERVING_URL_KEY,
+ FEAST_DEFAULT_OPTIONS,
)
from feast.core.CoreService_pb2 import (
ApplyFeatureSetRequest,
@@ -57,6 +58,7 @@
)
from feast.core.CoreService_pb2_grpc import CoreServiceStub
from feast.core.FeatureSet_pb2 import FeatureSetStatus
+from feast.feature import FeatureRef
from feast.feature_set import Entity, FeatureSet, FeatureSetRef
from feast.job import IngestJob, RetrievalJob
from feast.loaders.abstract_producer import get_producer
@@ -290,13 +292,15 @@ def project(self) -> Union[str, None]:
"""
return self._config.get(CONFIG_PROJECT_KEY)
- def set_project(self, project: str):
+ def set_project(self, project: Optional[str] = None):
"""
Set currently active Feast project
Args:
- project: Project to set as active
+ project: Project to set as active. If unset, will reset to the default project.
"""
+ if project is None:
+ project = FEAST_DEFAULT_OPTIONS[CONFIG_PROJECT_KEY]
self._config.set(CONFIG_PROJECT_KEY, project)
def list_projects(self) -> List[str]:
@@ -339,13 +343,17 @@ def archive_project(self, project):
"""
self._connect_core()
- self._core_service_stub.ArchiveProject(
- ArchiveProjectRequest(name=project),
- timeout=self._config.getint(CONFIG_GRPC_CONNECTION_TIMEOUT_DEFAULT_KEY),
- ) # type: ArchiveProjectResponse
+ try:
+ self._core_service_stub.ArchiveProject(
+ ArchiveProjectRequest(name=project),
+ timeout=self._config.getint(CONFIG_GRPC_CONNECTION_TIMEOUT_DEFAULT_KEY),
+ ) # type: ArchiveProjectResponse
+ except grpc.RpcError as e:
+ raise grpc.RpcError(e.details())
+ # revert to the default project
if self._project == project:
- self._project = ""
+ self._project = FEAST_DEFAULT_OPTIONS[CONFIG_PROJECT_KEY]
def apply(self, feature_sets: Union[List[FeatureSet], FeatureSet]):
"""
@@ -498,23 +506,24 @@ def get_batch_features(
self,
feature_refs: List[str],
entity_rows: Union[pd.DataFrame, str],
- default_project: str = None,
+ project: str = None,
) -> RetrievalJob:
"""
Retrieves historical features from a Feast Serving deployment.
Args:
- feature_refs (List[str]):
- List of feature references that will be returned for each entity.
- Each feature reference should have the following format
- "project/feature".
-
+ feature_refs: List of feature references that will be returned for each entity.
+ Each feature reference should have the following format:
+ "feature_set:feature" where "feature_set" & "feature" refer to
+ the feature and feature set names respectively.
+ Only the feature name is required.
entity_rows (Union[pd.DataFrame, str]):
Pandas dataframe containing entities and a 'datetime' column.
Each entity in a feature set must be present as a column in this
dataframe. The datetime column must contain timestamps in
datetime64 format.
- default_project: Default project where feature values will be found.
+ project: Specifies the project which contain the FeatureSets
+ which the requested features belong to.
Returns:
feast.job.RetrievalJob:
@@ -542,10 +551,6 @@ def get_batch_features(
self._connect_serving()
- feature_references = _build_feature_references(
- feature_refs=feature_refs, default_project=default_project
- )
-
# Retrieve serving information to determine store type and
# staging location
serving_info = self._serving_service_stub.GetFeastServingInfo(
@@ -587,7 +592,10 @@ def get_batch_features(
entity_rows, serving_info.job_staging_location
) # type: List[str]
request = GetBatchFeaturesRequest(
- features=feature_references,
+ features=_build_feature_references(
+ feature_ref_strs=feature_refs,
+ project=project if project is not None else self.project,
+ ),
dataset_source=DatasetSource(
file_source=DatasetSource.FileSource(
file_uris=staged_files, data_format=DataFormat.DATA_FORMAT_AVRO
@@ -607,23 +615,22 @@ def get_online_features(
self,
feature_refs: List[str],
entity_rows: List[GetOnlineFeaturesRequest.EntityRow],
- default_project: Optional[str] = None,
+ project: Optional[str] = None,
) -> GetOnlineFeaturesResponse:
"""
Retrieves the latest online feature data from Feast Serving
Args:
- feature_refs: List of feature references in the following format
- [project]/[feature_name]. Only the feature name
- is a required component in the reference.
- example:
- ["my_project/my_feature_1",
- "my_feature_4",]
+ feature_refs: List of feature references that will be returned for each entity.
+ Each feature reference should have the following format:
+ "feature_set:feature" where "feature_set" & "feature" refer to
+ the feature and feature set names respectively.
+ Only the feature name is required.
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
- default_project: This project will be used if the project name is
- not provided in the feature reference
+ project: Specifies the project which contain the FeatureSets
+ which the requested features belong to.
Returns:
Returns a list of maps where each item in the list contains the
@@ -635,14 +642,37 @@ def get_online_features(
response = self._serving_service_stub.GetOnlineFeatures(
GetOnlineFeaturesRequest(
features=_build_feature_references(
- feature_refs=feature_refs,
- default_project=(
- default_project if not self.project else self.project
- ),
+ feature_ref_strs=feature_refs,
+ project=project if project is not None else self.project,
),
entity_rows=entity_rows,
)
)
+ # collect entity row refs
+ entity_refs = set()
+ for entity_row in entity_rows:
+ entity_refs.update(entity_row.fields.keys())
+
+ strip_field_values = []
+ for field_value in response.field_values:
+ # strip the project part the string feature references returned from serving
+ strip_fields = {}
+ for ref_str, value in field_value.fields.items():
+ # find and ignore entities
+ if ref_str in entity_refs:
+ strip_fields[ref_str] = value
+ else:
+ strip_ref_str = repr(
+ FeatureRef.from_str(ref_str, ignore_project=True)
+ )
+ strip_fields[strip_ref_str] = value
+ strip_field_values.append(
+ GetOnlineFeaturesResponse.FieldValues(fields=strip_fields)
+ )
+
+ del response.field_values[:]
+ response.field_values.extend(strip_field_values)
+
except grpc.RpcError as e:
raise grpc.RpcError(e.details())
@@ -834,50 +864,25 @@ def ingest(
def _build_feature_references(
- feature_refs: List[str], default_project: str = None
+ feature_ref_strs: List[str], project: Optional[str] = None
) -> List[FeatureReference]:
"""
- Builds a list of FeatureSet objects from feature set ids in order to
- retrieve feature data from Feast Serving
+ Builds a list of FeatureReference protos from string feature set references
Args:
- feature_refs: List of feature reference strings
- ("project/feature")
- default_project: This project will be used if the project name is
- not provided in the feature reference
- """
-
- features = []
+ feature_ref_strs: List of string feature references
+ project: Optionally specifies the project in the parsed feature references.
- for feature_ref in feature_refs:
- project_split = feature_ref.split("/")
-
- if len(project_split) == 2:
- project, name = project_split
- elif len(project_split) == 1:
- name = project_split[0]
- if default_project is None:
- raise ValueError(
- f"No project specified in {feature_ref} and no default project provided"
- )
- project = default_project
- else:
- raise ValueError(
- f'Could not parse feature ref {feature_ref}, expecting "project/feature"'
- )
-
- if len(project) == 0 or len(name) == 0:
- raise ValueError(
- f'Could not parse feature ref {feature_ref}, expecting "project/feature"'
- )
-
- if ":" in name:
- raise ValueError(
- f'Could not parse feature ref {feature_ref}, expecting "project/feature". Versions were deprecated in v0.5.0.'
- )
-
- features.append(FeatureReference(project=project, name=name))
- return features
+ Returns:
+ A list of FeatureReference protos parsed from args.
+ """
+ feature_refs = [FeatureRef.from_str(ref_str) for ref_str in feature_ref_strs]
+ feature_ref_protos = [ref.to_proto() for ref in feature_refs]
+ # apply project if specified
+ if project is not None:
+ for feature_ref_proto in feature_ref_protos:
+ feature_ref_proto.project = project
+ return feature_ref_protos
def _generate_ingestion_id(feature_set: FeatureSet) -> str:
diff --git a/sdk/python/feast/feature.py b/sdk/python/feast/feature.py
index f5c07070b09..35e0ea32aeb 100644
--- a/sdk/python/feast/feature.py
+++ b/sdk/python/feast/feature.py
@@ -14,6 +14,7 @@
from feast.core.FeatureSet_pb2 import FeatureSpec as FeatureProto
from feast.field import Field
+from feast.serving.ServingService_pb2 import FeatureReference as FeatureRefProto
from feast.types import Value_pb2 as ValueTypeProto
from feast.value_type import ValueType
@@ -62,3 +63,86 @@ def from_proto(cls, feature_proto: FeatureProto):
feature.update_shape_type(feature_proto)
feature.update_domain_info(feature_proto)
return feature
+
+
+class FeatureRef:
+ """ Feature Reference represents a reference to a specific feature. """
+
+ def __init__(self, name: str, feature_set: str = None):
+ self.proto = FeatureRefProto(name=name, feature_set=feature_set)
+
+ @classmethod
+ def from_proto(cls, proto: FeatureRefProto):
+ """
+ Construct a feature reference from the given FeatureReference proto
+
+ Arg:
+ proto: Protobuf FeatureReference to construct from
+
+ Returns:
+ FeatureRef that refers to the given feature
+ """
+ return cls(name=proto.name, feature_set=proto.feature_set)
+
+ @classmethod
+ def from_str(cls, feature_ref_str: str, ignore_project: bool = False):
+ """
+ Parse the given string feature reference into FeatureRef model
+ String feature reference should be in the format feature_set:feature.
+ Where "feature_set" and "name" are the feature_set name and feature name
+ respectively.
+
+ 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}")
+
+ # parse feature set name if specified
+ if ":" in feature_ref_str:
+ proto.feature_set, feature_ref_str = feature_ref_str.split(":")
+
+ proto.name = feature_ref_str
+ return cls.from_proto(proto)
+
+ def to_proto(self) -> FeatureRefProto:
+ """
+ Convert and return this feature set reference to protobuf.
+
+ Returns:
+ Protobuf respresentation of this feature set reference.
+ """
+ return self.proto
+
+ def __repr__(self):
+ # return string representation of the reference
+ # [project/][feature_set:]name
+ # in protov3 unset string and int fields default to "" and 0
+ ref_str = ""
+ if len(self.proto.project) > 0:
+ ref_str += self.proto.project + "/"
+ if len(self.proto.feature_set) > 0:
+ ref_str += self.proto.feature_set + ":"
+ ref_str += self.proto.name
+ return ref_str
+
+ def __str__(self):
+ # human readable string of the reference
+ return f"FeatureRef<{self.__repr__()}>"
+
+ def __eq__(self, other):
+ # compare with other feature set
+ return hash(self) == hash(other)
+
+ def __hash__(self):
+ # hash this reference
+ return hash(repr(self))
diff --git a/sdk/python/feast/feature_set.py b/sdk/python/feast/feature_set.py
index 3c77aa1db5e..aebee52ca42 100644
--- a/sdk/python/feast/feature_set.py
+++ b/sdk/python/feast/feature_set.py
@@ -898,11 +898,11 @@ def __str__(self):
def __repr__(self):
# return string representation of the reference
# [project/]name
+ # in protov3 unset string and int fields default to "" and 0
ref_str = ""
- if self.proto.project:
+ if len(self.proto.project) > 0:
ref_str += self.proto.project + "/"
- if self.proto.name:
- ref_str += self.proto.name
+ ref_str += self.proto.name
return ref_str
def __eq__(self, other):
diff --git a/sdk/python/feast/job.py b/sdk/python/feast/job.py
index f2e31c709e2..21b08224bad 100644
--- a/sdk/python/feast/job.py
+++ b/sdk/python/feast/job.py
@@ -37,7 +37,9 @@ class RetrievalJob:
A class representing a job for feature retrieval in Feast.
"""
- def __init__(self, job_proto: JobProto, serving_stub: ServingServiceStub):
+ def __init__(
+ self, job_proto: JobProto, serving_stub: ServingServiceStub,
+ ):
"""
Args:
job_proto: Job proto object (wrapped by this job object)
@@ -45,7 +47,8 @@ def __init__(self, job_proto: JobProto, serving_stub: ServingServiceStub):
"""
self.job_proto = job_proto
self.serving_stub = serving_stub
- self.storage_client = storage.Client(project=None)
+ # TODO: abstract away GCP depedency
+ self.gcs_client = storage.Client(project=None)
@property
def id(self):
@@ -125,7 +128,7 @@ def result(self, timeout_sec: int = DEFAULT_TIMEOUT_SEC):
for file_uri in uris:
if file_uri.scheme == "gs":
file_obj = tempfile.TemporaryFile()
- self.storage_client.download_blob_to_file(file_uri.geturl(), file_obj)
+ self.gcs_client.download_blob_to_file(file_uri.geturl(), file_obj)
elif file_uri.scheme == "file":
file_obj = open(file_uri.path, "rb")
else:
diff --git a/sdk/python/feast/test_feature.py b/sdk/python/feast/test_feature.py
new file mode 100644
index 00000000000..a4f0ff58ff2
--- /dev/null
+++ b/sdk/python/feast/test_feature.py
@@ -0,0 +1,23 @@
+# Copyright 2019 The Feast Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from feast.feature import FeatureRef
+
+
+class TestFeatureRef:
+ def test_str_ref(self):
+ original_ref = FeatureRef(project="test", name="test")
+ ref_str = repr(original_ref)
+ parsed_ref = FeatureRef.from_str(ref_str)
+ assert original_ref == parsed_ref
diff --git a/sdk/python/tests/test_client.py b/sdk/python/tests/test_client.py
index f143f18c8f2..380557ce928 100644
--- a/sdk/python/tests/test_client.py
+++ b/sdk/python/tests/test_client.py
@@ -14,13 +14,18 @@
import pkgutil
+import tempfile
from concurrent import futures
+from datetime import datetime
from unittest import mock
import grpc
+import pandas as pd
+import pandavro
import pytest
from google.protobuf.duration_pb2 import Duration
from mock import MagicMock, patch
+from pytz import timezone
import dataframes
import feast.core.CoreService_pb2_grpc as Core
@@ -45,10 +50,16 @@
from feast.feature_set import Feature, FeatureSet, FeatureSetRef
from feast.job import IngestJob
from feast.serving.ServingService_pb2 import (
+ DataFormat,
+ FeastServingType,
+ GetBatchFeaturesResponse,
GetFeastServingInfoResponse,
+ GetJobResponse,
GetOnlineFeaturesRequest,
GetOnlineFeaturesResponse,
)
+from feast.serving.ServingService_pb2 import Job as BatchRetrievalJob
+from feast.serving.ServingService_pb2 import JobStatus, JobType
from feast.source import KafkaSource
from feast.types import Value_pb2 as ValueProto
from feast.value_type import ValueType
@@ -196,12 +207,17 @@ def test_get_online_features(self, mocked_client, mocker):
grpc.insecure_channel("")
)
- fields = dict()
- for feature_num in range(1, 10):
- fields[f"my_project/feature_{str(feature_num)}"] = ValueProto.Value(
- int64_val=feature_num
- )
- field_values = GetOnlineFeaturesResponse.FieldValues(fields=fields)
+ def int_val(x):
+ return ValueProto.Value(int64_val=x)
+
+ # serving can return feature references with projects,
+ # get_online_features() should strip the project part.
+ field_values = GetOnlineFeaturesResponse.FieldValues(
+ fields={
+ "driver_project/driver:driver_id": int_val(1),
+ "driver_project/driver_id": int_val(9),
+ }
+ )
response = GetOnlineFeaturesResponse()
entity_rows = []
@@ -209,7 +225,7 @@ def test_get_online_features(self, mocked_client, mocker):
response.field_values.append(field_values)
entity_rows.append(
GetOnlineFeaturesRequest.EntityRow(
- fields={"customer_id": ValueProto.Value(int64_val=row_number)}
+ fields={"customer_id": int_val(row_number)}
)
)
@@ -219,24 +235,17 @@ def test_get_online_features(self, mocked_client, mocker):
return_value=response,
)
+ # NOTE: Feast Serving does not allow for feature references
+ # that specify the same feature in the same request
response = mocked_client.get_online_features(
entity_rows=entity_rows,
- feature_refs=[
- "my_project/feature_1",
- "my_project/feature_2",
- "my_project/feature_3",
- "my_project/feature_4",
- "my_project/feature_5",
- "my_project/feature_6",
- "my_project/feature_7",
- "my_project/feature_8",
- "my_project/feature_9",
- ],
+ feature_refs=["driver:driver_id", "driver_id"],
+ project="driver_project",
) # type: GetOnlineFeaturesResponse
assert (
- response.field_values[0].fields["my_project/feature_1"].int64_val == 1
- and response.field_values[0].fields["my_project/feature_9"].int64_val == 9
+ response.field_values[0].fields["driver:driver_id"].int64_val == 1
+ and response.field_values[0].fields["driver_id"].int64_val == 9
)
@pytest.mark.parametrize(
@@ -400,130 +409,125 @@ def test_stop_ingest_job(self, mocked_client, mocker):
mocked_client.stop_ingest_job(ingest_job)
assert mocked_client._core_service_stub.StopIngestionJob.called
- # @pytest.mark.parametrize
- # "mocked_client",
- # [pytest.lazy_fixture("mock_client"), pytest.lazy_fixture("secure_mock_client")],
- # )
- # def test_get_batch_features(self, mocked_client, mocker):
- #
- # mocked_client._serving_service_stub = Serving.ServingServiceStub(
- # grpc.insecure_channel("")
- # )
- # mocked_client._core_service_stub = Core.CoreServiceStub(
- # grpc.insecure_channel("")
- # )
- #
- # mocker.patch.object(
- # mocked_client._core_service_stub,
- # "GetFeatureSet",
- # return_value=GetFeatureSetResponse(
- # feature_set=FeatureSetProto(
- # spec=FeatureSetSpecProto(
- # name="customer_fs",
- # project="my_project",
- # entities=[
- # EntitySpecProto(
- # name="customer", value_type=ValueProto.ValueType.INT64
- # ),
- # EntitySpecProto(
- # name="transaction",
- # value_type=ValueProto.ValueType.INT64,
- # ),
- # ],
- # features=[
- # FeatureSpecProto(
- # name="customer_feature_1",
- # value_type=ValueProto.ValueType.FLOAT,
- # ),
- # FeatureSpecProto(
- # name="customer_feature_2",
- # value_type=ValueProto.ValueType.STRING,
- # ),
- # ],
- # ),
- # meta=FeatureSetMetaProto(status=FeatureSetStatusProto.STATUS_READY),
- # )
- # ),
- # )
- #
- # expected_dataframe = pd.DataFrame(
- # {
- # "datetime": [datetime.utcnow() for _ in range(3)],
- # "customer": [1001, 1002, 1003],
- # "transaction": [1001, 1002, 1003],
- # "my_project/customer_feature_1": [1001, 1002, 1003],
- # "my_project/customer_feature_2": [1001, 1002, 1003],
- # }
- # )
- #
- # final_results = tempfile.mktemp()
- # to_avro(file_path_or_buffer=final_results, df=expected_dataframe)
- #
- # mocker.patch.object(
- # mocked_client._serving_service_stub,
- # "GetBatchFeatures",
- # return_value=GetBatchFeaturesResponse(
- # job=BatchFeaturesJob(
- # id="123",
- # type=JobType.JOB_TYPE_DOWNLOAD,
- # status=JobStatus.JOB_STATUS_DONE,
- # file_uris=[f"file://{final_results}"],
- # data_format=DataFormat.DATA_FORMAT_AVRO,
- # )
- # ),
- # )
- #
- # mocker.patch.object(
- # mocked_client._serving_service_stub,
- # "GetJob",
- # return_value=GetJobResponse(
- # job=BatchFeaturesJob(
- # id="123",
- # type=JobType.JOB_TYPE_DOWNLOAD,
- # status=JobStatus.JOB_STATUS_DONE,
- # file_uris=[f"file://{final_results}"],
- # data_format=DataFormat.DATA_FORMAT_AVRO,
- # )
- # ),
- # )
- #
- # mocker.patch.object(
- # mocked_client._serving_service_stub,
- # "GetFeastServingInfo",
- # return_value=GetFeastServingInfoResponse(
- # job_staging_location=f"file://{tempfile.mkdtemp()}/",
- # type=FeastServingType.FEAST_SERVING_TYPE_BATCH,
- # ),
- # )
- #
- # mocked_client.set_project("project1")
- # response = mocked_client.get_batch_features(
- # entity_rows=pd.DataFrame(
- # {
- # "datetime": [
- # pd.datetime.now(tz=timezone("Asia/Singapore")) for _ in range(3)
- # ],
- # "customer": [1001, 1002, 1003],
- # "transaction": [1001, 1002, 1003],
- # }
- # ),
- # feature_refs=[
- # "my_project/customer_feature_1",
- # "my_project/customer_feature_2",
- # ],
- # ) # type: Job
- #
- # assert response.id == "123" and response.status == JobStatus.JOB_STATUS_DONE
- #
- # actual_dataframe = response.to_dataframe()
- #
- # assert actual_dataframe[
- # ["my_project/customer_feature_1", "my_project/customer_feature_2"]
- # ].equals(
- # expected_dataframe[
- # ["my_project/customer_feature_1", "my_project/customer_feature_2"]
- # ]
- # )
+ @pytest.mark.parametrize(
+ "mocked_client",
+ [pytest.lazy_fixture("mock_client"), pytest.lazy_fixture("secure_mock_client")],
+ )
+ def test_get_batch_features(self, mocked_client, mocker):
+
+ mocked_client._serving_service_stub = Serving.ServingServiceStub(
+ grpc.insecure_channel("")
+ )
+ mocked_client._core_service_stub = Core.CoreServiceStub(
+ grpc.insecure_channel("")
+ )
+
+ mocker.patch.object(
+ mocked_client._core_service_stub,
+ "GetFeatureSet",
+ return_value=GetFeatureSetResponse(
+ feature_set=FeatureSetProto(
+ spec=FeatureSetSpecProto(
+ name="driver",
+ project="driver_project",
+ entities=[
+ EntitySpecProto(
+ name="driver", value_type=ValueProto.ValueType.INT64
+ ),
+ EntitySpecProto(
+ name="transaction",
+ value_type=ValueProto.ValueType.INT64,
+ ),
+ ],
+ features=[
+ FeatureSpecProto(
+ name="driver_id", value_type=ValueProto.ValueType.FLOAT,
+ ),
+ FeatureSpecProto(
+ name="driver_name",
+ value_type=ValueProto.ValueType.STRING,
+ ),
+ ],
+ ),
+ meta=FeatureSetMetaProto(status=FeatureSetStatusProto.STATUS_READY),
+ )
+ ),
+ )
+
+ expected_dataframe = pd.DataFrame(
+ {
+ "datetime": [datetime.utcnow() for _ in range(3)],
+ "driver": [1001, 1002, 1003],
+ "transaction": [1001, 1002, 1003],
+ "driver_id": [1001, 1002, 1003],
+ }
+ )
+
+ final_results = tempfile.mktemp()
+ pandavro.to_avro(file_path_or_buffer=final_results, df=expected_dataframe)
+
+ mocker.patch.object(
+ mocked_client._serving_service_stub,
+ "GetBatchFeatures",
+ return_value=GetBatchFeaturesResponse(
+ job=BatchRetrievalJob(
+ id="123",
+ type=JobType.JOB_TYPE_DOWNLOAD,
+ status=JobStatus.JOB_STATUS_DONE,
+ file_uris=[f"file://{final_results}"],
+ data_format=DataFormat.DATA_FORMAT_AVRO,
+ )
+ ),
+ )
+
+ mocker.patch.object(
+ mocked_client._serving_service_stub,
+ "GetJob",
+ return_value=GetJobResponse(
+ job=BatchRetrievalJob(
+ id="123",
+ type=JobType.JOB_TYPE_DOWNLOAD,
+ status=JobStatus.JOB_STATUS_DONE,
+ file_uris=[f"file://{final_results}"],
+ data_format=DataFormat.DATA_FORMAT_AVRO,
+ )
+ ),
+ )
+
+ mocker.patch.object(
+ mocked_client._serving_service_stub,
+ "GetFeastServingInfo",
+ return_value=GetFeastServingInfoResponse(
+ job_staging_location=f"file://{tempfile.mkdtemp()}/",
+ type=FeastServingType.FEAST_SERVING_TYPE_BATCH,
+ ),
+ )
+
+ mocked_client.set_project("project1")
+ # TODO: Abstract away GCS client and GCP dependency
+ # NOTE: Feast Serving does not allow for feature references
+ # that specify the same feature in the same request.
+ with patch("google.cloud.storage.Client"):
+ response = mocked_client.get_batch_features(
+ entity_rows=pd.DataFrame(
+ {
+ "datetime": [
+ pd.datetime.now(tz=timezone("Asia/Singapore"))
+ for _ in range(3)
+ ],
+ "driver": [1001, 1002, 1003],
+ "transaction": [1001, 1002, 1003],
+ }
+ ),
+ feature_refs=["driver:driver_id", "driver_id"],
+ project="driver_project",
+ ) # Type: GetBatchFeaturesResponse
+
+ assert response.id == "123" and response.status == JobStatus.JOB_STATUS_DONE
+
+ actual_dataframe = response.to_dataframe()
+
+ assert actual_dataframe[["driver_id"]].equals(expected_dataframe[["driver_id"]])
@pytest.mark.parametrize(
"test_client",
diff --git a/serving/src/main/java/feast/serving/specs/CachedSpecService.java b/serving/src/main/java/feast/serving/specs/CachedSpecService.java
index edb8ee6ee55..07b0b8bbbd2 100644
--- a/serving/src/main/java/feast/serving/specs/CachedSpecService.java
+++ b/serving/src/main/java/feast/serving/specs/CachedSpecService.java
@@ -38,6 +38,7 @@
import io.prometheus.client.Gauge;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -51,12 +52,15 @@ public class CachedSpecService {
private static final int MAX_SPEC_COUNT = 1000;
private static final Logger log = org.slf4j.LoggerFactory.getLogger(CachedSpecService.class);
+ private static final String DEFAULT_PROJECT_NAME = "default";
+ // flag to signal that multiple featuresets match a specific
+ // string feature reference in the feature to featureset mapping.
+ private static final String FEATURE_SET_CONFLICT_FLAG = "##CONFLICT##";
private final CoreSpecService coreService;
- private final Map featureToFeatureSetMapping;
+ private Map featureToFeatureSetMapping;
- private final CacheLoader featureSetCacheLoader;
private final LoadingCache featureSetCache;
private Store store;
@@ -80,7 +84,7 @@ public CachedSpecService(CoreSpecService coreService, StoreProto.Store store) {
Map featureSets = getFeatureSetMap();
featureToFeatureSetMapping =
new ConcurrentHashMap<>(getFeatureToFeatureSetMapping(featureSets));
- featureSetCacheLoader = CacheLoader.from(featureSets::get);
+ CacheLoader featureSetCacheLoader = CacheLoader.from(featureSets::get);
featureSetCache =
CacheBuilder.newBuilder().maximumSize(MAX_SPEC_COUNT).build(featureSetCacheLoader);
featureSetCache.putAll(featureSets);
@@ -100,7 +104,9 @@ public FeatureSetSpec getFeatureSetSpec(String featureSetRef) throws ExecutionEx
}
/**
- * Get FeatureSetSpecs for the given features.
+ * 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,
*
* @return FeatureSetRequest containing the specs, and their respective feature references
*/
@@ -109,15 +115,22 @@ public List getFeatureSets(List featureRefe
featureReferences.stream()
.map(
featureReference -> {
- String featureSet =
+ // map feature reference to coresponding feature set name
+ String fsName =
featureToFeatureSetMapping.get(generateFeatureStringRef(featureReference));
- if (featureSet == null) {
+ if (fsName == null) {
throw new SpecRetrievalException(
String.format(
- "Unable to find feature set for feature ref: " + "(project: %s, name: %s)",
- featureReference.getProject(), featureReference.getName()));
+ "Unable to find Feature Set for the given Feature Reference: %s",
+ generateFeatureStringRef(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)",
+ generateFeatureStringRef(featureReference)));
}
- return Pair.of(featureSet, featureReference);
+ return Pair.of(fsName, featureReference);
})
.collect(groupingBy(Pair::getLeft))
.forEach(
@@ -126,6 +139,19 @@ public List getFeatureSets(List featureRefe
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)
@@ -150,8 +176,7 @@ public void populateCache() {
featureSetCache.invalidateAll();
featureSetCache.putAll(featureSetMap);
- featureToFeatureSetMapping.clear();
- featureToFeatureSetMapping.putAll(getFeatureToFeatureSetMapping(featureSetMap));
+ featureToFeatureSetMapping = getFeatureToFeatureSetMapping(featureSetMap);
featureSetsCount.set(featureSetCache.size());
cacheLastUpdated.set(System.currentTimeMillis());
@@ -191,21 +216,81 @@ private Map getFeatureSetMap() {
return featureSets;
}
+ /**
+ * Generate a feature to feature set mapping from the given feature sets map. Accounts for
+ * variations (missing project, feature_set) in string feature references generated by creating
+ * multiple entries in the returned mapping for each variation.
+ *
+ * @param featureSets map of feature set name to feature set specs
+ * @return mapping of string feature references to name of feature sets
+ */
private Map getFeatureToFeatureSetMapping(
Map featureSets) {
- HashMap mapping = new HashMap<>();
-
- for (FeatureSetSpec featureSetSpec : featureSets.values()) {
- for (FeatureSpec featureSpec : featureSetSpec.getFeaturesList()) {
- FeatureReference featureRef =
- FeatureReference.newBuilder()
- .setProject(featureSetSpec.getProject())
- .setName(featureSpec.getName())
- .build();
- mapping.put(
- generateFeatureStringRef(featureRef), generateFeatureSetStringRef(featureSetSpec));
- }
- }
+ Map mapping = new HashMap<>();
+
+ featureSets.values().stream()
+ .forEach(
+ featureSetSpec -> {
+ for (FeatureSpec featureSpec : featureSetSpec.getFeaturesList()) {
+ // Register the different permutations of string feature references
+ // that refers to this feature in the feature to featureset mapping.
+
+ // Features in FeatureSets in default project can be referenced without project.
+ boolean isInDefaultProject =
+ featureSetSpec.getProject().equals(DEFAULT_PROJECT_NAME);
+
+ for (boolean hasProject : new boolean[] {true, false}) {
+ if (!isInDefaultProject && !hasProject) continue;
+ // Features can be referenced without a featureset if there are no conflicts.
+ for (boolean hasFeatureSet : new boolean[] {true, false}) {
+ // Get mapping between string feature reference and featureset
+ Pair singleMapping =
+ this.generateFeatureToFeatureSetMapping(
+ featureSpec, featureSetSpec, hasProject, hasFeatureSet);
+ String featureRef = singleMapping.getKey();
+ String featureSetRef = singleMapping.getValue();
+ // Check if another feature set has already mapped to this
+ // string feature reference. if so mark the conflict.
+ if (mapping.containsKey(featureRef)) {
+ mapping.put(featureRef, FEATURE_SET_CONFLICT_FLAG);
+ } else {
+ mapping.put(featureRef, featureSetRef);
+ }
+ }
+ }
+ }
+ });
+
return mapping;
}
+
+ /**
+ * Generate a single mapping between the given feature and the featureset. Maps a feature
+ * reference refering to the given feature to the corresponding featureset's name.
+ *
+ * @param featureSpec specifying the feature to create mapping for.
+ * @param featureSetSpec specifying the feature set to create mapping for.
+ * @param hasProject whether generated mapping's string feature ref has a project.
+ * @param hasFeatureSet whether generated mapping's string feature ref has a featureSet.
+ * @return a pair mapping a string feature reference to a featureset name.
+ */
+ private Pair generateFeatureToFeatureSetMapping(
+ FeatureSpec featureSpec,
+ FeatureSetSpec featureSetSpec,
+ boolean hasProject,
+ boolean hasFeatureSet) {
+ FeatureReference.Builder featureRef =
+ FeatureReference.newBuilder()
+ .setProject(featureSetSpec.getProject())
+ .setFeatureSet(featureSetSpec.getName())
+ .setName(featureSpec.getName());
+ if (!hasProject) {
+ featureRef = featureRef.clearProject();
+ }
+ if (!hasFeatureSet) {
+ featureRef = featureRef.clearFeatureSet();
+ }
+ return Pair.of(
+ generateFeatureStringRef(featureRef.build()), generateFeatureSetStringRef(featureSetSpec));
+ }
}
diff --git a/serving/src/main/java/feast/serving/util/RefUtil.java b/serving/src/main/java/feast/serving/util/RefUtil.java
index 018b440c503..e3c36f1f9f6 100644
--- a/serving/src/main/java/feast/serving/util/RefUtil.java
+++ b/serving/src/main/java/feast/serving/util/RefUtil.java
@@ -21,7 +21,13 @@
public class RefUtil {
public static String generateFeatureStringRef(FeatureReference featureReference) {
- String ref = String.format("%s/%s", featureReference.getProject(), featureReference.getName());
+ String ref = featureReference.getName();
+ if (!featureReference.getFeatureSet().isEmpty()) {
+ ref = featureReference.getFeatureSet() + ":" + ref;
+ }
+ if (!featureReference.getProject().isEmpty()) {
+ ref = featureReference.getProject() + "/" + ref;
+ }
return ref;
}
diff --git a/serving/src/test/java/feast/serving/controller/ServingServiceGRpcControllerTest.java b/serving/src/test/java/feast/serving/controller/ServingServiceGRpcControllerTest.java
index bf8ed710ca7..5c8308daea5 100644
--- a/serving/src/test/java/feast/serving/controller/ServingServiceGRpcControllerTest.java
+++ b/serving/src/test/java/feast/serving/controller/ServingServiceGRpcControllerTest.java
@@ -51,10 +51,8 @@ public void setUp() {
validRequest =
GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").build())
- .addFeatures(
- FeatureReference.newBuilder().setName("feature2").setProject("project").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature1").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature2").build())
.addEntityRows(
EntityRow.newBuilder()
.setEntityTimestamp(Timestamp.newBuilder().setSeconds(100))
diff --git a/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java b/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
index 66a443ae777..85f590d5238 100644
--- a/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
+++ b/serving/src/test/java/feast/serving/service/CachedSpecServiceTest.java
@@ -24,22 +24,19 @@
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
-import com.google.common.collect.Lists;
import feast.proto.core.CoreServiceProto.ListFeatureSetsRequest;
import feast.proto.core.CoreServiceProto.ListFeatureSetsResponse;
import feast.proto.core.FeatureSetProto;
import feast.proto.core.FeatureSetProto.FeatureSetSpec;
import feast.proto.core.FeatureSetProto.FeatureSpec;
import feast.proto.core.StoreProto.Store;
-import feast.proto.core.StoreProto.Store.RedisConfig;
-import feast.proto.core.StoreProto.Store.StoreType;
import feast.proto.core.StoreProto.Store.Subscription;
import feast.proto.serving.ServingAPIProto.FeatureReference;
+import feast.serving.exception.SpecRetrievalException;
import feast.serving.specs.CachedSpecService;
import feast.serving.specs.CoreSpecService;
import feast.storage.api.retriever.FeatureSetRequest;
-import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
@@ -63,70 +60,60 @@ public class CachedSpecServiceTest {
public void setUp() {
initMocks(this);
- store =
- Store.newBuilder()
- .setName("SERVING")
- .setType(StoreType.REDIS)
- .setRedisConfig(RedisConfig.newBuilder().setHost("localhost").setPort(6379))
- .addSubscriptions(
- Subscription.newBuilder().setProject("project").setName("fs1").build())
- .addSubscriptions(
- Subscription.newBuilder().setProject("project").setName("fs2").build())
- .build();
-
- when(coreService.registerStore(store)).thenReturn(store);
+ this.store = Store.newBuilder().build();
+ this.featureSetSpecs = new HashMap<>();
- featureSetSpecs = new LinkedHashMap<>();
- featureSetSpecs.put(
+ this.setupFeatureSetAndStoreSubscription(
+ "project",
"fs1",
- FeatureSetSpec.newBuilder()
- .setProject("project")
- .setName("fs1")
- .addFeatures(FeatureSpec.newBuilder().setName("feature"))
- .build());
- featureSetSpecs.put(
- "fs1",
- FeatureSetSpec.newBuilder()
- .setProject("project")
- .setName("fs1")
- .addFeatures(FeatureSpec.newBuilder().setName("feature"))
- .addFeatures(FeatureSpec.newBuilder().setName("feature2"))
- .build());
- featureSetSpecs.put(
+ List.of(
+ FeatureSpec.newBuilder().setName("feature").build(),
+ FeatureSpec.newBuilder().setName("feature2").build()));
+
+ this.setupFeatureSetAndStoreSubscription(
+ "default",
"fs2",
+ List.of(
+ FeatureSpec.newBuilder().setName("feature3").build(),
+ FeatureSpec.newBuilder().setName("feature4").build(),
+ FeatureSpec.newBuilder().setName("feature5").build()));
+
+ this.setupFeatureSetAndStoreSubscription(
+ "default", "fs3", List.of(FeatureSpec.newBuilder().setName("feature4").build()));
+
+ when(this.coreService.registerStore(store)).thenReturn(store);
+ cachedSpecService = new CachedSpecService(this.coreService, this.store);
+ }
+
+ private void setupFeatureSetAndStoreSubscription(
+ String project, String name, List featureSpecs) {
+ FeatureSetSpec fsSpec =
FeatureSetSpec.newBuilder()
- .setProject("project")
- .setName("fs2")
- .addFeatures(FeatureSpec.newBuilder().setName("feature3"))
- .build());
-
- List fs1FeatureSets =
- Lists.newArrayList(
- FeatureSetProto.FeatureSet.newBuilder().setSpec(featureSetSpecs.get("fs1")).build(),
- FeatureSetProto.FeatureSet.newBuilder().setSpec(featureSetSpecs.get("fs1")).build());
- List fs2FeatureSets =
- Lists.newArrayList(
- FeatureSetProto.FeatureSet.newBuilder().setSpec(featureSetSpecs.get("fs2")).build());
- when(coreService.listFeatureSets(
- ListFeatureSetsRequest.newBuilder()
- .setFilter(
- ListFeatureSetsRequest.Filter.newBuilder()
- .setProject("project")
- .setFeatureSetName("fs1")
- .build())
- .build()))
- .thenReturn(ListFeatureSetsResponse.newBuilder().addAllFeatureSets(fs1FeatureSets).build());
+ .setProject(project)
+ .setName(name)
+ .addAllFeatures(featureSpecs)
+ .build();
+ this.featureSetSpecs.put(String.format("%s", name), fsSpec);
+
+ this.store =
+ this.store
+ .toBuilder()
+ .addSubscriptions(Subscription.newBuilder().setProject(project).setName(name).build())
+ .build();
+
+ // collect the different versions the featureset with the given name
+ FeatureSetProto.FeatureSet featureSet =
+ FeatureSetProto.FeatureSet.newBuilder().setSpec(fsSpec).build();
+
when(coreService.listFeatureSets(
ListFeatureSetsRequest.newBuilder()
.setFilter(
ListFeatureSetsRequest.Filter.newBuilder()
- .setProject("project")
- .setFeatureSetName("fs2")
+ .setProject(project)
+ .setFeatureSetName(name)
.build())
.build()))
- .thenReturn(ListFeatureSetsResponse.newBuilder().addAllFeatureSets(fs2FeatureSets).build());
-
- cachedSpecService = new CachedSpecService(coreService, store);
+ .thenReturn(ListFeatureSetsResponse.newBuilder().addFeatureSets(featureSet).build());
}
@Test
@@ -143,64 +130,95 @@ public void shouldPopulateAndReturnStore() {
@Test
public void shouldPopulateAndReturnFeatureSets() {
+ // test that CachedSpecService can retrieve fully qualified feature references.
cachedSpecService.populateCache();
- FeatureReference frv1 =
- FeatureReference.newBuilder().setProject("project").setName("feature").build();
- FeatureReference frv2 =
- FeatureReference.newBuilder().setProject("project").setName("feature").build();
+ FeatureReference fs1fr1 =
+ FeatureReference.newBuilder()
+ .setProject("project")
+ .setName("feature")
+ .setFeatureSet("fs1")
+ .build();
+ FeatureReference fs1fr2 =
+ FeatureReference.newBuilder()
+ .setProject("project")
+ .setName("feature2")
+ .setFeatureSet("fs1")
+ .build();
assertThat(
- cachedSpecService.getFeatureSets(Collections.singletonList(frv1)),
+ cachedSpecService.getFeatureSets(List.of(fs1fr1, fs1fr2)),
equalTo(
- Lists.newArrayList(
+ List.of(
FeatureSetRequest.newBuilder()
- .addFeatureReference(frv1)
+ .addFeatureReference(fs1fr1)
+ .addFeatureReference(fs1fr2)
.setSpec(featureSetSpecs.get("fs1"))
.build())));
+ }
+
+ @Test
+ public void shouldPopulateAndReturnFeatureSetWithDefaultProjectIfProjectNotSupplied() {
+ // test that CachedSpecService will use default project when project unspecified
+ FeatureReference fs2fr3 =
+ FeatureReference.newBuilder().setName("feature3").setFeatureSet("fs2").build();
+ // check that this is true for references in where feature set is unspecified
+ FeatureReference fs2fr5 = FeatureReference.newBuilder().setName("feature5").build();
+
assertThat(
- cachedSpecService.getFeatureSets(Collections.singletonList(frv2)),
+ cachedSpecService.getFeatureSets(List.of(fs2fr3, fs2fr5)),
equalTo(
- Lists.newArrayList(
+ List.of(
FeatureSetRequest.newBuilder()
- .addFeatureReference(frv2)
- .setSpec(featureSetSpecs.get("fs1"))
+ .addFeatureReference(fs2fr3)
+ .addFeatureReference(fs2fr5)
+ .setSpec(featureSetSpecs.get("fs2"))
.build())));
}
@Test
- public void shouldPopulateAndReturnLatestFeatureSetIfVersionsNotSupplied() {
- cachedSpecService.populateCache();
- FeatureReference frv1 =
+ public void shouldPopulateAndReturnClosestFeatureSetIfFeatureSetNotSupplied() {
+ // test that CachedSpecService will try to match a featureset without a featureset name in
+ // reference
+ FeatureReference fs1fr1 =
FeatureReference.newBuilder().setProject("project").setName("feature").build();
+ // check that this is true for reference in which project is unspecified
+ FeatureReference fs2fr3 = FeatureReference.newBuilder().setName("feature3").build();
+
assertThat(
- cachedSpecService.getFeatureSets(Collections.singletonList(frv1)),
- equalTo(
- Lists.newArrayList(
- FeatureSetRequest.newBuilder()
- .addFeatureReference(frv1)
- .setSpec(featureSetSpecs.get("fs1"))
- .build())));
+ cachedSpecService.getFeatureSets(List.of(fs1fr1, fs2fr3)),
+ containsInAnyOrder(
+ List.of(
+ FeatureSetRequest.newBuilder()
+ .addFeatureReference(fs1fr1)
+ .setSpec(featureSetSpecs.get("fs1"))
+ .build(),
+ FeatureSetRequest.newBuilder()
+ .addFeatureReference(fs2fr3)
+ .setSpec(featureSetSpecs.get("fs2"))
+ .build())
+ .toArray()));
}
@Test
public void shouldPopulateAndReturnFeatureSetsGivenFeaturesFromDifferentFeatureSets() {
cachedSpecService.populateCache();
- FeatureReference frv1 =
+ FeatureReference fs1fr1 =
FeatureReference.newBuilder().setProject("project").setName("feature").build();
- FeatureReference fr3 =
- FeatureReference.newBuilder().setProject("project").setName("feature3").build();
+
+ FeatureReference fs2fr3 =
+ FeatureReference.newBuilder().setProject("default").setName("feature3").build();
assertThat(
- cachedSpecService.getFeatureSets(Lists.newArrayList(frv1, fr3)),
+ cachedSpecService.getFeatureSets(List.of(fs1fr1, fs2fr3)),
containsInAnyOrder(
- Lists.newArrayList(
+ List.of(
FeatureSetRequest.newBuilder()
- .addFeatureReference(frv1)
+ .addFeatureReference(fs1fr1)
.setSpec(featureSetSpecs.get("fs1"))
.build(),
FeatureSetRequest.newBuilder()
- .addFeatureReference(fr3)
+ .addFeatureReference(fs2fr3)
.setSpec(featureSetSpecs.get("fs2"))
.build())
.toArray()));
@@ -215,13 +233,26 @@ public void shouldPopulateAndReturnFeatureSetGivenFeaturesFromSameFeatureSet() {
FeatureReference.newBuilder().setProject("project").setName("feature2").build();
assertThat(
- cachedSpecService.getFeatureSets(Lists.newArrayList(fr1, fr2)),
+ cachedSpecService.getFeatureSets(List.of(fr1, fr2)),
equalTo(
- Lists.newArrayList(
+ List.of(
FeatureSetRequest.newBuilder()
.addFeatureReference(fr1)
.addFeatureReference(fr2)
.setSpec(featureSetSpecs.get("fs1"))
.build())));
}
+
+ @Test
+ public void shouldThrowExceptionWhenMultipleFeatureSetMapToFeatureReference()
+ throws SpecRetrievalException {
+ // both fs2 and fs3 have the feature with the same name.
+ // using a generic feature reference only specifying the feature's name
+ // should cause a multiple feature sets to match and throw an error
+ FeatureReference fs2fr4 = FeatureReference.newBuilder().setName("feature4").build();
+ FeatureReference fs3fr4 = FeatureReference.newBuilder().setName("feature4").build();
+
+ expectedException.expect(SpecRetrievalException.class);
+ cachedSpecService.getFeatureSets(List.of(fs2fr4, fs3fr4));
+ }
}
diff --git a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java
index 3148d0e030d..6358460a070 100644
--- a/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java
+++ b/serving/src/test/java/feast/serving/service/OnlineServingServiceTest.java
@@ -69,10 +69,8 @@ public void setUp() {
public void shouldReturnResponseWithValuesIfKeysPresent() {
GetOnlineFeaturesRequest request =
GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").build())
- .addFeatures(
- FeatureReference.newBuilder().setName("feature2").setProject("project").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature1").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature2").build())
.addEntityRows(
EntityRow.newBuilder()
.setEntityTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -95,7 +93,6 @@ public void shouldReturnResponseWithValuesIfKeysPresent() {
Field.newBuilder().setName("entity2").setValue(strValue("a")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(1)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(1)).build()))
- .setFeatureSet("featureSet")
.build(),
FeatureRow.newBuilder()
.setEventTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -105,7 +102,6 @@ public void shouldReturnResponseWithValuesIfKeysPresent() {
Field.newBuilder().setName("entity2").setValue(strValue("b")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(2)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(2)).build()))
- .setFeatureSet("featureSet")
.build());
FeatureSetRequest featureSetRequest =
@@ -127,90 +123,14 @@ public void shouldReturnResponseWithValuesIfKeysPresent() {
FieldValues.newBuilder()
.putFields("entity1", intValue(1))
.putFields("entity2", strValue("a"))
- .putFields("project/feature1", intValue(1))
- .putFields("project/feature2", intValue(1)))
+ .putFields("feature1", intValue(1))
+ .putFields("feature2", intValue(1)))
.addFieldValues(
FieldValues.newBuilder()
.putFields("entity1", intValue(2))
.putFields("entity2", strValue("b"))
- .putFields("project/feature1", intValue(2))
- .putFields("project/feature2", intValue(2)))
- .build();
- GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request);
- assertThat(
- responseToMapList(actual), containsInAnyOrder(responseToMapList(expected).toArray()));
- }
-
- @Test
- public void shouldReturnKeysWithoutVersionIfNotProvided() {
- GetOnlineFeaturesRequest request =
- GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").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(
- FeatureRow.newBuilder()
- .setEventTimestamp(Timestamp.newBuilder().setSeconds(100))
- .addAllFields(
- Lists.newArrayList(
- Field.newBuilder().setName("entity1").setValue(intValue(1)).build(),
- Field.newBuilder().setName("entity2").setValue(strValue("a")).build(),
- Field.newBuilder().setName("feature1").setValue(intValue(1)).build(),
- Field.newBuilder().setName("feature2").setValue(intValue(1)).build()))
- .setFeatureSet("featureSet")
- .build(),
- FeatureRow.newBuilder()
- .setEventTimestamp(Timestamp.newBuilder().setSeconds(100))
- .addAllFields(
- Lists.newArrayList(
- Field.newBuilder().setName("entity1").setValue(intValue(2)).build(),
- Field.newBuilder().setName("entity2").setValue(strValue("b")).build(),
- Field.newBuilder().setName("feature1").setValue(intValue(2)).build(),
- Field.newBuilder().setName("feature2").setValue(intValue(2)).build()))
- .setFeatureSet("featureSet")
- .build());
-
- FeatureSetRequest featureSetRequest =
- FeatureSetRequest.newBuilder()
- .addAllFeatureReferences(request.getFeaturesList())
- .setSpec(getFeatureSetSpec())
- .build();
-
- when(specService.getFeatureSets(request.getFeaturesList()))
- .thenReturn(Collections.singletonList(featureSetRequest));
- when(retriever.getOnlineFeatures(
- request.getEntityRowsList(), Collections.singletonList(featureSetRequest)))
- .thenReturn(Collections.singletonList(featureRows));
- when(tracer.buildSpan(ArgumentMatchers.any())).thenReturn(Mockito.mock(SpanBuilder.class));
-
- GetOnlineFeaturesResponse expected =
- GetOnlineFeaturesResponse.newBuilder()
- .addFieldValues(
- FieldValues.newBuilder()
- .putFields("entity1", intValue(1))
- .putFields("entity2", strValue("a"))
- .putFields("project/feature1", intValue(1))
- .putFields("project/feature2", intValue(1)))
- .addFieldValues(
- FieldValues.newBuilder()
- .putFields("entity1", intValue(2))
- .putFields("entity2", strValue("b"))
- .putFields("project/feature1", intValue(2))
- .putFields("project/feature2", intValue(2)))
+ .putFields("feature1", intValue(2))
+ .putFields("feature2", intValue(2)))
.build();
GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request);
assertThat(
@@ -222,10 +142,8 @@ public void shouldReturnResponseWithUnsetValuesIfKeysNotPresent() {
// some keys not present, should have empty values
GetOnlineFeaturesRequest request =
GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").build())
- .addFeatures(
- FeatureReference.newBuilder().setName("feature2").setProject("project").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature1").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature2").build())
.addEntityRows(
EntityRow.newBuilder()
.setEntityTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -275,14 +193,14 @@ public void shouldReturnResponseWithUnsetValuesIfKeysNotPresent() {
FieldValues.newBuilder()
.putFields("entity1", intValue(1))
.putFields("entity2", strValue("a"))
- .putFields("project/feature1", intValue(1))
- .putFields("project/feature2", intValue(1)))
+ .putFields("feature1", intValue(1))
+ .putFields("feature2", intValue(1)))
.addFieldValues(
FieldValues.newBuilder()
.putFields("entity1", intValue(2))
.putFields("entity2", strValue("b"))
- .putFields("project/feature1", Value.newBuilder().build())
- .putFields("project/feature2", Value.newBuilder().build()))
+ .putFields("feature1", Value.newBuilder().build())
+ .putFields("feature2", Value.newBuilder().build()))
.build();
GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request);
assertThat(
@@ -294,10 +212,8 @@ public void shouldReturnResponseWithUnsetValuesIfMaxAgeIsExceeded() {
// keys present, but too stale comp. to maxAge
GetOnlineFeaturesRequest request =
GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").build())
- .addFeatures(
- FeatureReference.newBuilder().setName("feature2").setProject("project").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature1").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature2").build())
.addEntityRows(
EntityRow.newBuilder()
.setEntityTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -320,7 +236,7 @@ public void shouldReturnResponseWithUnsetValuesIfMaxAgeIsExceeded() {
Field.newBuilder().setName("entity2").setValue(strValue("a")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(1)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(1)).build()))
- .setFeatureSet("featureSet")
+ .setFeatureSet("project/featureSet")
.build(),
FeatureRow.newBuilder()
.setEventTimestamp(
@@ -331,7 +247,7 @@ public void shouldReturnResponseWithUnsetValuesIfMaxAgeIsExceeded() {
Field.newBuilder().setName("entity2").setValue(strValue("b")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(2)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(2)).build()))
- .setFeatureSet("featureSet")
+ .setFeatureSet("project/featureSet")
.build());
FeatureSetSpec spec =
@@ -355,14 +271,14 @@ public void shouldReturnResponseWithUnsetValuesIfMaxAgeIsExceeded() {
FieldValues.newBuilder()
.putFields("entity1", intValue(1))
.putFields("entity2", strValue("a"))
- .putFields("project/feature1", intValue(1))
- .putFields("project/feature2", intValue(1)))
+ .putFields("feature1", intValue(1))
+ .putFields("feature2", intValue(1)))
.addFieldValues(
FieldValues.newBuilder()
.putFields("entity1", intValue(2))
.putFields("entity2", strValue("b"))
- .putFields("project/feature1", Value.newBuilder().build())
- .putFields("project/feature2", Value.newBuilder().build()))
+ .putFields("feature1", Value.newBuilder().build())
+ .putFields("feature2", Value.newBuilder().build()))
.build();
GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request);
assertThat(
@@ -374,8 +290,7 @@ public void shouldFilterOutUndesiredRows() {
// requested rows less than the rows available in the featureset
GetOnlineFeaturesRequest request =
GetOnlineFeaturesRequest.newBuilder()
- .addFeatures(
- FeatureReference.newBuilder().setName("feature1").setProject("project").build())
+ .addFeatures(FeatureReference.newBuilder().setName("feature1").build())
.addEntityRows(
EntityRow.newBuilder()
.setEntityTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -398,7 +313,6 @@ public void shouldFilterOutUndesiredRows() {
Field.newBuilder().setName("entity2").setValue(strValue("a")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(1)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(1)).build()))
- .setFeatureSet("featureSet")
.build(),
FeatureRow.newBuilder()
.setEventTimestamp(Timestamp.newBuilder().setSeconds(100))
@@ -408,7 +322,6 @@ public void shouldFilterOutUndesiredRows() {
Field.newBuilder().setName("entity2").setValue(strValue("b")).build(),
Field.newBuilder().setName("feature1").setValue(intValue(2)).build(),
Field.newBuilder().setName("feature2").setValue(intValue(2)).build()))
- .setFeatureSet("featureSet")
.build());
FeatureSetRequest featureSetRequest =
@@ -430,12 +343,12 @@ public void shouldFilterOutUndesiredRows() {
FieldValues.newBuilder()
.putFields("entity1", intValue(1))
.putFields("entity2", strValue("a"))
- .putFields("project/feature1", intValue(1)))
+ .putFields("feature1", intValue(1)))
.addFieldValues(
FieldValues.newBuilder()
.putFields("entity1", intValue(2))
.putFields("entity2", strValue("b"))
- .putFields("project/feature1", intValue(2)))
+ .putFields("feature1", intValue(2)))
.build();
GetOnlineFeaturesResponse actual = onlineServingService.getOnlineFeatures(request);
assertThat(
@@ -458,7 +371,6 @@ private Value strValue(String val) {
private FeatureSetSpec getFeatureSetSpec() {
return FeatureSetSpec.newBuilder()
- .setProject("project")
.setName("featureSet")
.addEntities(EntitySpec.newBuilder().setName("entity1"))
.addEntities(EntitySpec.newBuilder().setName("entity2"))
diff --git a/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/FeatureSetQueryInfo.java b/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/FeatureSetQueryInfo.java
index a99411f87b9..befdc564904 100644
--- a/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/FeatureSetQueryInfo.java
+++ b/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/FeatureSetQueryInfo.java
@@ -16,6 +16,7 @@
*/
package feast.storage.connectors.bigquery.retriever;
+import feast.proto.serving.ServingAPIProto.FeatureReference;
import java.util.List;
public class FeatureSetQueryInfo {
@@ -24,7 +25,7 @@ public class FeatureSetQueryInfo {
private final String name;
private final long maxAge;
private final List entities;
- private final List features;
+ private final List features;
private final String table;
public FeatureSetQueryInfo(
@@ -32,7 +33,7 @@ public FeatureSetQueryInfo(
String name,
long maxAge,
List entities,
- List features,
+ List features,
String table) {
this.project = project;
this.name = name;
@@ -68,7 +69,7 @@ public List getEntities() {
return entities;
}
- public List getFeatures() {
+ public List getFeatures() {
return features;
}
diff --git a/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/QueryTemplater.java b/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/QueryTemplater.java
index 84899d69adb..969efb36c38 100644
--- a/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/QueryTemplater.java
+++ b/storage/connectors/bigquery/src/main/java/feast/storage/connectors/bigquery/retriever/QueryTemplater.java
@@ -79,10 +79,7 @@ public static List getFeatureSetInfos(
Duration maxAge = spec.getMaxAge();
List fsEntities =
spec.getEntitiesList().stream().map(EntitySpec::getName).collect(Collectors.toList());
- List features =
- featureSetRequest.getFeatureReferences().stream()
- .map(FeatureReference::getName)
- .collect(Collectors.toList());
+ List features = featureSetRequest.getFeatureReferences().asList();
featureSetInfos.add(
new FeatureSetQueryInfo(
spec.getProject(), spec.getName(), maxAge.getSeconds(), fsEntities, features, ""));
diff --git a/storage/connectors/bigquery/src/main/resources/templates/join_featuresets.sql b/storage/connectors/bigquery/src/main/resources/templates/join_featuresets.sql
index 10aafb05092..ddddac8d2cf 100644
--- a/storage/connectors/bigquery/src/main/resources/templates/join_featuresets.sql
+++ b/storage/connectors/bigquery/src/main/resources/templates/join_featuresets.sql
@@ -7,8 +7,8 @@ SELECT * FROM `{{ leftTableName }}`
LEFT JOIN (
SELECT
uuid,
- {% for featureName in featureSet.features %}
- {{ featureSet.project }}_{{ featureName }}{% if loop.last %}{% else %}, {% endif %}
+ {% for feature in featureSet.features %}
+ {{ featureSet.project }}__{{ featureSet.name }}__{{ feature.name }}{% if loop.last %}{% else %}, {% endif %}
{% endfor %}
FROM `{{ featureSet.table }}`
) USING (uuid)
@@ -17,8 +17,8 @@ LEFT JOIN (
event_timestamp,
{{ entities | join(', ') }}
{% for featureSet in featureSets %}
- {% for featureName in featureSet.features %}
- ,{{ featureSet.project }}_{{ featureName }} as {{ featureName }}
+ {% for feature in featureSet.features %}
+ ,{{ featureSet.project }}__{{ featureSet.name }}__{{ feature.name }} as {% if feature.featureSet != "" %}{{ featureSet.name }}__{% endif %}{{ feature.name }}
{% endfor %}
{% endfor %}
-FROM joined
\ No newline at end of file
+FROM joined
diff --git a/storage/connectors/bigquery/src/main/resources/templates/single_featureset_pit_join.sql b/storage/connectors/bigquery/src/main/resources/templates/single_featureset_pit_join.sql
index c02bf6b46c1..24bdab2c29c 100644
--- a/storage/connectors/bigquery/src/main/resources/templates/single_featureset_pit_join.sql
+++ b/storage/connectors/bigquery/src/main/resources/templates/single_featureset_pit_join.sql
@@ -47,8 +47,8 @@ SELECT
uuid,
event_timestamp,
{{ featureSet.entities | join(', ')}},
- {% for featureName in featureSet.features %}
- IF(event_timestamp >= {{ featureSet.project }}_{{ featureSet.name }}_feature_timestamp {% if featureSet.maxAge == 0 %}{% else %}AND Timestamp_sub(event_timestamp, interval {{ featureSet.maxAge }} second) < {{ featureSet.project }}_{{ featureSet.name }}_feature_timestamp{% endif %}, {{ featureSet.project }}_{{ featureName }}, NULL) as {{ featureSet.project }}_{{ featureName }}{% if loop.last %}{% else %}, {% endif %}
+ {% for feature in featureSet.features %}
+ IF(event_timestamp >= {{ featureSet.project }}_{{ featureSet.name }}_feature_timestamp {% if featureSet.maxAge == 0 %}{% else %}AND Timestamp_sub(event_timestamp, interval {{ featureSet.maxAge }} second) < {{ featureSet.project }}_{{ featureSet.name }}_feature_timestamp{% endif %}, {{ featureSet.project }}__{{ featureSet.name }}__{{ feature.name }}, NULL) as {{ featureSet.project }}__{{ featureSet.name }}__{{ feature.name }}{% if loop.last %}{% else %}, {% endif %}
{% endfor %}
FROM (
SELECT
@@ -70,8 +70,8 @@ SELECT
event_timestamp as {{ featureSet.project }}_{{ featureSet.name }}_feature_timestamp,
created_timestamp,
{{ featureSet.entities | join(', ')}},
- {% for featureName in featureSet.features %}
- {{ featureName }} as {{ featureSet.project }}_{{ featureName }}{% if loop.last %}{% else %}, {% endif %}
+ {% for feature in featureSet.features %}
+ {{ feature.name }} as {{ featureSet.project }}__{{ featureSet.name }}__{{ feature.name }}{% if loop.last %}{% else %}, {% endif %}
{% endfor %}
FROM `{{ projectId }}.{{ datasetId }}.{{ featureSet.project }}_{{ featureSet.name }}` WHERE event_timestamp <= '{{maxTimestamp}}'
{% if featureSet.maxAge == 0 %}{% else %}AND event_timestamp >= Timestamp_sub(TIMESTAMP '{{ minTimestamp }}', interval {{ featureSet.maxAge }} second){% endif %}
diff --git a/tests/e2e/basic-ingest-redis-serving.py b/tests/e2e/basic-ingest-redis-serving.py
index adf0669a715..311f1282477 100644
--- a/tests/e2e/basic-ingest-redis-serving.py
+++ b/tests/e2e/basic-ingest-redis-serving.py
@@ -15,6 +15,7 @@
from feast.client import Client
from feast.feature_set import FeatureSet, FeatureSetRef
from feast.type_map import ValueType
+from feast.constants import FEAST_DEFAULT_OPTIONS, CONFIG_PROJECT_KEY
from google.protobuf.duration_pb2 import Duration
from datetime import datetime
import pytz
@@ -29,7 +30,6 @@
FLOAT_TOLERANCE = 0.00001
PROJECT_NAME = 'basic_' + uuid.uuid4().hex.upper()[0:6]
-
@pytest.fixture(scope='module')
def core_url(pytestconfig):
return pytestconfig.getoption("core_url")
@@ -51,7 +51,6 @@ def client(core_url, serving_url, allow_dirty):
# Get client for core and serving
client = Client(core_url=core_url, serving_url=serving_url)
client.create_project(PROJECT_NAME)
- client.set_project(PROJECT_NAME)
# Ensure Feast core is active, but empty
if not allow_dirty:
@@ -63,80 +62,94 @@ def client(core_url, serving_url, allow_dirty):
return client
-
-@pytest.fixture(scope='module')
-def basic_dataframe():
+def basic_dataframe(entities, features, ingest_time, n_size):
offset = random.randint(1000, 100000) # ensure a unique key space is used
- return pd.DataFrame(
- {
- "datetime": [datetime.utcnow().replace(tzinfo=pytz.utc) for _ in
- range(5)],
- "customer_id": [offset + inc for inc in range(5)],
- "daily_transactions": [np.random.rand() for _ in range(5)],
- "total_transactions": [512 for _ in range(5)],
- }
- )
-
+ df_dict = {
+ "datetime": [ingest_time.replace(tzinfo=pytz.utc) for _ in
+ range(n_size)],
+ }
+ for entity_name in entities:
+ df_dict[entity_name] = list(range(1, n_size + 1))
+ for feature_name in features:
+ df_dict[feature_name] = [np.random.rand() for _ in range(n_size)]
+ return pd.DataFrame(df_dict)
+
+
+@pytest.fixture(scope="module")
+def ingest_time():
+ return datetime.utcnow()
+
+@pytest.fixture(scope="module")
+def cust_trans_df(ingest_time):
+ return basic_dataframe(entities=["customer_id"],
+ features=["daily_transactions", "total_transactions"],
+ ingest_time=ingest_time,
+ n_size=5)
+
+@pytest.fixture(scope="module")
+def driver_df(ingest_time):
+ return basic_dataframe(entities=["driver_id"],
+ features=["rating", "cost"],
+ ingest_time=ingest_time,
+ n_size=5)
@pytest.mark.timeout(45)
@pytest.mark.run(order=10)
def test_basic_register_feature_set_success(client):
- # Load feature set from file
+ # Register feature set without project
cust_trans_fs_expected = FeatureSet.from_yaml("basic/cust_trans_fs.yaml")
+ driver_fs_expected = FeatureSet.from_yaml("basic/driver_fs.yaml")
+ client.apply(cust_trans_fs_expected)
+ client.apply(driver_fs_expected)
+ cust_trans_fs_actual = client.get_feature_set("customer_transactions")
+ assert cust_trans_fs_actual == cust_trans_fs_expected
+ driver_fs_actual = client.get_feature_set("driver")
+ assert driver_fs_actual == driver_fs_expected
+ # Register feature set with project
+ cust_trans_fs_expected = FeatureSet.from_yaml("basic/cust_trans_fs.yaml")
client.set_project(PROJECT_NAME)
-
- # Register feature set
client.apply(cust_trans_fs_expected)
-
- cust_trans_fs_actual = client.get_feature_set(name="customer_transactions")
-
+ cust_trans_fs_actual = client.get_feature_set("customer_transactions",
+ project=PROJECT_NAME)
assert cust_trans_fs_actual == cust_trans_fs_expected
- if cust_trans_fs_actual is None:
- raise Exception(
- "Client cannot retrieve 'customer_transactions' FeatureSet "
- "after registration. Either Feast Core does not save the "
- "FeatureSet correctly or the client needs to wait longer for FeatureSet "
- "to be committed."
- )
-
+ # reset client's project for other tests
+ client.set_project()
@pytest.mark.timeout(300)
@pytest.mark.run(order=11)
-def test_basic_ingest_success(client, basic_dataframe):
- client.set_project(PROJECT_NAME)
-
+def test_basic_ingest_success(client, cust_trans_df, driver_df):
cust_trans_fs = client.get_feature_set(name="customer_transactions")
+ driver_fs = client.get_feature_set(name="driver")
# Ingest customer transaction data
- client.ingest(cust_trans_fs, basic_dataframe)
+ client.ingest(cust_trans_fs, cust_trans_df)
+ client.ingest(driver_fs, driver_df)
time.sleep(5)
@pytest.mark.timeout(45)
@pytest.mark.run(order=12)
-def test_basic_retrieve_online_success(client, basic_dataframe):
+def test_basic_retrieve_online_success(client, cust_trans_df):
# Poll serving for feature values until the correct values are returned
while True:
time.sleep(1)
-
- client.set_project(PROJECT_NAME)
-
response = client.get_online_features(
entity_rows=[
GetOnlineFeaturesRequest.EntityRow(
fields={
"customer_id": Value(
- int64_val=basic_dataframe.iloc[0]["customer_id"]
+ int64_val=cust_trans_df.iloc[0]["customer_id"]
)
}
)
],
+ # Test retrieve with different variations of the string feature refs
feature_refs=[
"daily_transactions",
"total_transactions",
- ],
+ ]
) # type: GetOnlineFeaturesResponse
if response is None:
@@ -144,23 +157,78 @@ def test_basic_retrieve_online_success(client, basic_dataframe):
returned_daily_transactions = float(
response.field_values[0]
- .fields[PROJECT_NAME + "/daily_transactions"]
- .float_val
+ .fields["daily_transactions"]
+ .float_val
)
sent_daily_transactions = float(
- basic_dataframe.iloc[0]["daily_transactions"])
+ cust_trans_df.iloc[0]["daily_transactions"])
if math.isclose(
- sent_daily_transactions,
- returned_daily_transactions,
- abs_tol=FLOAT_TOLERANCE,
+ sent_daily_transactions,
+ returned_daily_transactions,
+ abs_tol=FLOAT_TOLERANCE,
):
break
+@pytest.mark.timeout(45)
+@pytest.mark.run(order=13)
+def test_basic_retrieve_online_multiple_featureset(client, cust_trans_df, driver_df):
+ # Poll serving for feature values until the correct values are returned
+ while True:
+ time.sleep(1)
+ # Test retrieve with different variations of the string feature refs
+ # ie feature set inference for feature refs without specified feature set
+ feature_ref_df_mapping = [
+ ("customer_transactions:daily_transactions", cust_trans_df),
+ ("driver:rating", driver_df),
+ ("total_transactions", cust_trans_df),
+ ]
+ response = client.get_online_features(
+ entity_rows=[
+ GetOnlineFeaturesRequest.EntityRow(
+ fields={
+ "customer_id": Value(
+ int64_val=cust_trans_df.iloc[0]["customer_id"]
+ ),
+ "driver_id": Value(
+ int64_val=driver_df.iloc[0]["driver_id"]
+ )
+ }
+ )
+ ],
+ feature_refs=[mapping[0] for mapping in feature_ref_df_mapping],
+ ) # type: GetOnlineFeaturesResponse
+
+ if response is None:
+ continue
+
+ def check_response(ingest_df, response, feature_ref):
+ returned_value = float(
+ response.field_values[0]
+ .fields[feature_ref]
+ .float_val
+ )
+ feature_ref_splits = feature_ref.split(":")
+ if len(feature_ref_splits) == 1:
+ feature_name = feature_ref
+ else:
+ _, feature_name = feature_ref_splits
+
+ sent_value = float(
+ ingest_df.iloc[0][feature_name])
+
+ return math.isclose(
+ sent_value,
+ returned_value,
+ abs_tol=FLOAT_TOLERANCE,
+ )
+ if all([check_response(df, response, ref) for ref, df in feature_ref_df_mapping]):
+ break
+
@pytest.mark.timeout(300)
@pytest.mark.run(order=19)
-def test_basic_ingest_jobs(client, basic_dataframe):
+def test_basic_ingest_jobs(client):
# list ingestion jobs given featureset
cust_trans_fs = client.get_feature_set(name="customer_transactions")
ingest_jobs = client.list_ingest_jobs(
@@ -327,7 +395,7 @@ def test_all_types_retrieve_online_success(client, all_types_dataframe):
returned_float_list = (
response.field_values[0]
- .fields[PROJECT_NAME + "/float_list_feature"]
+ .fields["float_list_feature"]
.float_list_val.val
)
@@ -445,7 +513,7 @@ def test_large_volume_retrieve_online_success(client, large_volume_dataframe):
returned_daily_transactions = float(
response.field_values[0]
- .fields[PROJECT_NAME + "/daily_transactions_large"]
+ .fields["daily_transactions_large"]
.float_val
)
sent_daily_transactions = float(
diff --git a/tests/e2e/basic/driver_fs.yaml b/tests/e2e/basic/driver_fs.yaml
new file mode 100644
index 00000000000..f25ca956782
--- /dev/null
+++ b/tests/e2e/basic/driver_fs.yaml
@@ -0,0 +1,12 @@
+kind: feature_set
+spec:
+ name: driver
+ entities:
+ - name: driver_id
+ valueType: INT64
+ features:
+ - name: rating
+ valueType: FLOAT
+ - name: cost
+ valueType: FLOAT
+ maxAge: 3600s
diff --git a/tests/e2e/bq-batch-retrieval.py b/tests/e2e/bq-batch-retrieval.py
index a4d8a729ef7..99b88a8dff7 100644
--- a/tests/e2e/bq-batch-retrieval.py
+++ b/tests/e2e/bq-batch-retrieval.py
@@ -27,7 +27,6 @@
PROJECT_NAME = "batch_" + uuid.uuid4().hex.upper()[0:6]
-
@pytest.fixture(scope="module")
def core_url(pytestconfig):
return pytestconfig.getoption("core_url")
@@ -53,7 +52,6 @@ def client(core_url, serving_url, allow_dirty):
# Get client for core and serving
client = Client(core_url=core_url, serving_url=serving_url)
client.create_project(PROJECT_NAME)
- client.set_project(PROJECT_NAME)
# Ensure Feast core is active, but empty
if not allow_dirty:
@@ -167,7 +165,8 @@ def test_batch_get_batch_features_with_file(client):
time.sleep(15)
feature_retrieval_job = client.get_batch_features(
entity_rows="file://file_feature_set.avro",
- feature_refs=[f"{PROJECT_NAME}/feature_value1"],
+ feature_refs=["feature_value1"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
@@ -220,7 +219,9 @@ def test_batch_get_batch_features_with_gs_path(client, gcs_path):
time.sleep(15)
feature_retrieval_job = client.get_batch_features(
- entity_rows=f"{gcs_path}{ts}/*", feature_refs=[f"{PROJECT_NAME}/feature_value2"]
+ entity_rows=f"{gcs_path}{ts}/*",
+ feature_refs=["feature_value2"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
@@ -259,7 +260,8 @@ def test_batch_order_by_creation_time(client):
client.ingest(proc_time_fs, correct_df)
feature_retrieval_job = client.get_batch_features(
entity_rows=incorrect_df[["datetime", "entity_id"]],
- feature_refs=[f"{PROJECT_NAME}/feature_value3"],
+ feature_refs=["feature_value3"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
clean_up_remote_files(feature_retrieval_job.get_avro_files())
@@ -295,7 +297,9 @@ def test_batch_additional_columns_in_entity_table(client):
time.sleep(15)
feature_retrieval_job = client.get_batch_features(
- entity_rows=entity_df, feature_refs=[f"{PROJECT_NAME}/feature_value4"]
+ entity_rows=entity_df,
+ feature_refs=["feature_value4"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe().sort_values(by=["entity_id"])
clean_up_remote_files(feature_retrieval_job.get_avro_files())
@@ -341,7 +345,9 @@ def test_batch_point_in_time_correctness_join(client):
time.sleep(15)
feature_retrieval_job = client.get_batch_features(
- entity_rows=entity_df, feature_refs=[f"{PROJECT_NAME}/feature_value5"]
+ entity_rows=entity_df,
+ feature_refs=["feature_value5"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
clean_up_remote_files(feature_retrieval_job.get_avro_files())
@@ -385,12 +391,15 @@ def test_batch_multiple_featureset_joins(client):
)
time.sleep(15)
+ # Test retrieve with different variations of the string feature refs
+ # ie feature set inference for feature refs without specified feature set
feature_retrieval_job = client.get_batch_features(
entity_rows=entity_df,
feature_refs=[
- f"{PROJECT_NAME}/feature_value6",
- f"{PROJECT_NAME}/other_feature_value7",
+ "feature_value6",
+ "feature_set_2:other_feature_value7",
],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
clean_up_remote_files(feature_retrieval_job.get_avro_files())
@@ -400,7 +409,7 @@ def test_batch_multiple_featureset_joins(client):
int(i) for i in output["feature_value6"].to_list()
]
assert (
- output["other_entity_id"].to_list() == output["other_feature_value7"].to_list()
+ output["other_entity_id"].to_list() == output["feature_set_2__other_feature_value7"].to_list()
)
@@ -423,7 +432,8 @@ def test_batch_no_max_age(client):
time.sleep(15)
feature_retrieval_job = client.get_batch_features(
entity_rows=features_8_df[["datetime", "entity_id"]],
- feature_refs=[f"{PROJECT_NAME}/feature_value8"],
+ feature_refs=["feature_value8"],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe()
@@ -504,9 +514,10 @@ def test_update_featureset_apply_featureset_and_ingest_first_subset(
feature_retrieval_job = client.get_batch_features(
entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[:5],
feature_refs=[
- f"{PROJECT_NAME}/update_feature1",
- f"{PROJECT_NAME}/update_feature2",
+ "update_feature1",
+ "update_feature2",
],
+ project=PROJECT_NAME
)
output = feature_retrieval_job.to_dataframe().sort_values(by=["entity_id"])
@@ -557,10 +568,11 @@ def test_update_featureset_update_featureset_and_ingest_second_subset(
feature_retrieval_job = client.get_batch_features(
entity_rows=update_featureset_dataframe[["datetime", "entity_id"]].iloc[5:],
feature_refs=[
- f"{PROJECT_NAME}/update_feature1",
- f"{PROJECT_NAME}/update_feature3",
- f"{PROJECT_NAME}/update_feature4",
+ "update_feature1",
+ "update_feature3",
+ "update_feature4",
],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe().sort_values(by=["entity_id"])
@@ -579,11 +591,12 @@ def test_update_featureset_retrieve_all_fields(client, update_featureset_datafra
feature_retrieval_job = client.get_batch_features(
entity_rows=update_featureset_dataframe[["datetime", "entity_id"]],
feature_refs=[
- f"{PROJECT_NAME}/update_feature1",
- f"{PROJECT_NAME}/update_feature2",
- f"{PROJECT_NAME}/update_feature3",
- f"{PROJECT_NAME}/update_feature4",
+ "update_feature1",
+ "update_feature2",
+ "update_feature3",
+ "update_feature4",
],
+ project=PROJECT_NAME,
)
feature_retrieval_job.result()
@@ -594,10 +607,11 @@ def test_update_featureset_retrieve_valid_fields(client, update_featureset_dataf
feature_retrieval_job = client.get_batch_features(
entity_rows=update_featureset_dataframe[["datetime", "entity_id"]],
feature_refs=[
- f"{PROJECT_NAME}/update_feature1",
- f"{PROJECT_NAME}/update_feature3",
- f"{PROJECT_NAME}/update_feature4",
+ "update_feature1",
+ "update_feature3",
+ "update_feature4",
],
+ project=PROJECT_NAME,
)
output = feature_retrieval_job.to_dataframe().sort_values(by=["entity_id"])
clean_up_remote_files(feature_retrieval_job.get_avro_files())