Question for plugin authors
What is the proper way to implement a REST handler in a custom ActionPlugin
(a.k.a. API extension plugin) that must wait for the response of multiple Elasticsearch requests before returning a response to the user?
Example
Consider the example handler below, which sends two requests to Elasticsearch on behalf of a single request from the user. The handler uses its given NodeClient
to:
- Create an index
- Perform a search
- Respond to the user after both actions have completed
@Override
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) {
return channel -> {
try {
// Create an arbitrary index
client.admin().indices().prepareCreate("sample-index")
.setSettings(Settings.builder()
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 0)
)
.addMapping("doc", "{\"properties\":{\"foo\":{\"type\":\"keyword\"}}}", XContentType.JSON)
.get();
// Submit an arbitrary search request
client.prepareSearch("*").get();
// Return an arbitrary response
XContentBuilder content = XContentFactory.jsonBuilder();
content.startObject().field("acknowledged", true).endObject();
channel.sendResponse(new BytesRestResponse(RestStatus.OK, content));
} catch (final Exception e) {
channel.sendResponse(new BytesRestResponse(channel, e));
}
};
}
Problem
The problem with the example above is that the two .get()
actions submitted by the NodeClient
are blocking calls (see explanation). This will cause an Elasticsearch cluster to hang.
What is the proper way to implement the desired behavior of the example above?