com.mx.path.gateway.process.FutureWithGatewayContext Maven / Gradle / Ivy
package com.mx.path.gateway.process;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
import com.mx.path.core.common.gateway.GatewayException;
/**
* This class can be used to easily spin off an asynchronous future that handle Gateway context propagation. By default,
* this class will also handle submitting the future to a default executor service and handle catching & translating
* thread exceptions into Gateway exceptions. This class is backed by the AsyncWithGatewayContext class.
*
* Note: the future begins executing immediately after object creation. This means you can spin off N async tasks that
* will run in parallel until you want to wait for them to finish.
*
* Usage:
* {@code
*
* // begins the API call immediately (takes ~2 seconds)
* FutureWithGatewayContext remoteStrings = new FutureWithGatewayContext<>(() -> api.getRemoteStrings());
*
* // begins the API call immediately (takes ~2 seconds)
* FutureWithGatewayContext remoteInt = new FutureWithGatewayContext<>(() -> api.getRemoteInt());
*
* RemoteStrings strings = remoteStrings.get(); // blocks
* RemoteInt int = remoteInt.get(); // blocks
*
* // Total request time: ~2 seconds instead of ~4.
* }
*
* @param result type
*/
public final class FutureWithGatewayContext {
private static final long DEFAULT_RETRIEVAL_TIMEOUT_MILLIS = 10000;
private static final int DEFAULT_THREAD_POOL_SIZE = 20;
private static final ExecutorService DEFAULT_EXECUTOR = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
private long timeoutMillis = DEFAULT_RETRIEVAL_TIMEOUT_MILLIS;
private final Future future;
public FutureWithGatewayContext(Supplier lambda) {
future = DEFAULT_EXECUTOR.submit(new AsyncWithGatewayContext<>(lambda));
}
public FutureWithGatewayContext(Supplier lambda, long timeoutMillis) {
this.future = DEFAULT_EXECUTOR.submit(new AsyncWithGatewayContext<>(lambda));
this.timeoutMillis = timeoutMillis;
}
public FutureWithGatewayContext(Supplier lambda, ExecutorService executorService) {
this.future = executorService.submit(new AsyncWithGatewayContext<>(lambda));
}
public FutureWithGatewayContext(Supplier lambda, ExecutorService executorService, long timeoutMillis) {
this.future = executorService.submit(new AsyncWithGatewayContext<>(lambda));
this.timeoutMillis = timeoutMillis;
}
public T get() {
try {
return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
throw new GatewayException("FutureWithGatewayContext timeout out", e);
} catch (InterruptedException e) {
throw new GatewayException("FutureWithGatewayContext was interrupted", e);
} catch (ExecutionException e) {
throw new GatewayException("FutureWithGatewayContext execution failed", e);
}
}
}