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

org.embulk.util.retryhelper.jaxrs.JAXRSRetryHelper Maven / Gradle / Ivy

/*
 * Copyright 2020 The Embulk project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.embulk.util.retryhelper.jaxrs;

import java.util.Locale;
import org.embulk.util.retryhelper.Retryable;
import org.embulk.util.retryhelper.RetryExecutor;
import org.embulk.util.retryhelper.RetryGiveupException;
import org.slf4j.LoggerFactory;

public class JAXRSRetryHelper
        implements AutoCloseable
{
    public JAXRSRetryHelper(int maximumRetries,
                            int initialRetryIntervalMillis,
                            int maximumRetryIntervalMillis,
                            JAXRSClientCreator clientCreator)
    {
        this(maximumRetries,
             initialRetryIntervalMillis,
             maximumRetryIntervalMillis,
             clientCreator.create(),
             true,
             LoggerFactory.getLogger(JAXRSRetryHelper.class));
    }

    public JAXRSRetryHelper(int maximumRetries,
                            int initialRetryIntervalMillis,
                            int maximumRetryIntervalMillis,
                            JAXRSClientCreator clientCreator,
                            final org.slf4j.Logger logger)
    {
        this(maximumRetries,
             initialRetryIntervalMillis,
             maximumRetryIntervalMillis,
             clientCreator.create(),
             true,
             logger);
    }

    /**
     * Creates a {@code JAXRSRetryHelper} instance with a ready-made JAX-RS {@code Client} instance.
     *
     * Note that the {@code Client} instance is not automatically closed.
     */
    public static JAXRSRetryHelper createWithReadyMadeClient(int maximumRetries,
                                                             int initialRetryIntervalMillis,
                                                             int maximumRetryIntervalMillis,
                                                             final javax.ws.rs.client.Client client,
                                                             final org.slf4j.Logger logger)
    {
        return new JAXRSRetryHelper(maximumRetries,
                                    initialRetryIntervalMillis,
                                    maximumRetryIntervalMillis,
                                    client,
                                    false,
                                    logger);
    }

    private JAXRSRetryHelper(int maximumRetries,
                             int initialRetryIntervalMillis,
                             int maximumRetryIntervalMillis,
                             final javax.ws.rs.client.Client client,
                             boolean closeAutomatically,
                             final org.slf4j.Logger logger)
    {
        this.maximumRetries = maximumRetries;
        this.initialRetryIntervalMillis = initialRetryIntervalMillis;
        this.maximumRetryIntervalMillis = maximumRetryIntervalMillis;
        this.client = client;;
        this.closeAutomatically = closeAutomatically;
        this.logger = logger;
    }

    public  T requestWithRetry(final JAXRSResponseReader responseReader,
                                  final JAXRSSingleRequester singleRequester)
    {
        try {
            return RetryExecutor.builder()
                .withRetryLimit(this.maximumRetries)
                .withInitialRetryWaitMillis(this.initialRetryIntervalMillis)
                .withMaxRetryWaitMillis(this.maximumRetryIntervalMillis)
                .build()
                .runInterruptible(new Retryable() {
                        @Override
                        public T call()
                                throws Exception
                        {
                            // |javax.ws.rs.ProcessingException| can be throws
                            // by timeout in connection or reading.
                            javax.ws.rs.core.Response response = singleRequester.requestOnce(client);

                            if (response.getStatus() / 100 != 2) {
                                throw new javax.ws.rs.WebApplicationException(response);
                            }

                            return responseReader.readResponse(response);
                        }

                        @Override
                        public boolean isRetryableException(Exception exception)
                        {
                            return singleRequester.toRetry(exception);
                        }

                        @Override
                        public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
                                throws RetryGiveupException
                        {
                            String message = String.format(
                                Locale.ENGLISH, "Retrying %d/%d after %d seconds. Message: %s",
                                retryCount, retryLimit, retryWait / 1000, exception.getMessage());
                            if (retryCount % 3 == 0) {
                                logger.warn(message, exception);
                            }
                            else {
                                logger.warn(message);
                            }
                        }

                        @Override
                        public void onGiveup(Exception first, Exception last)
                                throws RetryGiveupException
                        {
                        }
                    });
        }
        catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            // InterruptedException must not be RuntimeException.
            throw new RuntimeException(ex);
        }
        catch (RetryGiveupException ex) {
            // RetryGiveupException is ExecutionException, which must not be RuntimeException.
            throw new RuntimeException(ex.getCause());
        }
    }

    @Override
    public void close()
    {
        if (this.closeAutomatically && this.client != null) {
            this.client.close();
        }
    }

    private final int maximumRetries;
    private final int initialRetryIntervalMillis;
    private final int maximumRetryIntervalMillis;
    private final javax.ws.rs.client.Client client;
    private final org.slf4j.Logger logger;
    private final boolean closeAutomatically;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy