[7.x][ML] Fix DFA explain API timeout when source index is missing (#50176) (#50180)

This commit fixes a bug that caused the data frame analytics
_explain API to time out in a multi-node setup when the source
index was missing. When we try to create the extracted fields detector,
we check the index settings. If the index is missing that responds
with a failure that could be wrapped as a remote exception.
While we unwrapped correctly to check if the cause was an
`IndexNotFoundException`, we then proceeded to cast the original
exception instead of the cause.

Backport of #50176
This commit is contained in:
Dimitris Athanasiou 2019-12-13 17:00:55 +02:00 committed by GitHub
parent cd04021961
commit fe3c9e71d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 2 deletions

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.xpack.ml.integration; package org.elasticsearch.xpack.ml.integration;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
@ -14,14 +15,26 @@ import org.elasticsearch.xpack.core.ml.action.ExplainDataFrameAnalyticsAction;
import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsConfig; import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsConfig;
import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsSource; import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsSource;
import org.elasticsearch.xpack.core.ml.dataframe.analyses.Classification; import org.elasticsearch.xpack.core.ml.dataframe.analyses.Classification;
import org.elasticsearch.xpack.core.ml.dataframe.analyses.OutlierDetection;
import org.elasticsearch.xpack.core.ml.utils.QueryProvider; import org.elasticsearch.xpack.core.ml.utils.QueryProvider;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.Matchers.lessThanOrEqualTo;
public class ExplainDataFrameAnalyticsIT extends MlNativeDataFrameAnalyticsIntegTestCase { public class ExplainDataFrameAnalyticsIT extends MlNativeDataFrameAnalyticsIntegTestCase {
public void testExplain_GivenMissingSourceIndex() {
DataFrameAnalyticsConfig config = new DataFrameAnalyticsConfig.Builder()
.setSource(new DataFrameAnalyticsSource(new String[] {"missing_index"}, null, null))
.setAnalysis(new OutlierDetection.Builder().build())
.buildForExplain();
ResourceNotFoundException e = expectThrows(ResourceNotFoundException.class, () -> explainDataFrame(config));
assertThat(e.getMessage(), equalTo("cannot retrieve data because index [missing_index] does not exist"));
}
public void testSourceQueryIsApplied() throws IOException { public void testSourceQueryIsApplied() throws IOException {
// To test the source query is applied when we extract data, // To test the source query is applied when we extract data,
// we set up a job where we have a query which excludes all but one document. // we set up a job where we have a query which excludes all but one document.

View File

@ -171,9 +171,10 @@ public class ExtractedFieldsDetectorFactory {
docValueFieldsLimitListener.onResponse(minDocValueFieldsLimit); docValueFieldsLimitListener.onResponse(minDocValueFieldsLimit);
}, },
e -> { e -> {
if (ExceptionsHelper.unwrapCause(e) instanceof IndexNotFoundException) { Throwable cause = ExceptionsHelper.unwrapCause(e);
if (cause instanceof IndexNotFoundException) {
docValueFieldsLimitListener.onFailure(new ResourceNotFoundException("cannot retrieve data because index " docValueFieldsLimitListener.onFailure(new ResourceNotFoundException("cannot retrieve data because index "
+ ((IndexNotFoundException) e).getIndex() + " does not exist")); + ((IndexNotFoundException) cause).getIndex() + " does not exist"));
} else { } else {
docValueFieldsLimitListener.onFailure(e); docValueFieldsLimitListener.onFailure(e);
} }