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

io.sgr.telegram.bot.api.http.CompletableFutureBasedCallback Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2019 SgrAlpha
 *
 * 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 io.sgr.telegram.bot.api.http;

import static io.sgr.telegram.bot.api.utils.Preconditions.notNull;

import io.sgr.telegram.bot.api.exceptions.ApiCallException;
import io.sgr.telegram.bot.api.models.http.ApiErrorResponse;
import io.sgr.telegram.bot.api.models.http.ApiResponse;
import io.sgr.telegram.bot.api.utils.JsonUtil;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;

class CompletableFutureBasedCallback implements Callback> {

    private final CompletableFuture future;
    private final boolean retry;
    private final Logger logger;

    CompletableFutureBasedCallback(@Nonnull final CompletableFuture future, final boolean retry, @Nonnull final Logger logger) {
        notNull(future, "Missing future!");
        this.future = future;
        this.retry = retry;
        notNull(logger, "Missing logger!");
        this.logger = logger;
    }

    @Override public void onResponse(@Nonnull final Call> call, @Nonnull final Response> response) {
        if (response.isSuccessful()) {
            final ApiResponse rawBody = response.body();
            if (rawBody == null) {
                future.completeExceptionally(new IllegalStateException("Missing response body!"));
                return;
            }
            future.complete(rawBody.getResult());
            return;
        }
        final ResponseBody errorBody = response.errorBody();
        ApiErrorResponse apiError = null;
        if (errorBody != null) {
            try {
                apiError = JsonUtil.getObjectMapper().readValue(errorBody.bytes(), ApiErrorResponse.class);
            } catch (IOException e) {
                logger.error("{}: {}", e.getClass().getSimpleName(), e.getMessage());
            }
        }
        final String errDesc = apiError == null ? "NA" : apiError.getDescription().orElse("NA");
        if (response.code() >= 400 && response.code() < 500) {
            if (response.code() == 409) {
                future.completeExceptionally(new ApiCallException(apiError));
                return;
            }
            if (response.code() == 429) {
                int index = errDesc.lastIndexOf(' ');
                int time;
                try {
                    time = Integer.parseInt(errDesc.substring(index));
                } catch (Exception e) {
                    time = 3;
                }
                try {
                    TimeUnit.SECONDS.sleep(time);
                } catch (InterruptedException e) {
                    future.completeExceptionally(e);
                    return;
                }
                call.clone().enqueue(this);
                return;
            }
            logger.error("Error '{}:{}' received.", response.code(), errDesc);
            future.completeExceptionally(new ApiCallException(apiError));
            return;
        }
        if (retry) {
            logger.error("Error '{}:{}' received.", response.code(), errDesc);
            future.completeExceptionally(new ApiCallException(apiError));
            return;
        }
        logger.error("Error '{}:{}' received, retrying ...", response.code(), errDesc);
        call.clone().enqueue(this);
    }

    @Override public void onFailure(@Nonnull final Call> call, @Nonnull final Throwable t) {
        if (!retry) {
            future.completeExceptionally(t);
            return;
        }
        // Ignore client read timeout
        if ("timeout".equalsIgnoreCase(t.getMessage())) {
            future.completeExceptionally(t);
            return;
        }
        logger.error("{} '{}' received when sending message.", t.getClass().getSimpleName(), t.getMessage());
        call.clone().enqueue(this);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy