-
Notifications
You must be signed in to change notification settings - Fork 24.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix _bulk response when it can't create an index #24048
Conversation
Before elastic#22488 when an index couldn't be created during a `_bulk` operation we'd do all the *other* actions and return the index creation error on each failing action. In elastic#22488 we accidentally cahnged it so that we now reject the entire bulk request if a single action cannot create an index that it must create to run. This gets reverts to the old behavior while still keeping the nicer error messages. Instead of failing the entire request we now only fail the portions of the request that can't work because the index doesn't exist. Closes elastic#24028
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nik9000, I did a first round. I get the change, it looks good. I offered a suggestion that might simplify things, I have a complaint about a name. I appreciate the REST test a lot, but I would like to ask if it would be possible to write a unit test. Maybe it would be possible override executeBulk and assert on the names of indices that can not be created that is passed in?
ClusterState state = clusterService.state(); | ||
for (String index : autoCreateIndices) { | ||
if (shouldAutoCreate(index, state)) { | ||
for (Iterator<String> itr = autoCreateIndices.iterator(); itr.hasNext();) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be simplified, no need to iterate and remove, and no need for the final map:
diff --git a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java
index 1b1f961a12..708f8eb4b0 100644
--- a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java
+++ b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java
@@ -64,6 +64,7 @@ import org.elasticsearch.transport.TransportService;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -142,34 +143,30 @@ public class TransportBulkAction extends HandledTransportAction<BulkRequest, Bul
if (needToCheck()) {
// Attempt to create all the indices that we're going to need during the bulk before we start.
// Step 1: collect all the indices in the request
- final Set<String> autoCreateIndices = bulkRequest.requests.stream()
+ final Set<String> indices = bulkRequest.requests.stream()
.map(DocWriteRequest::index)
.collect(Collectors.toSet());
/* Step 2: filter that to indices that don't exist and we can create. At the same time build a map of indices we can't create
* that we'll use when we try to run the requests. */
- Map<String, IndexNotFoundException> indicesThatCannotBeCreated = null;
+ final Map<String, IndexNotFoundException> indicesThatCannotBeCreated = new HashMap<>();
+ final Set<String> autoCreateIndices = new HashSet<>();
ClusterState state = clusterService.state();
- for (Iterator<String> itr = autoCreateIndices.iterator(); itr.hasNext();) {
- String index = itr.next();
+ for (final String index : indices) {
boolean shouldAutoCreate;
try {
shouldAutoCreate = shouldAutoCreate(index, state);
} catch (IndexNotFoundException e) {
shouldAutoCreate = false;
- if (indicesThatCannotBeCreated == null) {
- indicesThatCannotBeCreated = new HashMap<>();
- }
indicesThatCannotBeCreated.put(index, e);
}
- if (false == shouldAutoCreate) {
- itr.remove();
+ if (shouldAutoCreate) {
+ autoCreateIndices.add(index);
}
}
+
// Step 3: create all the indices that are missing, if there are any missing. start the bulk after all the creates come back.
- final Map<String, IndexNotFoundException> finalIndicesThatCannotBeCreated =
- indicesThatCannotBeCreated == null ? emptyMap() : indicesThatCannotBeCreated;
if (autoCreateIndices.isEmpty()) {
- executeBulk(task, bulkRequest, startTime, listener, responses, finalIndicesThatCannotBeCreated);
+ executeBulk(task, bulkRequest, startTime, listener, responses, indicesThatCannotBeCreated);
} else {
final AtomicInteger counter = new AtomicInteger(autoCreateIndices.size());
for (String index : autoCreateIndices) {
@@ -181,7 +178,7 @@ public class TransportBulkAction extends HandledTransportAction<BulkRequest, Bul
@Override
public void onResponse(CreateIndexResponse result) {
if (counter.decrementAndGet() == 0) {
- executeBulk(task, bulkRequest, startTime, listener, responses, finalIndicesThatCannotBeCreated);
+ executeBulk(task, bulkRequest, startTime, listener, responses, indicesThatCannotBeCreated);
}
}
@@ -200,7 +197,7 @@ public class TransportBulkAction extends HandledTransportAction<BulkRequest, Bul
executeBulk(task, bulkRequest, startTime, ActionListener.wrap(listener::onResponse, inner -> {
inner.addSuppressed(e);
listener.onFailure(inner);
- }), responses, finalIndicesThatCannotBeCreated);
+ }), responses, indicesThatCannotBeCreated);
}
}
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to add the extra HashMap allocation. I'm happy to do it your way if you think it isn't a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I think it will die young so it's probably not a big deal. I'm fine if you think it's important yet I think either way the rest of my suggestion (to avoid the iterate/remove) stand?
settings.gradle
Outdated
'qa:no-bootstrap-tests', | ||
'qa:rolling-upgrade', | ||
'qa:multi-cluster-search', | ||
'qa:smoke-test-autocreateindex-limited', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course I have a complaint about the naming. 😇
I think that we should stop calling these "smoke tests" as they are not smoke tests, and I would like to see some extra hyphens in autocreateindex
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
Almost certainly |
@jasontedor I'm fine with the young garbage argument. I pushed some commits which should address your comments. |
bulkRequest.add(new IndexRequest("can't")); | ||
bulkRequest.add(new DeleteRequest("do")); | ||
bulkRequest.add(new UpdateRequest("any", randomAlphaOfLength(5), randomAlphaOfLength(5))); | ||
indicesThatCannotBeCreatedTestCase(new HashSet<>(Arrays.asList("no", "can't", "do", "any")), bulkRequest, index -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double negative. 😄
settings.gradle
Outdated
@@ -57,11 +57,12 @@ List projects = [ | |||
'plugins:repository-s3', | |||
'plugins:jvm-example', | |||
'plugins:store-smb', | |||
'qa:autocreateindex', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still want hyphens: auto-create-index
. 😇
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I left two comments that you can address as you see fit.
Thanks @jasontedor! I'll backport now. |
Before #22488 when an index couldn't be created during a `_bulk` operation we'd do all the *other* actions and return the index creation error on each failing action. In #22488 we accidentally changed it so that we now reject the entire bulk request if a single action cannot create an index that it must create to run. This gets reverts to the old behavior while still keeping the nicer error messages. Instead of failing the entire request we now only fail the portions of the request that can't work because the index doesn't exist. Closes #24028
Before #22488 when an index couldn't be created during a `_bulk` operation we'd do all the *other* actions and return the index creation error on each failing action. In #22488 we accidentally changed it so that we now reject the entire bulk request if a single action cannot create an index that it must create to run. This gets reverts to the old behavior while still keeping the nicer error messages. Instead of failing the entire request we now only fail the portions of the request that can't work because the index doesn't exist. Closes #24028
All backported except 5.x. Still waiting on that build. |
Before #22488 when an index couldn't be created during a `_bulk` operation we'd do all the *other* actions and return the index creation error on each failing action. In #22488 we accidentally changed it so that we now reject the entire bulk request if a single action cannot create an index that it must create to run. This gets reverts to the old behavior while still keeping the nicer error messages. Instead of failing the entire request we now only fail the portions of the request that can't work because the index doesn't exist. Closes #24028
Backported to 5.x as well. |
Before elastic#22488 when an index couldn't be created during a `_bulk` operation we'd do all the *other* actions and return the index creation error on each failing action. In elastic#22488 we accidentally changed it so that we now reject the entire bulk request if a single action cannot create an index that it must create to run. This gets reverts to the old behavior while still keeping the nicer error messages. Instead of failing the entire request we now only fail the portions of the request that can't work because the index doesn't exist. Closes elastic#24028
Before #22488 when an index couldn't be created during a
_bulk
operation we'd do all the other actions and return the index
creation error on each failing action. In #22488 we accidentally
changed it so that we now reject the entire bulk request if a single
action cannot create an index that it must create to run. This
reverts to the old behavior while still keeping the nicer
error messages. Instead of failing the entire request we now only
fail the portions of the request that can't work because the index
doesn't exist.
Closes #24028