All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.polyglotted.elastic.client.ElasticRestClient Maven / Gradle / Ivy

The newest version!
package io.polyglotted.elastic.client;

import io.polyglotted.common.model.MapResult;
import io.polyglotted.common.util.HttpRequestBuilder.HttpReqType;
import io.polyglotted.common.util.MapBuilder.ImmutableMapBuilder;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import org.apache.http.ConnectionClosedException;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.sniff.Sniffer;

import javax.annotation.Nullable;
import java.io.IOException;
import java.net.ConnectException;
import java.util.List;
import java.util.Map;

import static io.polyglotted.common.model.MapResult.immutableResult;
import static io.polyglotted.common.util.BaseSerializer.deserialize;
import static io.polyglotted.common.util.BaseSerializer.deserializeToList;
import static io.polyglotted.common.util.HttpRequestBuilder.HttpReqType.DELETE;
import static io.polyglotted.common.util.HttpRequestBuilder.HttpReqType.GET;
import static io.polyglotted.common.util.HttpRequestBuilder.HttpReqType.POST;
import static io.polyglotted.common.util.MapBuilder.immutableMapBuilder;
import static io.polyglotted.common.util.MapRetriever.asMap;
import static io.polyglotted.common.util.MapRetriever.deepRetrieve;
import static io.polyglotted.common.util.MapRetriever.mapVal;
import static io.polyglotted.common.util.MapRetriever.reqdStr;
import static io.polyglotted.common.util.StrUtil.*;
import static io.polyglotted.common.util.ThreadUtil.safeSleep;
import static io.polyglotted.elastic.client.ElasticException.checkState;
import static io.polyglotted.elastic.client.ElasticException.throwEx;
import static io.polyglotted.elastic.client.InternalHostsSniffer.addHeader;
import static io.polyglotted.elastic.client.InternalHostsSniffer.buildSniffer;
import static java.util.Collections.emptyMap;
import static org.apache.http.HttpStatus.SC_MULTIPLE_CHOICES;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;

@Accessors(fluent = true)
public class ElasticRestClient implements ElasticClient {
    private final RestClient internalClient;
    private final Sniffer sniffer;
    @Nullable @Getter private final Header bootstrapAuth;

    ElasticRestClient(RestClientBuilder builder, ElasticSettings settings, @Nullable Header bootstrapAuth) {
        internalClient = builder.build();
        this.sniffer = settings.enableSniffer ? buildSniffer(this.internalClient, settings, bootstrapAuth) : null;
        this.bootstrapAuth = bootstrapAuth;
    }

    @Override @SneakyThrows public void close() { if (sniffer != null) { sniffer.close(); } internalClient.close(); }

    @SuppressWarnings("ALL")
    @Override public ElasticClient waitForStatus(Header auth, String status) {
        try {
            for (int i = 0; i <= 300; i++) {
                performCliRequest(auth, GET, "/_cluster/health?wait_for_status=" + status); break;
            }
        } catch (ConnectException | ConnectionClosedException retry) {
            safeSleep(1000); waitForStatus(auth, status);
        } catch (Exception ioe) { throw throwEx("waitForStatus failed", ioe); }
        return this;
    }

    @Override public MapResult clusterHealth(Header auth) { return deserialize(simpleGet(auth, "/_cluster/health", "clusterHealth")); }

    @Override public boolean indexExists(Header auth, String index) {
        try {
            return internalClient.performRequest(addHeader(new Request("HEAD", "/" + index), auth))
                .getStatusLine().getStatusCode() == SC_OK;
        } catch (Exception ioe) { throw throwEx("indexExists failed", ioe); }
    }

    @Override public MapResult indexNameFor(Header auth, String alias) {
        ImmutableMapBuilder result = immutableMapBuilder();
        try {
            List> list = deserializeToList(performCliRequest(auth, GET, "/_cat/aliases"
                + (notNullOrEmpty(alias) ? "/" + alias : "") + "?h=index,alias&format=json"));
            for (Map map : list) { result.put(reqdStr(map, "alias"), reqdStr(map, "index")); }
            return result.result();
        } catch (Exception ioe) { throw throwEx("indexNameFor failed", ioe); }
    }

    @Override public String createIndex(Header auth, String index, String body) {
        try {
            MapResult result = deserialize(simplePut(auth, "/" + index, body, "createIndex"));
            checkState(result.boolVal("acknowledged", false) && result.boolVal("shards_acknowledged", false), "unable to create index");
            return result.reqdStr("index");
        } catch (Exception ioe) { throw throwEx("createIndex failed", ioe); }
    }

    @Override public void dropIndex(Header auth, String index) { simpleDelete(auth, "/" + index, "dropIndex"); }

    @Override public void openIndex(Header auth, String index) { simplePost(auth, "/" + index + "/_open", null, "openIndex"); }

    @Override public void closeIndex(Header auth, String index) {simplePost(auth, "/" + index + "/_close", null, "closeIndex"); }

