Skip to content

Commit fcc7c37

Browse files
authored
Refactor WriteableIngestDocument (#99324) (#100223)
1 parent ef30674 commit fcc7c37

File tree

16 files changed

+156
-223
lines changed

16 files changed

+156
-223
lines changed

modules/ingest-common/src/test/java/org/elasticsearch/ingest/common/ForEachProcessorTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ public void testAppendingToTheSameField() {
344344
execProcessor(processor, ingestDocument, (result, e) -> {});
345345
assertThat(testProcessor.getInvokedCounter(), equalTo(2));
346346
ingestDocument.removeField("_ingest._value");
347-
assertThat(ingestDocument, equalTo(originalIngestDocument));
347+
assertIngestDocument(ingestDocument, originalIngestDocument);
348348
}
349349

350350
public void testRemovingFromTheSameField() {
@@ -355,7 +355,7 @@ public void testRemovingFromTheSameField() {
355355
execProcessor(processor, ingestDocument, (result, e) -> {});
356356
assertThat(testProcessor.getInvokedCounter(), equalTo(2));
357357
ingestDocument.removeField("_ingest._value");
358-
assertThat(ingestDocument, equalTo(originalIngestDocument));
358+
assertIngestDocument(ingestDocument, originalIngestDocument);
359359
}
360360

361361
public void testMapIteration() {

modules/ingest-common/src/test/java/org/elasticsearch/ingest/common/GrokProcessorTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public void testMatchWithoutCaptures() throws Exception {
114114
MatcherWatchdog.noop()
115115
);
116116
processor.execute(doc);
117-
assertThat(doc, equalTo(originalDoc));
117+
assertIngestDocument(doc, originalDoc);
118118
}
119119

120120
public void testNullField() {

server/src/main/java/org/elasticsearch/action/ingest/SimulateDocumentBaseResult.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,17 @@ public final class SimulateDocumentBaseResult implements SimulateDocumentResult
5050
}
5151

5252
public SimulateDocumentBaseResult(IngestDocument ingestDocument) {
53+
Exception failure = null;
54+
WriteableIngestDocument wid = null;
5355
if (ingestDocument != null) {
54-
this.ingestDocument = new WriteableIngestDocument(ingestDocument);
55-
} else {
56-
this.ingestDocument = null;
56+
try {
57+
wid = new WriteableIngestDocument(ingestDocument);
58+
} catch (Exception ex) {
59+
failure = ex;
60+
}
5761
}
58-
this.failure = null;
62+
this.ingestDocument = wid;
63+
this.failure = failure;
5964
}
6065

6166
public SimulateDocumentBaseResult(Exception failure) {

server/src/main/java/org/elasticsearch/action/ingest/SimulateProcessorResult.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,19 @@ public SimulateProcessorResult(
126126
) {
127127
this.processorTag = processorTag;
128128
this.description = description;
129-
this.ingestDocument = (ingestDocument == null) ? null : new WriteableIngestDocument(ingestDocument);
129+
WriteableIngestDocument wid = null;
130+
if (ingestDocument != null) {
131+
try {
132+
wid = new WriteableIngestDocument(ingestDocument);
133+
} catch (Exception ex) {
134+
// if there was a failure already, then track it as a suppressed exception
135+
if (failure != null) {
136+
ex.addSuppressed(failure);
137+
}
138+
failure = ex;
139+
}
140+
}
141+
this.ingestDocument = wid;
130142
this.failure = failure;
131143
this.conditionalWithResult = conditionalWithResult;
132144
this.type = type;

server/src/main/java/org/elasticsearch/action/ingest/WriteableIngestDocument.java

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.io.IOException;
2626
import java.time.ZonedDateTime;
2727
import java.util.Map;
28-
import java.util.Objects;
2928

3029
import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
3130
import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
@@ -57,7 +56,7 @@ final class WriteableIngestDocument implements Writeable, ToXContentFragment {
5756
sourceAndMetadata.put(Metadata.VERSION_TYPE.getFieldName(), a[4]);
5857
}
5958
Map<String, Object> ingestMetadata = (Map<String, Object>) a[6];
60-
return new WriteableIngestDocument(new IngestDocument(sourceAndMetadata, ingestMetadata));
59+
return new WriteableIngestDocument(sourceAndMetadata, ingestMetadata);
6160
}
6261
);
6362
static {
@@ -83,17 +82,30 @@ final class WriteableIngestDocument implements Writeable, ToXContentFragment {
8382
PARSER.declareObject(constructorArg(), INGEST_DOC_PARSER, new ParseField(DOC_FIELD));
8483
}
8584

85+
/**
86+
* Builds a writeable ingest document that wraps a copy of the passed-in, non-null ingest document.
87+
*
88+
* @throws IllegalArgumentException if the passed-in ingest document references itself
89+
*/
8690
WriteableIngestDocument(IngestDocument ingestDocument) {
8791
assert ingestDocument != null;
88-
this.ingestDocument = ingestDocument;
92+
this.ingestDocument = new IngestDocument(ingestDocument); // internal defensive copy
8993
}
9094

91-
WriteableIngestDocument(StreamInput in) throws IOException {
92-
Map<String, Object> sourceAndMetadata = in.readMap();
93-
Map<String, Object> ingestMetadata = in.readMap();
95+
/**
96+
* Builds a writeable ingest document by constructing the wrapped ingest document from the passed-in maps.
97+
* <p>
98+
* This is intended for cases like deserialization, where we know the passed-in maps aren't self-referencing,
99+
* and where a defensive copy is unnecessary.
100+
*/
101+
private WriteableIngestDocument(Map<String, Object> sourceAndMetadata, Map<String, Object> ingestMetadata) {
94102
this.ingestDocument = new IngestDocument(sourceAndMetadata, ingestMetadata);
95103
}
96104

105+
WriteableIngestDocument(StreamInput in) throws IOException {
106+
this(in.readMap(), in.readMap());
107+
}
108+
97109
@Override
98110
public void writeTo(StreamOutput out) throws IOException {
99111
out.writeGenericMap(ingestDocument.getSourceAndMetadata());
@@ -127,23 +139,6 @@ public static WriteableIngestDocument fromXContent(XContentParser parser) {
127139
return PARSER.apply(parser, null);
128140
}
129141

130-
@Override
131-
public boolean equals(Object o) {
132-
if (this == o) {
133-
return true;
134-
}
135-
if (o == null || getClass() != o.getClass()) {
136-
return false;
137-
}
138-
WriteableIngestDocument that = (WriteableIngestDocument) o;
139-
return Objects.equals(ingestDocument, that.ingestDocument);
140-
}
141-
142-
@Override
143-
public int hashCode() {
144-
return Objects.hash(ingestDocument);
145-
}
146-
147142
@Override
148143
public String toString() {
149144
return ingestDocument.toString();

server/src/main/java/org/elasticsearch/ingest/IngestDocument.java

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.elasticsearch.ingest;
1010

1111
import org.elasticsearch.common.Strings;
12+
import org.elasticsearch.common.util.CollectionUtils;
1213
import org.elasticsearch.common.util.Maps;
1314
import org.elasticsearch.common.util.set.Sets;
1415
import org.elasticsearch.index.VersionType;
@@ -94,14 +95,26 @@ public IngestDocument(String index, String id, long version, String routing, Ver
9495

9596
/**
9697
* Copy constructor that creates a new {@link IngestDocument} which has exactly the same properties as the one provided.
98+
*
99+
* @throws IllegalArgumentException if the passed-in ingest document references itself
97100
*/
98101
public IngestDocument(IngestDocument other) {
99102
this(
100-
new IngestCtxMap(deepCopyMap(other.ctxMap.getSource()), other.ctxMap.getMetadata().clone()),
103+
new IngestCtxMap(deepCopyMap(ensureNoSelfReferences(other.ctxMap.getSource())), other.ctxMap.getMetadata().clone()),
101104
deepCopyMap(other.ingestMetadata)
102105
);
103106
}
104107

108+
/**
109+
* Internal helper utility method to get around the issue that a {@code this(...) } constructor call must be the first statement
110+
* in a constructor. This is only for use in the {@link IngestDocument#IngestDocument(IngestDocument)} copy constructor, it's not a
111+
* general purpose method.
112+
*/
113+
private static Map<String, Object> ensureNoSelfReferences(Map<String, Object> source) {
114+
CollectionUtils.ensureNoSelfReferences(source, null);
115+
return source;
116+
}
117+
105118
/**
106119
* Constructor to create an IngestDocument from its constituent maps. The maps are shallow copied.
107120
*/
@@ -898,24 +911,6 @@ public void doNoSelfReferencesCheck(boolean doNoSelfReferencesCheck) {
898911
this.doNoSelfReferencesCheck = doNoSelfReferencesCheck;
899912
}
900913

901-
@Override
902-
public boolean equals(Object obj) {
903-
if (obj == this) {
904-
return true;
905-
}
906-
if (obj == null || getClass() != obj.getClass()) {
907-
return false;
908-
}
909-
910-
IngestDocument other = (IngestDocument) obj;
911-
return Objects.equals(ctxMap, other.ctxMap) && Objects.equals(ingestMetadata, other.ingestMetadata);
912-
}
913-
914-
@Override
915-
public int hashCode() {
916-
return Objects.hash(ctxMap, ingestMetadata);
917-
}
918-
919914
@Override
920915
public String toString() {
921916
return "IngestDocument{" + " sourceAndMetadata=" + ctxMap + ", ingestMetadata=" + ingestMetadata + '}';

server/src/main/java/org/elasticsearch/ingest/TrackingResultProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void execute(IngestDocument ingestDocument, BiConsumer<IngestDocument, Ex
9898
pipelineProcessor.getType(),
9999
pipelineProcessor.getTag(),
100100
pipelineProcessor.getDescription(),
101-
new IngestDocument(ingestDocument),
101+
ingestDocument,
102102
e,
103103
conditionalWithResult
104104
)
@@ -148,7 +148,7 @@ public void execute(IngestDocument ingestDocument, BiConsumer<IngestDocument, Ex
148148
actualProcessor.getType(),
149149
actualProcessor.getTag(),
150150
actualProcessor.getDescription(),
151-
new IngestDocument(ingestDocument),
151+
ingestDocument,
152152
e,
153153
conditionalWithResult
154154
)
@@ -172,7 +172,7 @@ public void execute(IngestDocument ingestDocument, BiConsumer<IngestDocument, Ex
172172
actualProcessor.getType(),
173173
actualProcessor.getTag(),
174174
actualProcessor.getDescription(),
175-
new IngestDocument(ingestDocument),
175+
ingestDocument,
176176
conditionalWithResult
177177
)
178178
);

server/src/test/java/org/elasticsearch/action/ingest/SimulateDocumentBaseResultTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ protected Predicate<String> getRandomFieldsExcludeFilter() {
8888
}
8989

9090
public static void assertEqualDocs(SimulateDocumentBaseResult response, SimulateDocumentBaseResult parsedResponse) {
91-
assertEquals(response.getIngestDocument(), parsedResponse.getIngestDocument());
91+
assertIngestDocument(response.getIngestDocument(), parsedResponse.getIngestDocument());
9292
if (response.getFailure() != null) {
9393
assertNotNull(parsedResponse.getFailure());
9494
assertThat(parsedResponse.getFailure().getMessage(), containsString(response.getFailure().getMessage()));

server/src/test/java/org/elasticsearch/action/ingest/SimulateExecutionServiceTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public void testExecuteItem() throws Exception {
108108
assertThat(processor.getInvokedCounter(), equalTo(2));
109109
assertThat(actualItemResponse, instanceOf(SimulateDocumentBaseResult.class));
110110
SimulateDocumentBaseResult simulateDocumentBaseResult = (SimulateDocumentBaseResult) actualItemResponse;
111-
assertThat(simulateDocumentBaseResult.getIngestDocument(), equalTo(ingestDocument));
111+
assertIngestDocument(simulateDocumentBaseResult.getIngestDocument(), ingestDocument);
112112
assertThat(simulateDocumentBaseResult.getFailure(), nullValue());
113113
}
114114

server/src/test/java/org/elasticsearch/action/ingest/SimulateProcessorResultTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ protected Predicate<String> getRandomFieldsExcludeFilter() {
127127

128128
static void assertEqualProcessorResults(SimulateProcessorResult response, SimulateProcessorResult parsedResponse) {
129129
assertEquals(response.getProcessorTag(), parsedResponse.getProcessorTag());
130-
assertEquals(response.getIngestDocument(), parsedResponse.getIngestDocument());
130+
assertIngestDocument(response.getIngestDocument(), parsedResponse.getIngestDocument());
131131
if (response.getFailure() != null) {
132132
assertNotNull(parsedResponse.getFailure());
133133
assertThat(parsedResponse.getFailure().getMessage(), containsString(response.getFailure().getMessage()));

0 commit comments

Comments
 (0)