1
0
Эх сурвалжийг харах

Fix 'autoGeneratedTimestamp should not be set externally' error when retrying IndexRequest (#86184)

We use BulkProcessor to index various features internally (ilm history, watcher history and more).
When an index request is retried then resending that same request can cause the following error:

```
java.lang.IllegalArgumentException: autoGeneratedTimestamp should not be set externally
	at org.elasticsearch.action.bulk.TransportBulkAction.doInternalExecute(TransportBulkAction.java:223) ~[elasticsearch-7.16.1.jar:7.16.1]
	at org.elasticsearch.action.bulk.TransportBulkAction$1.doRun(TransportBulkAction.java:192) ~[elasticsearch-7.16.1.jar:7.16.1]
	at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26) [elasticsearch-7.16.1.jar:7.16.1]
	at org.elasticsearch.action.bulk.TransportBulkAction.doExecute(TransportBulkAction.java:200) [elasticsearch-7.16.1.jar:7.16.1]
	at org.elasticsearch.action.bulk.TransportBulkAction.doExecute(TransportBulkAction.java:91) [elasticsearch-7.16.1.jar:7.16.1]
```

This happens when index requests fail because of a retryable error (e.g. EsRejectedExecutionException).
Prior to this change, the BulkProcessor (via Retry) then reuses the same instance.
With this change, the autoGeneratedTimestamp field is unset via a reset method added to IndexRequest class,
which should avoid the IAE.

Closes #83927
Martijn van Groningen 3 жил өмнө
parent
commit
08c3bda45a

+ 6 - 0
docs/changelog/86184.yaml

@@ -0,0 +1,6 @@
+pr: 86184
+summary: Fix 'autoGeneratedTimestamp should not be set externally' error when retrying IndexRequest
+area: Features
+type: bug
+issues:
+  - 83927

+ 6 - 6
server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java

@@ -113,12 +113,12 @@ public class BulkRequest extends ActionRequest
      * @return the current bulk request
      */
     public BulkRequest add(DocWriteRequest<?> request) {
-        if (request instanceof IndexRequest) {
-            add((IndexRequest) request);
-        } else if (request instanceof DeleteRequest) {
-            add((DeleteRequest) request);
-        } else if (request instanceof UpdateRequest) {
-            add((UpdateRequest) request);
+        if (request instanceof IndexRequest indexRequest) {
+            add(indexRequest);
+        } else if (request instanceof DeleteRequest deleteRequest) {
+            add(deleteRequest);
+        } else if (request instanceof UpdateRequest updateRequest) {
+            add(updateRequest);
         } else {
             throw new IllegalArgumentException("No support for request [" + request + "]");
         }

+ 7 - 1
server/src/main/java/org/elasticsearch/action/bulk/Retry.java

@@ -11,6 +11,8 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.elasticsearch.ExceptionsHelper;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.DocWriteRequest;
+import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.core.TimeValue;
 import org.elasticsearch.rest.RestStatus;
@@ -141,7 +143,11 @@ public class Retry {
             int index = 0;
             for (BulkItemResponse bulkItemResponse : bulkItemResponses.getItems()) {
                 if (bulkItemResponse.isFailed()) {
-                    requestToReissue.add(currentBulkRequest.requests().get(index));
+                    DocWriteRequest<?> originalBulkItemRequest = currentBulkRequest.requests().get(index);
+                    if (originalBulkItemRequest instanceof IndexRequest item) {
+                        item.reset();
+                    }
+                    requestToReissue.add(originalBulkItemRequest);
                 }
                 index++;
             }

+ 8 - 0
server/src/main/java/org/elasticsearch/action/index/IndexRequest.java

@@ -621,6 +621,14 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
         id(uid);
     }
 
+    /**
+     * Resets this <code>IndexRequest</code> class, so that in case this instance can be used by the bulk/index action
+     * if it was already used before. For example if retrying a retryable failure.
+     */
+    public void reset() {
+        autoGeneratedTimestamp = UNSET_AUTO_GENERATED_TIMESTAMP;
+    }
+
     public void checkAutoIdWithOpTypeCreateSupportedByVersion(Version version) {
         if (id == null && opType == OpType.CREATE && version.before(Version.V_7_5_0)) {
             throw new IllegalArgumentException(