Skip to content

Commit 3c0a975

Browse files
authored
ESQL: Test with a data node failure (#117164)
Adds a test that always fails on one of the data nodes and makes sure this comes back as a failure. When we build support for partial results we can use this test to simulate it.
1 parent 7705514 commit 3c0a975

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.action;
9+
10+
import org.elasticsearch.ElasticsearchException;
11+
import org.elasticsearch.action.index.IndexRequestBuilder;
12+
import org.elasticsearch.common.settings.Settings;
13+
import org.elasticsearch.common.util.CollectionUtils;
14+
import org.elasticsearch.index.mapper.OnScriptError;
15+
import org.elasticsearch.plugins.Plugin;
16+
import org.elasticsearch.plugins.ScriptPlugin;
17+
import org.elasticsearch.script.LongFieldScript;
18+
import org.elasticsearch.script.ScriptContext;
19+
import org.elasticsearch.script.ScriptEngine;
20+
import org.elasticsearch.search.lookup.SearchLookup;
21+
import org.elasticsearch.test.ESIntegTestCase;
22+
import org.elasticsearch.xcontent.XContentBuilder;
23+
import org.elasticsearch.xcontent.json.JsonXContent;
24+
25+
import java.io.IOException;
26+
import java.util.ArrayList;
27+
import java.util.Collection;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.Set;
31+
32+
import static org.hamcrest.Matchers.equalTo;
33+
34+
/**
35+
* Make sure the failures on the data node come back as failures over the wire.
36+
*/
37+
@ESIntegTestCase.ClusterScope(minNumDataNodes = 2)
38+
public class EsqlNodeFailureIT extends AbstractEsqlIntegTestCase {
39+
@Override
40+
protected Collection<Class<? extends Plugin>> nodePlugins() {
41+
return CollectionUtils.appendToCopy(super.nodePlugins(), FailingFieldPlugin.class);
42+
}
43+
44+
/**
45+
* Use a runtime field that fails when loading field values to fail the entire query.
46+
*/
47+
public void testFailureLoadingFields() throws IOException {
48+
XContentBuilder mapping = JsonXContent.contentBuilder().startObject();
49+
mapping.startObject("runtime");
50+
{
51+
mapping.startObject("fail_me");
52+
{
53+
mapping.field("type", "long");
54+
mapping.startObject("script").field("source", "").field("lang", "fail").endObject();
55+
}
56+
mapping.endObject();
57+
}
58+
mapping.endObject();
59+
client().admin().indices().prepareCreate("fail").setSettings(indexSettings(1, 0)).setMapping(mapping.endObject()).get();
60+
61+
int docCount = 100;
62+
List<IndexRequestBuilder> docs = new ArrayList<>(docCount);
63+
for (int d = 0; d < docCount; d++) {
64+
docs.add(client().prepareIndex("ok").setSource("foo", d));
65+
}
66+
docs.add(client().prepareIndex("fail").setSource("foo", 0));
67+
indexRandom(true, docs);
68+
69+
ElasticsearchException e = expectThrows(ElasticsearchException.class, () -> run("FROM fail,ok | LIMIT 100").close());
70+
assertThat(e.getMessage(), equalTo("test failure"));
71+
}
72+
73+
public static class FailingFieldPlugin extends Plugin implements ScriptPlugin {
74+
75+
@Override
76+
public ScriptEngine getScriptEngine(Settings settings, Collection<ScriptContext<?>> contexts) {
77+
return new ScriptEngine() {
78+
@Override
79+
public String getType() {
80+
return "fail";
81+
}
82+
83+
@Override
84+
@SuppressWarnings("unchecked")
85+
public <FactoryType> FactoryType compile(
86+
String name,
87+
String code,
88+
ScriptContext<FactoryType> context,
89+
Map<String, String> params
90+
) {
91+
return (FactoryType) new LongFieldScript.Factory() {
92+
@Override
93+
public LongFieldScript.LeafFactory newFactory(
94+
String fieldName,
95+
Map<String, Object> params,
96+
SearchLookup searchLookup,
97+
OnScriptError onScriptError
98+
) {
99+
return ctx -> new LongFieldScript(fieldName, params, searchLookup, onScriptError, ctx) {
100+
@Override
101+
public void execute() {
102+
throw new ElasticsearchException("test failure");
103+
}
104+
};
105+
}
106+
};
107+
}
108+
109+
@Override
110+
public Set<ScriptContext<?>> getSupportedContexts() {
111+
return Set.of(LongFieldScript.CONTEXT);
112+
}
113+
};
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)