Skip to content

Commit 3826bd9

Browse files
authored
Feature Table is not being update when only max_age was changed (#1208)
* fix max age Signed-off-by: Oleksii Moskalenko <moskalenko.alexey@gmail.com> * format Signed-off-by: Oleksii Moskalenko <moskalenko.alexey@gmail.com>
1 parent 88046a0 commit 3826bd9

2 files changed

Lines changed: 53 additions & 87 deletions

File tree

core/src/main/java/feast/core/model/FeatureTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ && getProject().equals(other.getProject())
411411
&& getLabelsJSON().equals(other.getLabelsJSON())
412412
&& getFeatures().equals(other.getFeatures())
413413
&& getEntities().equals(other.getEntities())
414-
&& getMaxAgeSecs() == getMaxAgeSecs()
414+
&& getMaxAgeSecs() == other.getMaxAgeSecs()
415415
&& Optional.ofNullable(getBatchSource()).equals(Optional.ofNullable(other.getBatchSource()))
416416
&& Optional.ofNullable(getStreamSource())
417417
.equals(Optional.ofNullable(other.getStreamSource()));

core/src/test/java/feast/core/service/SpecServiceIT.java

Lines changed: 52 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static org.junit.jupiter.api.Assertions.assertThrows;
2828

2929
import avro.shaded.com.google.common.collect.ImmutableMap;
30+
import com.google.protobuf.Duration;
3031
import feast.common.it.BaseIT;
3132
import feast.common.it.DataGenerator;
3233
import feast.common.it.SimpleCoreClient;
@@ -38,6 +39,7 @@
3839
import io.grpc.ManagedChannelBuilder;
3940
import io.grpc.StatusRuntimeException;
4041
import java.util.*;
42+
import java.util.stream.IntStream;
4143
import org.apache.commons.lang3.tuple.Triple;
4244
import org.junit.jupiter.api.BeforeAll;
4345
import org.junit.jupiter.api.BeforeEach;
@@ -61,6 +63,9 @@ public static void globalSetUp(@Value("${grpc.server.port}") int port) {
6163
apiClient = new SimpleCoreClient(stub);
6264
}
6365

66+
private FeatureTableProto.FeatureTableSpec example1;
67+
private FeatureTableProto.FeatureTableSpec example2;
68+
6469
@BeforeEach
6570
public void initState() {
6671

@@ -78,8 +83,8 @@ public void initState() {
7883
ImmutableMap.of("label_key2", "label_value2"));
7984
apiClient.simpleApplyEntity("default", entitySpec1);
8085
apiClient.simpleApplyEntity("default", entitySpec2);
81-
apiClient.applyFeatureTable(
82-
"default",
86+
87+
example1 =
8388
DataGenerator.createFeatureTableSpec(
8489
"featuretable1",
8590
Arrays.asList("entity1", "entity2"),
@@ -94,9 +99,9 @@ public void initState() {
9499
.toBuilder()
95100
.setBatchSource(
96101
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
97-
.build());
98-
apiClient.applyFeatureTable(
99-
"default",
102+
.build();
103+
104+
example2 =
100105
DataGenerator.createFeatureTableSpec(
101106
"featuretable2",
102107
Arrays.asList("entity1", "entity2"),
@@ -111,7 +116,10 @@ public void initState() {
111116
.toBuilder()
112117
.setBatchSource(
113118
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
114-
.build());
119+
.build();
120+
121+
apiClient.applyFeatureTable("default", example1);
122+
apiClient.applyFeatureTable("default", example2);
115123
apiClient.simpleApplyEntity(
116124
"project1",
117125
DataGenerator.createEntitySpecV2(
@@ -422,26 +430,10 @@ public void shouldThrowExceptionGivenNoSuchFeatureTable() {
422430

423431
@Test
424432
public void shouldReturnFeatureTableIfExists() {
425-
FeatureTableSpec featureTableSpec =
426-
DataGenerator.createFeatureTableSpec(
427-
"featuretable1",
428-
Arrays.asList("entity1", "entity2"),
429-
new HashMap<>() {
430-
{
431-
put("feature1", ValueProto.ValueType.Enum.STRING);
432-
put("feature2", ValueProto.ValueType.Enum.FLOAT);
433-
}
434-
},
435-
7200,
436-
ImmutableMap.of("feat_key2", "feat_value2"))
437-
.toBuilder()
438-
.setBatchSource(
439-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
440-
.build();
441433
FeatureTableProto.FeatureTable featureTable =
442434
apiClient.simpleGetFeatureTable("default", "featuretable1");
443435

444-
assertTrue(TestUtil.compareFeatureTableSpec(featureTable.getSpec(), featureTableSpec));
436+
assertTrue(TestUtil.compareFeatureTableSpec(featureTable.getSpec(), example1));
445437
}
446438
}
447439

@@ -544,17 +536,9 @@ public void shouldFilterFeaturesByEntitiesAndLabels() {
544536
@Nested
545537
public class ApplyFeatureTable {
546538
private FeatureTableSpec getTestSpec() {
547-
return DataGenerator.createFeatureTableSpec(
548-
"ft",
549-
List.of("entity1", "entity2"),
550-
Map.of(
551-
"feature1", ValueProto.ValueType.Enum.INT64,
552-
"feature2", ValueProto.ValueType.Enum.FLOAT),
553-
3600,
554-
Map.of())
539+
return example1
555540
.toBuilder()
556-
.setBatchSource(
557-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
541+
.setName("apply_test")
558542
.setStreamSource(
559543
DataGenerator.createKafkaDataSourceSpec(
560544
"localhost:9092", "topic", "class.path", "ts_col"))
@@ -574,22 +558,17 @@ public void shouldUpdateExistingTableWithValidSpec() {
574558
FeatureTableProto.FeatureTable table = apiClient.applyFeatureTable("default", getTestSpec());
575559

576560
FeatureTableSpec updatedSpec =
577-
DataGenerator.createFeatureTableSpec(
578-
"ft",
579-
List.of("entity1", "entity2"),
580-
Map.of(
581-
"feature2", ValueProto.ValueType.Enum.FLOAT,
582-
"feature3", ValueProto.ValueType.Enum.INT64,
583-
"feature4", ValueProto.ValueType.Enum.INT64),
584-
2100,
585-
Map.of("test", "labels"))
561+
getTestSpec()
586562
.toBuilder()
563+
.clearFeatures()
564+
.addFeatures(
565+
DataGenerator.createFeatureSpecV2(
566+
"feature5", ValueProto.ValueType.Enum.FLOAT, ImmutableMap.of()))
587567
.setStreamSource(
588-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
589-
.setBatchSource(
590568
DataGenerator.createKafkaDataSourceSpec(
591-
"localhost:9092", "topic", "class.path", "ts_col"))
569+
"localhost:9092", "new_topic", "new.class", "ts_col"))
592570
.build();
571+
593572
FeatureTableProto.FeatureTable updatedTable =
594573
apiClient.applyFeatureTable("default", updatedSpec);
595574

@@ -599,22 +578,21 @@ public void shouldUpdateExistingTableWithValidSpec() {
599578

600579
@Test
601580
public void shouldUpdateFeatureTableOnEntityChange() {
602-
List<String> entities = Arrays.asList("entity1", "entity2");
603581
FeatureTableProto.FeatureTableSpec updatedSpec =
604-
DataGenerator.createFeatureTableSpec(
605-
"featuretable1",
606-
Arrays.asList("entity1"),
607-
new HashMap<>() {
608-
{
609-
put("feature1", ValueProto.ValueType.Enum.STRING);
610-
put("feature2", ValueProto.ValueType.Enum.FLOAT);
611-
}
612-
},
613-
7200,
614-
ImmutableMap.of("feat_key2", "feat_value2"))
582+
getTestSpec().toBuilder().clearEntities().addEntities("entity1").build();
583+
584+
FeatureTableProto.FeatureTable updatedTable =
585+
apiClient.applyFeatureTable("default", updatedSpec);
586+
587+
assertTrue(TestUtil.compareFeatureTableSpec(updatedTable.getSpec(), updatedSpec));
588+
}
589+
590+
@Test
591+
public void shouldUpdateFeatureTableOnMaxAgeChange() {
592+
FeatureTableProto.FeatureTableSpec updatedSpec =
593+
getTestSpec()
615594
.toBuilder()
616-
.setBatchSource(
617-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
595+
.setMaxAge(Duration.newBuilder().setSeconds(600).build())
618596
.build();
619597

620598
FeatureTableProto.FeatureTable updatedTable =
@@ -625,21 +603,19 @@ public void shouldUpdateFeatureTableOnEntityChange() {
625603

626604
@Test
627605
public void shouldUpdateFeatureTableOnFeatureTypeChange() {
606+
int featureIdx =
607+
IntStream.range(0, getTestSpec().getFeaturesCount())
608+
.filter(i -> getTestSpec().getFeatures(i).getName().equals("feature2"))
609+
.findFirst()
610+
.orElse(-1);
611+
628612
FeatureTableProto.FeatureTableSpec updatedSpec =
629-
DataGenerator.createFeatureTableSpec(
630-
"featuretable1",
631-
Arrays.asList("entity1", "entity2"),
632-
new HashMap<>() {
633-
{
634-
put("feature1", ValueProto.ValueType.Enum.STRING);
635-
put("feature2", ValueProto.ValueType.Enum.STRING_LIST);
636-
}
637-
},
638-
7200,
639-
ImmutableMap.of("feat_key2", "feat_value2"))
613+
getTestSpec()
640614
.toBuilder()
641-
.setBatchSource(
642-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
615+
.setFeatures(
616+
featureIdx,
617+
DataGenerator.createFeatureSpecV2(
618+
"feature2", ValueProto.ValueType.Enum.STRING_LIST, ImmutableMap.of()))
643619
.build();
644620

645621
FeatureTableProto.FeatureTable updatedTable =
@@ -651,21 +627,11 @@ public void shouldUpdateFeatureTableOnFeatureTypeChange() {
651627
@Test
652628
public void shouldUpdateFeatureTableOnFeatureAddition() {
653629
FeatureTableProto.FeatureTableSpec updatedSpec =
654-
DataGenerator.createFeatureTableSpec(
655-
"featuretable1",
656-
Arrays.asList("entity1", "entity2"),
657-
new HashMap<>() {
658-
{
659-
put("feature1", ValueProto.ValueType.Enum.STRING);
660-
put("feature2", ValueProto.ValueType.Enum.FLOAT);
661-
put("feature3", ValueProto.ValueType.Enum.FLOAT);
662-
}
663-
},
664-
7200,
665-
ImmutableMap.of("feat_key2", "feat_value2"))
630+
getTestSpec()
666631
.toBuilder()
667-
.setBatchSource(
668-
DataGenerator.createFileDataSourceSpec("file:///path/to/file", "ts_col", ""))
632+
.addFeatures(
633+
DataGenerator.createFeatureSpecV2(
634+
"feature6", ValueProto.ValueType.Enum.FLOAT, ImmutableMap.of()))
669635
.build();
670636

671637
FeatureTableProto.FeatureTable updatedTable =

0 commit comments

Comments
 (0)