Skip to content

Commit 8331482

Browse files
author
Oleksii Moskalenko
authored
Don't send unrecognized featureSets to deadletter in IngestionJob (#845)
* do not send unrecognized featureSets to deadletter * pr comments
1 parent d6c2a65 commit 8331482

2 files changed

Lines changed: 49 additions & 31 deletions

File tree

ingestion/src/main/java/feast/ingestion/transform/fn/ValidateFeatureRowDoFn.java

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
import org.apache.beam.sdk.transforms.DoFn;
3232
import org.apache.beam.sdk.values.PCollectionView;
3333
import org.apache.beam.sdk.values.TupleTag;
34+
import org.slf4j.Logger;
35+
import org.slf4j.LoggerFactory;
3436

3537
@AutoValue
3638
public abstract class ValidateFeatureRowDoFn extends DoFn<FeatureRow, FeatureRow> {
39+
private static final Logger log = LoggerFactory.getLogger(ValidateFeatureRowDoFn.class);
3740

3841
public abstract PCollectionView<Map<String, Iterable<FeatureSetProto.FeatureSetSpec>>>
3942
getFeatureSets();
@@ -65,40 +68,43 @@ public void processElement(ProcessContext context) {
6568
FeatureRow featureRow = context.element();
6669
Iterable<FeatureSetProto.FeatureSetSpec> featureSetSpecs =
6770
context.sideInput(getFeatureSets()).get(featureRow.getFeatureSet());
71+
if (featureSetSpecs == null) {
72+
log.warn(
73+
String.format(
74+
"FeatureRow contains invalid featureSetReference %s."
75+
+ " Please check that the feature rows are being published"
76+
+ " to the correct topic on the feature stream.",
77+
featureRow.getFeatureSet()));
78+
return;
79+
}
6880

6981
List<FieldProto.Field> fields = new ArrayList<>();
70-
if (featureSetSpecs != null) {
71-
FeatureSetProto.FeatureSetSpec latestSpec = Iterators.getLast(featureSetSpecs.iterator());
72-
FeatureSet featureSet = new FeatureSet(latestSpec);
73-
74-
for (FieldProto.Field field : featureRow.getFieldsList()) {
75-
Field fieldSpec = featureSet.getField(field.getName());
76-
if (fieldSpec == null) {
77-
// skip
78-
continue;
79-
}
80-
// If value is set in the FeatureRow, make sure the value type matches
81-
// that defined in FeatureSetSpec
82-
if (!field.getValue().getValCase().equals(ValCase.VAL_NOT_SET)) {
83-
int expectedTypeFieldNumber = fieldSpec.getType().getNumber();
84-
int actualTypeFieldNumber = field.getValue().getValCase().getNumber();
85-
if (expectedTypeFieldNumber != actualTypeFieldNumber) {
86-
error =
87-
String.format(
88-
"FeatureRow contains field '%s' with invalid type '%s'. Feast expects the field type to match that in FeatureSet '%s'. Please check the FeatureRow data.",
89-
field.getName(), field.getValue().getValCase(), fieldSpec.getType());
90-
break;
91-
}
92-
}
93-
if (!fields.contains(field)) {
94-
fields.add(field);
82+
83+
FeatureSetProto.FeatureSetSpec latestSpec = Iterators.getLast(featureSetSpecs.iterator());
84+
FeatureSet featureSet = new FeatureSet(latestSpec);
85+
86+
for (FieldProto.Field field : featureRow.getFieldsList()) {
87+
Field fieldSpec = featureSet.getField(field.getName());
88+
if (fieldSpec == null) {
89+
// skip
90+
continue;
91+
}
92+
// If value is set in the FeatureRow, make sure the value type matches
93+
// that defined in FeatureSetSpec
94+
if (!field.getValue().getValCase().equals(ValCase.VAL_NOT_SET)) {
95+
int expectedTypeFieldNumber = fieldSpec.getType().getNumber();
96+
int actualTypeFieldNumber = field.getValue().getValCase().getNumber();
97+
if (expectedTypeFieldNumber != actualTypeFieldNumber) {
98+
error =
99+
String.format(
100+
"FeatureRow contains field '%s' with invalid type '%s'. Feast expects the field type to match that in FeatureSet '%s'. Please check the FeatureRow data.",
101+
field.getName(), field.getValue().getValCase(), fieldSpec.getType());
102+
break;
95103
}
96104
}
97-
} else {
98-
error =
99-
String.format(
100-
"FeatureRow contains invalid feature set id %s. Please check that the feature rows are being published to the correct topic on the feature stream.",
101-
featureRow.getFeatureSet());
105+
if (!fields.contains(field)) {
106+
fields.add(field);
107+
}
102108
}
103109

104110
if (error != null) {

ingestion/src/test/java/feast/ingestion/transform/ProcessAndValidateFeatureRowsTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package feast.ingestion.transform;
1818

19+
import static feast.common.models.FeatureSet.getFeatureSetStringRef;
20+
1921
import feast.proto.core.FeatureSetProto.EntitySpec;
2022
import feast.proto.core.FeatureSetProto.FeatureSetSpec;
2123
import feast.proto.core.FeatureSetProto.FeatureSpec;
@@ -104,7 +106,17 @@ public void shouldWriteSuccessAndFailureTagsCorrectly() {
104106
expected.add(randomRow);
105107
}
106108

107-
input.add(FeatureRow.newBuilder().setFeatureSet("invalid").build());
109+
FeatureRow invalidRow =
110+
FeatureRow.newBuilder()
111+
.setFeatureSet(getFeatureSetStringRef(fs1))
112+
.addFields(
113+
Field.newBuilder()
114+
.setName("feature_1")
115+
.setValue(Value.newBuilder().setBoolVal(false).build())
116+
.build())
117+
.build();
118+
119+
input.add(invalidRow);
108120

109121
PCollectionView<Map<String, Iterable<FeatureSetSpec>>> specsView =
110122
p.apply("StaticSpecs", Create.of(featureSetSpecs)).apply(View.asMultimap());

0 commit comments

Comments
 (0)