Class ClientTuning

java.lang.Object
com.commercetools.docs.meta.ClientTuning

public class ClientTuning extends Object
Table of content

Tuning the client

Blocking execution

In a lot of frameworks there is no support for asynchronous execution and so it is necessary to wait for the responses. The client can wait for responses with the method RequestCommand.executeBlocking(). This method enforces a timeout for resilience and throws directly ApiHttpException.

ProjectApiRoot apiRoot = createProjectClient();
Project project = apiRoot.get().executeBlocking().getBody();

See the test code.

PolicyMiddleware

The PolicyMiddleware configures a client to handle failures like gateway timeouts and version conflicts through retrying the request. Limiting the number of parallel requests or timeouts

A best practice example to retry on gateway timeouts and similar problems.

ProjectApiRoot apiRoot = ApiRootBuilder.of()
        .defaultClient(ClientCredentials.of().withClientId("clientId").withClientSecret("clientSecret").build(),
            ServiceRegion.GCP_EUROPE_WEST1)
        .withPolicies(policies -> policies.withRetry(builder -> builder.maxRetries(5)
                .statusCodes(Arrays.asList(BAD_GATEWAY_502, SERVICE_UNAVAILABLE_503, GATEWAY_TIMEOUT_504))))
        .build("my-project");

See the test code.

For more configuration options see PolicyBuilder

Configure the underlying http client

The ApiRootBuilder has create methods which allow to pass a preconfigured HTTP client.

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy", 8080));
VrapHttpClient httpClient = new CtOkHttp4Client(builder -> builder.proxy(proxy));

ProjectApiRoot apiRoot = ApiRootBuilder.of(httpClient)
        .defaultClient(ClientCredentials.of()
                .withClientId("your-client-id")
                .withClientSecret("your-client-secret")
                .withScopes("your-scopes")
                .build(),
            ServiceRegion.GCP_EUROPE_WEST1)
        .build("my-project");

See the test code.

Limit concurrent requests

By default the client is initialized with a ForkJoinPool. The underlying HTTP client may have it's own configuration for limiting the maximum number of requests. By default the OkHttp and Apache AsyncHTTP client will be configured for 64 maximum requests.

To adjust this instantiate the HTTP client in the client builder

ApiRootBuilder.of(new CtOkHttp4Client(64, 64))
        // ...
        .build();

ApiRootBuilder.of(new CtApacheHttpClient(64, 64))
        // ...
        .build();

See the test code.

Another option is to use a middleware which limits the number of requests. The SDK provides for this use case the QueueMiddleware.

ApiRootBuilder.of()
        // ...
        .withPolicies(policies -> policies.withBulkhead(64, Duration.ofSeconds(10)))
        .build();

See the test code.

Timeouts

Underlying HTTP Clients are by default configured to timeout after 120 seconds. There are different ways to limit the time a call can take. One is to develop a middleware which times out when necessary. This also is the most flexible option as it leaves room to distinguish between different kind of requests like GET requests should timeout after 10 seconds where as POST requests should timeout after 120 seconds. It's best to use a resilience library like failsafe to implement this functionality.

dev.failsafe.Timeout<ApiHttpResponse<byte[]>> timeout = dev.failsafe.Timeout
        .<ApiHttpResponse<byte[]>> builder(Duration.ofSeconds(10))
        .build();
FailsafeExecutor<ApiHttpResponse<byte[]>> failsafeExecutor = Failsafe.with(timeout);

ProjectApiRoot apiRoot = ApiRootBuilder.of()
        .defaultClient(ClientCredentials.of()
                .withClientId("your-client-id")
                .withClientSecret("your-client-secret")
                .build(),
            ServiceRegion.GCP_EUROPE_WEST1)
        .addMiddleware((request, next) -> failsafeExecutor.getStageAsync(() -> next.apply(request)))
        .build("my-project");

See the test code.

Alternatively the underlying HTTP can be configured to timeout after a specified amount of time.

ProjectApiRoot apiRoot = ApiRootBuilder
        .of(new CtOkHttp4Client(builder -> builder.callTimeout(Duration.ofSeconds(10))))
        .defaultClient(ClientCredentials.of()
                .withClientId("your-client-id")
                .withClientSecret("your-client-secret")
                .build(),
            ServiceRegion.GCP_EUROPE_WEST1)
        .build("my-project");

See the test code.

RequestConfig config = RequestConfig.custom().setResponseTimeout(Timeout.ofSeconds(10)).build();
ProjectApiRoot apiRoot = ApiRootBuilder
        .of(new CtApacheHttpClient(builder -> builder.setDefaultRequestConfig(config)))
        .defaultClient(ClientCredentials.of()
                .withClientId("your-client-id")
                .withClientSecret("your-client-secret")
                .build(),
            ServiceRegion.GCP_EUROPE_WEST1)
        .build("my-project");

See the test code.

The third option is to use the timeout functionality of the futures

ProjectApiRoot apiRoot = createProjectClient();

apiRoot.get().execute().get(10, TimeUnit.SECONDS);
apiRoot.get().executeBlocking(Duration.ofSeconds(10));

See the test code.

  • Constructor Details

    • ClientTuning

      public ClientTuning()