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

com.sap.hana.datalake.files.utils.http.RequestRetryHandler Maven / Gradle / Ivy

Go to download

An implementation of org.apache.hadoop.fs.FileSystem targeting SAP HANA Data Lake Files.

There is a newer version: 3.0.27
Show newest version
// © 2024 SAP SE or an SAP affiliate company. All rights reserved.
package com.sap.hana.datalake.files.utils.http;

import com.sap.hana.datalake.files.classification.InterfaceAudience;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Set;

@InterfaceAudience.Private
public class RequestRetryHandler implements HttpRequestRetryHandler {

  private static final Logger LOG = LoggerFactory.getLogger(RequestRetryHandler.class);

  private final int maxRetries;
  private final boolean retrySentRequests;
  private final Set> nonRetriableExceptions;

  public RequestRetryHandler(final int maxRetries, final boolean retrySentRequests, final Set> nonRetriableExceptions) {
    this.maxRetries = maxRetries;
    this.retrySentRequests = retrySentRequests;
    this.nonRetriableExceptions = nonRetriableExceptions;
  }

  @Override
  public boolean retryRequest(final IOException exception, final int executionCount, final HttpContext httpContext) {
    Args.notNull(exception, "exception");
    Args.notNull(httpContext, "httpContext");

    if (executionCount > this.maxRetries) {
      LOG.debug("Exception [{}] will not be retried; reason: max retries [{}] reached", exception.getClass(), this.maxRetries);
      return false;
    }

    if (!this.shouldRetryException(exception)) {
      LOG.debug("Exception [{}] will not be retried; reason: non retriable exception", exception.getClass());
      return false;
    }

    final HttpClientContext clientContext = HttpClientContext.adapt(httpContext);
    final HttpRequest request = clientContext.getRequest();

    if (this.requestIsAborted(request)) {
      LOG.debug("Exception [{}] will not be retried; reason: request aborted", exception.getClass());
      return false;
    }

    if (this.handleRequestAsIdempotent(request)) {
      LOG.debug("Exception [{}] will be retried; reason: request is idempotent", exception.getClass());
      return true;
    }

    // Retry if the request has not been sent fully or if it's OK to retry methods that have been sent
    if (!this.retrySentRequests && clientContext.isRequestSent()) {
      LOG.debug("Exception [{}] will not be retried; reason: request already sent", exception.getClass());
      return false;
    }

    LOG.debug("Exception [{}] will be retried", exception.getClass());

    return true;
  }

  private boolean shouldRetryException(final IOException exception) {
    if (this.nonRetriableExceptions.contains(exception.getClass())) {
      return false;
    }

    for (final Class rejectException : this.nonRetriableExceptions) {
      if (rejectException.isInstance(exception)) {
        return false;
      }
    }

    return true;
  }

  private boolean requestIsAborted(final HttpRequest request) {
    final HttpRequest effectiveRequest = request instanceof RequestWrapper ?
            ((RequestWrapper) request).getOriginal() :
            request;

    return effectiveRequest instanceof HttpUriRequest &&
            ((HttpUriRequest) effectiveRequest).isAborted();
  }

  private boolean handleRequestAsIdempotent(final HttpRequest request) {
    return !(request instanceof HttpEntityEnclosingRequest);
  }

}

// © 2024 SAP SE or an SAP affiliate company. All rights reserved.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy