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

com.gs.api.accelrx.web.client.AccelRxWebClientImpl Maven / Gradle / Ivy

package com.gs.api.accelrx.web.client;

import com.gs.api.accelrx.*;
import com.gs.api.accelrx.retry.RetryPolicyTransformers;
import com.gs.api.accelrx.web.client.response.AccelRxWebClientObservableResponse;
import com.gs.api.accelrx.web.client.response.AccelRxWebClientSingleResponse;
import com.gs.api.accelrx.web.client.validation.WebResponseValidation;
import dev.failsafe.RetryPolicy;
import dev.failsafe.RetryPolicyBuilder;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Single;
import io.vertx.rxjava3.core.Vertx;
import io.vertx.rxjava3.core.http.HttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.function.Function;

public class AccelRxWebClientImpl implements AccelRxWebClient {
    private static final Logger log = LoggerFactory.getLogger(AccelRxWebClientImpl.class);

    private final Vertx vertx;
    private final String serviceName;
    private final APIContract apiContract;
    private final AccelRxWebClientConfig webClientConfig;
    private final AccelRxWebClientServiceDiscovery serviceDiscovery;
    private final AccelRxWebClientSecurity webSecurity;
    private final WebResponseValidation responseValidation;
    private final AccelRxEncoding encoding;

    private final VertxClientBuilder clientBuilder;

    private final RetryPolicy requestRetryPolicy;
    private final RetryPolicyTransformers retryPolicyTransformers;

    public AccelRxWebClientImpl(Vertx vertx,
                                String serviceName,
                                APIContract apiContract,
                                AccelRxWebClientConfig webClientConfig,
                                AccelRxWebClientServiceDiscovery serviceDiscovery,
                                VertxClientBuilder clientBuilder,
                                AccelRxEncoding encoding,
                                AccelRxWebClientSecurity webSecurity,
                                WebResponseValidation responseValidation) {
        this.vertx = vertx;
        this.serviceName = serviceName;
        this.apiContract = apiContract;
        this.webClientConfig = webClientConfig;
        this.serviceDiscovery = serviceDiscovery;
        this.webSecurity = webSecurity;
        this.clientBuilder = clientBuilder;
        this.responseValidation = responseValidation;
        this.encoding = encoding;

        RetryPolicyBuilder retryPolicyBuilder = RetryPolicy.builder()
                .withMaxRetries(webClientConfig.retries());
        if (webClientConfig.retryDelayInMs() > 0) {
            retryPolicyBuilder.withDelay(Duration.ofMillis(webClientConfig.retryDelayInMs()));
        } else {
            retryPolicyBuilder.withBackoff(webClientConfig.retryBackoffDelayInMs(), webClientConfig.retryBackoffMaxDelayInMs(), ChronoUnit.MILLIS);
        }
        this.requestRetryPolicy = retryPolicyBuilder.build();
        this.retryPolicyTransformers = new RetryPolicyTransformers(vertx);
    }

    static AccelRxWebClient create(Vertx vertx,
                                   String serviceName,
                                   APIContract apiContract,
                                   AccelRxWebClientConfig webClientConfig,
                                   AccelRxWebClientServiceDiscovery serviceDiscovery,
                                   VertxClientBuilder clientBuilder,
                                   AccelRxEncoding encoding,
                                   AccelRxWebClientSecurity webSecurity,
                                   WebResponseValidation responseValidation) {
        log.info("Creating web client '{}'", serviceName);
        return new AccelRxWebClientImpl(
                vertx,
                serviceName,
                apiContract,
                webClientConfig,
                serviceDiscovery,
                clientBuilder,
                encoding,
                webSecurity,
                responseValidation);
    }

    @Override
    public Single execute(AccelRxWebClientRequest clientRequest) {
        return clientRequest.logger().start()
                .andThen(clientRequest.send(serviceDiscovery, encoding, webSecurity, clientProvider()))
                .compose(retryPolicyTransformers.retryWith(requestRetryPolicy, getFailureLogMessage(clientRequest)))
                .flatMap(response -> AccelRxWebClientSingleResponse.create(clientRequest, response, responseValidation.validatorFor(clientRequest.operationId()), encoding.jsonDeserializer()))
                .flatMap(response -> clientRequest.logger().endProcessResponse()
                        .andThen(Single.just(response)))
                .doOnSuccess(response -> clientRequest.logger().log(response))
                .map(response -> response);
    }

    @Override
    public Single executeToStream(AccelRxWebClientRequest clientRequest) {
        return clientRequest.logger().start()
                .andThen(clientRequest.send(serviceDiscovery, encoding, webSecurity, clientProvider()))
                .compose(retryPolicyTransformers.retryWith(requestRetryPolicy, getFailureLogMessage(clientRequest)))
                .map(response -> AccelRxWebClientObservableResponse.create(clientRequest, response))
                .doOnSuccess((response) -> clientRequest.logger().log(response))
                .map(response -> response);
    }

    private String getFailureLogMessage(AccelRxWebClientRequest clientRequest) {
        return String.format("Web client request for service: %s and operationId: %s", clientRequest.serviceName(), clientRequest.operationId());
    }

    @Override
    public String name() {
        return serviceName;
    }

    @Override
    public Completable refreshServiceDiscovery() {
        return serviceDiscovery.refresh();
    }

    private Function> clientProvider() {
        return (endpoint) -> clientBuilder.httpClient(endpoint.isSsl());
    }

}