package com.github.obourgain.elasticsearch.http.client; import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.Future; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.count.CountRequest; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.deletebyquery.DeleteByQueryRequest; import org.elasticsearch.action.exists.ExistsRequest; import org.elasticsearch.action.explain.ExplainRequest; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.MultiGetRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.mlt.MoreLikeThisRequest; import org.elasticsearch.action.percolate.MultiPercolateRequest; import org.elasticsearch.action.percolate.PercolateRequest; import org.elasticsearch.action.search.ClearScrollRequest; import org.elasticsearch.action.search.MultiSearchRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.suggest.SuggestRequest; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.termvector.TermVectorRequest; import org.elasticsearch.action.update.UpdateRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.obourgain.elasticsearch.http.concurrent.SnapshotableCopyOnWriteArray; import com.github.obourgain.elasticsearch.http.handler.document.bulk.BulkActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.bulk.BulkResponse; import com.github.obourgain.elasticsearch.http.handler.document.delete.DeleteActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.delete.DeleteResponse; import com.github.obourgain.elasticsearch.http.handler.document.deleteByQuery.DeleteByQueryActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.deleteByQuery.DeleteByQueryResponse; import com.github.obourgain.elasticsearch.http.handler.document.get.GetActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.get.GetResponse; import com.github.obourgain.elasticsearch.http.handler.document.index.IndexActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.index.IndexResponse; import com.github.obourgain.elasticsearch.http.handler.document.morelikethis.MoreLikeThisActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.multiget.MultiGetActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.multiget.MultiGetResponse; import com.github.obourgain.elasticsearch.http.handler.document.termvectors.TermVectorResponse; import com.github.obourgain.elasticsearch.http.handler.document.termvectors.TermVectorsActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.update.UpdateActionHandler; import com.github.obourgain.elasticsearch.http.handler.document.update.UpdateResponse; import com.github.obourgain.elasticsearch.http.handler.search.clearscroll.ClearScrollActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.clearscroll.ClearScrollResponse; import com.github.obourgain.elasticsearch.http.handler.search.count.CountActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.count.CountResponse; import com.github.obourgain.elasticsearch.http.handler.search.exists.ExistsActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.exists.ExistsResponse; import com.github.obourgain.elasticsearch.http.handler.search.explain.ExplainActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.explain.ExplainResponse; import com.github.obourgain.elasticsearch.http.handler.search.multipercolate.MultiPercolateActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.multipercolate.MultiPercolateResponse; import com.github.obourgain.elasticsearch.http.handler.search.percolate.PercolateActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.percolate.PercolateResponse; import com.github.obourgain.elasticsearch.http.handler.search.search.MultiSearchActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.search.MultiSearchResponse; import com.github.obourgain.elasticsearch.http.handler.search.search.SearchActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.search.SearchResponse; import com.github.obourgain.elasticsearch.http.handler.search.search.SearchScrollActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.suggest.SuggestActionHandler; import com.github.obourgain.elasticsearch.http.handler.search.suggest.SuggestResponse; import com.google.common.base.Supplier; import io.netty.buffer.ByteBuf; import io.reactivex.netty.RxNetty; import io.reactivex.netty.client.RxClient; import io.reactivex.netty.protocol.http.client.HttpClientBuilder; /** * @author olivier bourgain */ public class HttpClient { private static final Logger logger = LoggerFactory.getLogger(HttpClient.class); private static final int DEFAULT_MAX_CONNECTIONS = 10; private static final int DEFAULT_TIMEOUT_MILLIS = 30 * 1000 * 1000; private SnapshotableCopyOnWriteArray<io.reactivex.netty.protocol.http.client.HttpClient<ByteBuf, ByteBuf>> clients; private Supplier<io.reactivex.netty.protocol.http.client.HttpClient<ByteBuf, ByteBuf>> clientSupplier; private int maxConnections = DEFAULT_MAX_CONNECTIONS; private int timeOut = DEFAULT_TIMEOUT_MILLIS; private HttpAdminClient httpAdminClient; private IndexActionHandler indexActionHandler = new IndexActionHandler(this); private GetActionHandler getActionHandler = new GetActionHandler(this); private MultiGetActionHandler multiGetActionHandler = new MultiGetActionHandler(this); private DeleteActionHandler deleteActionHandler = new DeleteActionHandler(this); private UpdateActionHandler updateActionHandler = new UpdateActionHandler(this); private DeleteByQueryActionHandler deleteByQueryActionHandler = new DeleteByQueryActionHandler(this); private TermVectorsActionHandler termVectorActionHandler = new TermVectorsActionHandler(this); private SearchActionHandler searchActionHandler = new SearchActionHandler(this); private MultiSearchActionHandler multiSearchActionHandler = new MultiSearchActionHandler(this); private CountActionHandler countActionHandler = new CountActionHandler(this); private ExistsActionHandler existsActionHandler = new ExistsActionHandler(this); private ExplainActionHandler explainActionHandler = new ExplainActionHandler(this); private PercolateActionHandler percolateActionHandler = new PercolateActionHandler(this); private MultiPercolateActionHandler multiPercolateActionHandler = new MultiPercolateActionHandler(this); private MoreLikeThisActionHandler moreLikeThisActionHandler = new MoreLikeThisActionHandler(this); private ClearScrollActionHandler clearScrollActionHandler = new ClearScrollActionHandler(this); private SearchScrollActionHandler searchScrollActionHandler = new SearchScrollActionHandler(this); private BulkActionHandler bulkActionHandler = new BulkActionHandler(this); private SuggestActionHandler suggestActionHandler = new SuggestActionHandler(this); public HttpClient(String ... nodes) { this(Arrays.asList(nodes)); } public HttpClient(Collection<String> nodes) { // searchShard // search template List<io.reactivex.netty.protocol.http.client.HttpClient<ByteBuf, ByteBuf>> clientsTemp = new ArrayList<>(); // expect something like "http://%s:%d" for (String node : nodes) { String[] next = node.split(":"); // indices admin String host = next[1].substring(2); // remove the // of http:// int port = Integer.parseInt(next[2]); HttpClientBuilder<ByteBuf, ByteBuf> clientBuilder = RxNetty.newHttpClientBuilder(host, port); clientBuilder.config(new RxClient.ClientConfig.Builder().readTimeout(timeOut, MILLISECONDS).build()); clientBuilder.withMaxConnections(maxConnections); clientsTemp.add(clientBuilder.build()); logger.info("adding host {}:{}", host, port); } this.clients = new SnapshotableCopyOnWriteArray<>(clientsTemp); clientSupplier = new RoundRobinSupplier<>(clients); this.httpAdminClient = new HttpAdminClient(clientSupplier); } public void close() { // TODO prevent servers to be added while here for (io.reactivex.netty.protocol.http.client.HttpClient<ByteBuf, ByteBuf> client : clients.snapshot()) { client.shutdown(); } } public HttpAdminClient admin() { return httpAdminClient; } public io.reactivex.netty.protocol.http.client.HttpClient<ByteBuf, ByteBuf> getHttpClient() { return clientSupplier.get(); } public void index(IndexRequest request, ActionListener<IndexResponse> listener) { indexActionHandler.execute(request, listener); } public Future<IndexResponse> index(IndexRequest request) { PlainActionFuture<IndexResponse> future = PlainActionFuture.newFuture(); index(request, future); return future; } public void get(GetRequest request, ActionListener<GetResponse> listener) { getActionHandler.execute(request, listener); } public Future<GetResponse> get(GetRequest request) { PlainActionFuture<GetResponse> future = PlainActionFuture.newFuture(); get(request, future); return future; } public void multiGet(MultiGetRequest request, ActionListener<MultiGetResponse> listener) { multiGetActionHandler.execute(request, listener); } public Future<MultiGetResponse> multiGet(MultiGetRequest request) { PlainActionFuture<MultiGetResponse> future = PlainActionFuture.newFuture(); multiGet(request, future); return future; } public void delete(DeleteRequest request, ActionListener<DeleteResponse> listener) { deleteActionHandler.execute(request, listener); } public Future<DeleteResponse> delete(DeleteRequest request) { PlainActionFuture<DeleteResponse> future = PlainActionFuture.newFuture(); delete(request, future); return future; } public void update(UpdateRequest request, ActionListener<UpdateResponse> listener) { updateActionHandler.execute(request, listener); } public Future<UpdateResponse> update(UpdateRequest request) { PlainActionFuture<UpdateResponse> future = PlainActionFuture.newFuture(); update(request, future); return future; } public void deleteByQuery(DeleteByQueryRequest request, ActionListener<DeleteByQueryResponse> listener) { deleteByQueryActionHandler.execute(request, listener); } public Future<DeleteByQueryResponse> deleteByQuery(DeleteByQueryRequest request) { PlainActionFuture<DeleteByQueryResponse> future = PlainActionFuture.newFuture(); deleteByQuery(request, future); return future; } public void termVectors(TermVectorRequest request, ActionListener<TermVectorResponse> listener) { termVectorActionHandler.execute(request, listener); } public Future<TermVectorResponse> termVectors(TermVectorRequest request) { PlainActionFuture<TermVectorResponse> future = PlainActionFuture.newFuture(); termVectors(request, future); return future; } public void search(SearchRequest request, ActionListener<SearchResponse> listener) { searchActionHandler.execute(request, listener); } public Future<SearchResponse> search(SearchRequest request) { PlainActionFuture<SearchResponse> future = PlainActionFuture.newFuture(); search(request, future); return future; } public void multiSearch(MultiSearchRequest request, ActionListener<MultiSearchResponse> listener) { multiSearchActionHandler.execute(request, listener); } public Future<MultiSearchResponse> multiSearch(MultiSearchRequest request) { PlainActionFuture<MultiSearchResponse> future = PlainActionFuture.newFuture(); multiSearch(request, future); return future; } public void count(CountRequest request, ActionListener<CountResponse> listener) { countActionHandler.execute(request, listener); } public Future<CountResponse> count(CountRequest request) { PlainActionFuture<CountResponse> future = PlainActionFuture.newFuture(); count(request, future); return future; } public void exists(ExistsRequest request, ActionListener<ExistsResponse> listener) { existsActionHandler.execute(request, listener); } public Future<ExistsResponse> exists(ExistsRequest request) { PlainActionFuture<ExistsResponse> future = PlainActionFuture.newFuture(); exists(request, future); return future; } public void explain(ExplainRequest request, ActionListener<ExplainResponse> listener) { explainActionHandler.execute(request, listener); } public Future<ExplainResponse> explain(ExplainRequest request) { PlainActionFuture<ExplainResponse> future = PlainActionFuture.newFuture(); explain(request, future); return future; } public void percolate(PercolateRequest request, ActionListener<PercolateResponse> listener) { percolateActionHandler.execute(request, listener); } public Future<PercolateResponse> percolate(PercolateRequest request) { PlainActionFuture<PercolateResponse> future = PlainActionFuture.newFuture(); percolate(request, future); return future; } public void multiPercolate(MultiPercolateRequest request, ActionListener<MultiPercolateResponse> listener) { multiPercolateActionHandler.execute(request, listener); } public Future<MultiPercolateResponse> multiPercolate(MultiPercolateRequest request) { PlainActionFuture<MultiPercolateResponse> future = PlainActionFuture.newFuture(); multiPercolate(request, future); return future; } public void moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) { moreLikeThisActionHandler.execute(request, listener); } public Future<SearchResponse> moreLikeThis(MoreLikeThisRequest request) { PlainActionFuture<SearchResponse> future = PlainActionFuture.newFuture(); moreLikeThis(request, future); return future; } public void searchScroll(SearchScrollRequest request, ActionListener<SearchResponse> listener) { searchScrollActionHandler.execute(request, listener); } public Future<SearchResponse> searchScroll(SearchScrollRequest request) { PlainActionFuture<SearchResponse> future = PlainActionFuture.newFuture(); searchScroll(request, future); return future; } public void clearScroll(ClearScrollRequest request, ActionListener<ClearScrollResponse> listener) { clearScrollActionHandler.execute(request, listener); } public Future<ClearScrollResponse> clearScroll(ClearScrollRequest request) { PlainActionFuture<ClearScrollResponse> future = PlainActionFuture.newFuture(); clearScroll(request, future); return future; } public void bulk(BulkRequest request, ActionListener<BulkResponse> listener) { bulkActionHandler.execute(request, listener); } public Future<BulkResponse> bulk(BulkRequest request) { PlainActionFuture<BulkResponse> future = PlainActionFuture.newFuture(); bulk(request, future); return future; } public void suggest(SuggestRequest request, ActionListener<SuggestResponse> listener) { suggestActionHandler.execute(request, listener); } public Future<SuggestResponse> suggest(SuggestRequest request) { PlainActionFuture<SuggestResponse> future = PlainActionFuture.newFuture(); suggest(request, future); return future; } }