    @Override public void forceRefresh(Header auth, String index) {
        try {
            performCliRequest(auth, POST, "/" + index + "/_refresh");
        } catch (Exception ioe) { throw throwEx("forceRefresh failed", ioe); }
    }

    @Override public void putSettings(Header auth, String index, String settingsJson) {
        try {
            performCliRequest(auth, POST, "/" + index + "/_close");
            simplePut(auth, "/" + index + "/_settings", settingsJson, "putSettings");
            performCliRequest(auth, POST, "/" + index + "/_open");

        } catch (Exception e) { throw throwEx("putSettings failed", e); }
    }

    @Override public MapResult getSettings(Header auth, String index) {
        try {
            MapResult result = deserialize(simpleGet(auth, "/" + index + "/_settings", "getSettings"));
            return immutableResult(deepRetrieve(asMap(result.first()), "settings.index"));
        } catch (Exception e) { throw throwEx("getSettings failed", e); }
    }

    @Override public void putMapping(Header auth, String index, String type, String mappingJson) {
        simplePut(auth, "/" + index + "/_mapping/" + type, mappingJson, "putMapping");
    }

    @Override public MapResult getMapping(Header auth, String index, String type) {
        try {
            MapResult result = deserialize(performCliRequest(auth, GET, "/" + index + "/_mapping/" + type));
            return immutableResult(mapVal(asMap(result.first()), "mappings"));
        } catch (Exception e) { throw throwEx("getMapping failed", e); }
    }

    @Override
    public void putAliases(Header auth, String aliasesJson) {
        simplePost(auth, "/_aliases", aliasesJson, "putAliases");
    }

    @Override
    public MapResult getAlias(Header auth, String alias) {
        try {
            return deserialize(performCliRequest(auth, GET, nullOrEmpty(alias) ? "/_alias" : "/_alias/" + alias));
        } catch (Exception e) { throw throwEx("getAlias failed", e); }
    }

    @Override public void putPipeline(Header auth, String id, String body) { simplePut(auth, "/_ingest/pipeline/" + id, body, "putPipeline"); }

    @Override public boolean pipelineExists(Header auth, String id) { return simpleGet(auth, "/_ingest/pipeline/" + id, "pipelineExists") != null; }

    @Override public void deletePipeline(Header auth, String id) { simpleDelete(auth, "/_ingest/pipeline/" + id, "deletePipeline"); }

    @Override public void putTemplate(Header auth, String name, String body) { simplePut(auth, "/_template/" + name, body, "putTemplate"); }

    @Override public boolean templateExists(Header auth, String name) { return simpleGet(auth, "/_template/" + name, "templateExists") != null; }

    @Override public void deleteTemplate(Header auth, String name) { simpleDelete(auth, "/_template/" + name, "deleteTemplate"); }

    @Override public String simpleGet(Header auth, String endpoint, String methodName) {
        Exception throwable;
        try {
            return performCliRequest(auth, GET, endpoint);

        } catch (ResponseException re) {
            if (re.getResponse().getStatusLine().getStatusCode() == 404) { return null; }
            throwable = re;
        } catch (Exception ioe) { throwable = ioe; }
        throw throwEx(methodName + " failed", throwable);
    }

    @Override public String simplePost(Header auth, String endpoint, String body, String methodName) {
        return simpleExecute(auth, HttpReqType.POST, endpoint, body, methodName);
    }

    @Override public String simplePut(Header auth, String endpoint, String body, String methodName) {
        return simpleExecute(auth, HttpReqType.PUT, endpoint, body, methodName);
    }

    private String simpleExecute(Header auth, HttpReqType type, String endpoint, String body, String methodName) {
        try {
            return performCliRequest(auth, type, endpoint, emptyMap(), new StringEntity(nonNullStr(body, "{}"), APPLICATION_JSON));
        } catch (Exception ioe) { throw throwEx(methodName + " failed", ioe); }
    }

    @Override public void simpleDelete(Header auth, String endpoint, String methodName) {
        try {
            performCliRequest(auth, DELETE, endpoint);
        } catch (Exception ioe) { throw throwEx(methodName + " failed", ioe); }
    }

    @Override public String performCliRequest(Header auth, HttpReqType method, String endpoint) throws IOException {
        return performCliRequest(auth, method, endpoint, emptyMap(), null);
    }

    @Override public String performCliRequest(Header auth, HttpReqType method, String endpoint,
                                              Map params, HttpEntity entity) throws IOException {
        Request request = new Request(method.name(), endpoint.startsWith("/") ? endpoint : "/" + endpoint);
        for (Map.Entry e : params.entrySet()) { request.addParameter(e.getKey(), e.getValue()); }
        request.setEntity(entity);
        addHeader(request, auth);
        Response response = internalClient.performRequest(request);

        int statusCode = response.getStatusLine().getStatusCode();
        checkState(statusCode >= SC_OK && statusCode < SC_MULTIPLE_CHOICES, response.getStatusLine().getReasonPhrase());
        return EntityUtils.toString(response.getEntity());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy