diff --git a/common-test/src/main/java/feast/common/it/DataGenerator.java b/common-test/src/main/java/feast/common/it/DataGenerator.java
index 398d5b5abb..0606c75951 100644
--- a/common-test/src/main/java/feast/common/it/DataGenerator.java
+++ b/common-test/src/main/java/feast/common/it/DataGenerator.java
@@ -134,6 +134,19 @@ public static FeatureTableSpec createFeatureTableSpec(
.build())
.collect(Collectors.toList()))
.setMaxAge(Duration.newBuilder().setSeconds(3600).build())
+ .setBatchSource(
+ DataSource.newBuilder()
+ .setEventTimestampColumn("ts")
+ .setType(DataSource.SourceType.BATCH_FILE)
+ .setFileOptions(
+ FileOptions.newBuilder()
+ .setFileFormat(
+ FileFormat.newBuilder()
+ .setParquetFormat(ParquetFormat.newBuilder().build())
+ .build())
+ .setFileUrl("/dev/null")
+ .build())
+ .build())
.putAllLabels(labels)
.build();
}
diff --git a/core/src/test/java/feast/core/service/SpecServiceIT.java b/core/src/test/java/feast/core/service/SpecServiceIT.java
index e6dc068ef6..8851d875ae 100644
--- a/core/src/test/java/feast/core/service/SpecServiceIT.java
+++ b/core/src/test/java/feast/core/service/SpecServiceIT.java
@@ -659,6 +659,7 @@ public void shouldErrorOnMissingBatchSource() {
3600,
Map.of())
.toBuilder()
+ .clearBatchSource()
.build();
StatusRuntimeException exc =
diff --git a/infra/charts/feast/charts/feast-serving/templates/deployment.yaml b/infra/charts/feast/charts/feast-serving/templates/deployment.yaml
index 3df799df1d..1d6e3aadc4 100644
--- a/infra/charts/feast/charts/feast-serving/templates/deployment.yaml
+++ b/infra/charts/feast/charts/feast-serving/templates/deployment.yaml
@@ -117,7 +117,11 @@ spec:
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
exec:
- command: ["grpc-health-probe", "-addr=:{{ .Values.service.grpc.targetPort }}"]
+ command:
+ - "grpc-health-probe"
+ - "-addr=:{{ .Values.service.grpc.targetPort }}"
+ - "-connect-timeout={{ .Values.livenessProbe.timeoutSeconds }}s"
+ - "-rpc-timeout={{ .Values.livenessProbe.timeoutSeconds }}s"
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
@@ -128,7 +132,11 @@ spec:
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
exec:
- command: ["grpc-health-probe", "-addr=:{{ .Values.service.grpc.targetPort }}"]
+ command:
+ - "grpc-health-probe"
+ - "-addr=:{{ .Values.service.grpc.targetPort }}"
+ - "-connect-timeout={{ .Values.readinessProbe.timeoutSeconds }}s"
+ - "-rpc-timeout={{ .Values.readinessProbe.timeoutSeconds }}s"
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.readinessProbe.successThreshold }}
diff --git a/infra/docker/serving/Dockerfile b/infra/docker/serving/Dockerfile
index 72d6bc23c8..395b344c7c 100644
--- a/infra/docker/serving/Dockerfile
+++ b/infra/docker/serving/Dockerfile
@@ -42,12 +42,12 @@ RUN wget -q https://github.com/grpc-ecosystem/grpc-health-probe/releases/downloa
# Build stage 2: Production
# ============================================================
-FROM openjdk:11-jre-slim as production
+FROM amazoncorretto:11 as production
ARG VERSION=dev
COPY --from=builder /build/serving/target/feast-serving-$VERSION-exec.jar /opt/feast/feast-serving.jar
COPY --from=builder /usr/bin/grpc-health-probe /usr/bin/grpc-health-probe
CMD ["java",\
- "-Xms1024m",\
- "-Xmx1024m",\
+ "-Xms1g",\
+ "-Xmx4g",\
"-jar",\
"/opt/feast/feast-serving.jar"]
diff --git a/serving/pom.xml b/serving/pom.xml
index f70a118b21..b8f675dd30 100644
--- a/serving/pom.xml
+++ b/serving/pom.xml
@@ -298,13 +298,13 @@
org.testcontainers
testcontainers
- 1.14.3
+ 1.15.1
test
org.testcontainers
junit-jupiter
- 1.14.3
+ 1.15.1
test
diff --git a/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java b/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java
index 0de3fea82c..70dd6f7387 100644
--- a/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java
+++ b/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java
@@ -20,8 +20,6 @@
import com.google.protobuf.Duration;
import feast.common.models.FeatureV2;
-import feast.proto.core.FeatureProto;
-import feast.proto.core.FeatureTableProto.FeatureTableSpec;
import feast.proto.serving.ServingAPIProto.FeastServingType;
import feast.proto.serving.ServingAPIProto.FeatureReferenceV2;
import feast.proto.serving.ServingAPIProto.GetFeastServingInfoRequest;
@@ -29,6 +27,7 @@
import feast.proto.serving.ServingAPIProto.GetOnlineFeaturesRequestV2;
import feast.proto.serving.ServingAPIProto.GetOnlineFeaturesResponse;
import feast.proto.types.ValueProto;
+import feast.serving.exception.SpecRetrievalException;
import feast.serving.specs.CachedSpecService;
import feast.serving.util.Metrics;
import feast.storage.api.retriever.Feature;
@@ -37,7 +36,9 @@
import io.opentracing.Span;
import io.opentracing.Tracer;
import java.util.*;
+import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import org.slf4j.Logger;
public class OnlineServingServiceV2 implements ServingServiceV2 {
@@ -47,6 +48,27 @@ public class OnlineServingServiceV2 implements ServingServiceV2 {
private final Tracer tracer;
private final OnlineRetrieverV2 retriever;
+ private static final HashMap
+ TYPE_TO_VAL_CASE =
+ new HashMap<>() {
+ {
+ put(ValueProto.ValueType.Enum.BYTES, ValueProto.Value.ValCase.BYTES_VAL);
+ put(ValueProto.ValueType.Enum.STRING, ValueProto.Value.ValCase.STRING_VAL);
+ put(ValueProto.ValueType.Enum.INT32, ValueProto.Value.ValCase.INT32_VAL);
+ put(ValueProto.ValueType.Enum.INT64, ValueProto.Value.ValCase.INT64_VAL);
+ put(ValueProto.ValueType.Enum.DOUBLE, ValueProto.Value.ValCase.DOUBLE_VAL);
+ put(ValueProto.ValueType.Enum.FLOAT, ValueProto.Value.ValCase.FLOAT_VAL);
+ put(ValueProto.ValueType.Enum.BOOL, ValueProto.Value.ValCase.BOOL_VAL);
+ put(ValueProto.ValueType.Enum.BYTES_LIST, ValueProto.Value.ValCase.BYTES_LIST_VAL);
+ put(ValueProto.ValueType.Enum.STRING_LIST, ValueProto.Value.ValCase.STRING_LIST_VAL);
+ put(ValueProto.ValueType.Enum.INT32_LIST, ValueProto.Value.ValCase.INT32_LIST_VAL);
+ put(ValueProto.ValueType.Enum.INT64_LIST, ValueProto.Value.ValCase.INT64_LIST_VAL);
+ put(ValueProto.ValueType.Enum.DOUBLE_LIST, ValueProto.Value.ValCase.DOUBLE_LIST_VAL);
+ put(ValueProto.ValueType.Enum.FLOAT_LIST, ValueProto.Value.ValCase.FLOAT_LIST_VAL);
+ put(ValueProto.ValueType.Enum.BOOL_LIST, ValueProto.Value.ValCase.BOOL_LIST_VAL);
+ }
+ };
+
public OnlineServingServiceV2(
OnlineRetrieverV2 retriever, CachedSpecService specService, Tracer tracer) {
this.retriever = retriever;
@@ -74,30 +96,22 @@ public GetOnlineFeaturesResponse getOnlineFeatures(GetOnlineFeaturesRequestV2 re
}
List entityRows = request.getEntityRowsList();
- // Collect the feature/entity value for each entity row in entityValueMap
- Map> entityValuesMap =
- entityRows.stream().collect(Collectors.toMap(row -> row, row -> new HashMap<>()));
- // Collect the feature/entity status metadata for each entity row in entityValueMap
- Map>
- entityStatusesMap =
- entityRows.stream().collect(Collectors.toMap(row -> row, row -> new HashMap<>()));
-
- entityRows.forEach(
- entityRow -> {
- Map valueMap = entityRow.getFieldsMap();
- entityValuesMap.get(entityRow).putAll(valueMap);
- entityStatusesMap.get(entityRow).putAll(getMetadataMap(valueMap, false, false));
- });
+ List