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

com.algolia.ApiClient Maven / Gradle / Ivy

The newest version!
package com.algolia;

import com.algolia.config.*;
import com.algolia.exceptions.AlgoliaRuntimeException;
import com.algolia.internal.HttpRequester;
import com.algolia.internal.JsonSerializer;
import com.algolia.internal.StatefulHost;
import com.algolia.internal.interceptors.AuthInterceptor;
import com.algolia.internal.interceptors.RetryStrategy;
import com.algolia.internal.interceptors.UserAgentInterceptor;
import com.fasterxml.jackson.core.type.TypeReference;
import java.io.Closeable;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.jetbrains.annotations.Nullable;

/**
 * Represents a base client for making API requests. The client uses a {@link Requester} for
 * executing requests and an {@link ExecutorService} for asynchronous operations. It is designed to
 * be extended by concrete API client implementations.
 */
public abstract class ApiClient implements Closeable {

  private final Requester requester;
  private final ExecutorService executor;
  private AuthInterceptor authInterceptor;

  /** Constructs a new instance of the {@link ApiClient}. */
  protected ApiClient(
    String appId,
    String apiKey,
    String clientName,
    @Nullable ClientOptions options,
    List defaultHosts,
    Duration connectTimeout,
    Duration readTimeout,
    Duration writeTimeout
  ) {
    if (appId == null || appId.isEmpty()) {
      throw new AlgoliaRuntimeException("`appId` is missing.");
    }
    if (apiKey == null || apiKey.isEmpty()) {
      throw new AlgoliaRuntimeException("`apiKey` is missing.");
    }
    final ClientOptions clientOptions = options != null ? options : new ClientOptions();
    this.executor = clientOptions.getExecutor();
    this.requester = clientOptions.getCustomRequester() != null
      ? clientOptions.getCustomRequester()
      : defaultRequester(appId, apiKey, clientName, clientOptions, defaultHosts, connectTimeout, readTimeout, writeTimeout);
  }

  /** Creates a default {@link Requester} for executing API requests. */
  private Requester defaultRequester(
    String appId,
    String apiKey,
    String clientName,
    ClientOptions options,
    List defaultHosts,
    Duration connectTimeout,
    Duration readTimeout,
    Duration writeTimeout
  ) {
    AlgoliaAgent algoliaAgent = new AlgoliaAgent(BuildConfig.VERSION)
      .addSegment(new AlgoliaAgent.Segment(clientName, BuildConfig.VERSION))
      .addSegments(options.getAlgoliaAgentSegments());

    List hosts = options.getHosts() != null && !options.getHosts().isEmpty() ? options.getHosts() : defaultHosts;
    List statefulHosts = hosts.stream().map(StatefulHost::new).collect(Collectors.toList());

    JsonSerializer serializer = JsonSerializer.builder().setCustomConfig(options.getMapperConfig()).build();
    this.authInterceptor = new AuthInterceptor(appId, apiKey);
    HttpRequester.Builder builder = new HttpRequester.Builder(serializer)
      .addInterceptor(authInterceptor)
      .addInterceptor(new UserAgentInterceptor(algoliaAgent))
      .addInterceptor(new RetryStrategy(statefulHosts))
      .setConnectTimeout(connectTimeout)
      .setReadTimeout(readTimeout)
      .setWriteTimeout(writeTimeout);
    if (options.getRequesterConfig() != null) {
      options.getRequesterConfig().accept(builder);
    }
    return builder.build(options);
  }

  /**
   * Helper method to switch the API key used to authenticate the requests.
   *
   * @param apiKey The new API key to be used from now on.
   */
  public void setClientApiKey(@Nonnull String apiKey) {
    this.authInterceptor.setApiKey(apiKey);
  }

  /**
   * Executes an HTTP request asynchronously and returns a {@link CompletableFuture} of the response
   * deserialized into a specified type.
   */
  protected  CompletableFuture executeAsync(HttpRequest httpRequest, RequestOptions requestOptions, TypeReference returnType) {
    return CompletableFuture.supplyAsync(() -> requester.execute(httpRequest, requestOptions, returnType), executor);
  }

  /**
   * Executes an HTTP request asynchronously and returns a {@link CompletableFuture} of the response
   * deserialized into a specified type.
   */
  protected  CompletableFuture executeAsync(
    HttpRequest httpRequest,
    RequestOptions requestOptions,
    Class returnType,
    Class innerType
  ) {
    return CompletableFuture.supplyAsync(() -> requester.execute(httpRequest, requestOptions, returnType, innerType), executor);
  }

  @Override
  public void close() throws IOException {
    executor.shutdown();
    requester.close();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy