001
002package io.vrap.rmf.base.client.http;
003
004import java.time.Duration;
005import java.util.concurrent.CompletableFuture;
006import java.util.concurrent.ExecutorService;
007import java.util.concurrent.ScheduledExecutorService;
008import java.util.function.Function;
009
010import io.vrap.rmf.base.client.ApiHttpRequest;
011import io.vrap.rmf.base.client.ApiHttpResponse;
012
013import dev.failsafe.Bulkhead;
014import dev.failsafe.Failsafe;
015import dev.failsafe.FailsafeExecutor;
016import dev.failsafe.spi.Scheduler;
017
018/**
019 * Implementation of a Queue to limit the number of concurrent requests handled by the client
020 *
021 * @include.example io.vrap.rmf.base.client.QueueMiddlewareTest#queueConfiguration()
022 */
023public class QueueMiddleware implements QueueRequestMiddleware, AutoCloseable {
024
025    private final FailsafeExecutor<ApiHttpResponse<byte[]>> failsafeExecutor;
026
027    public QueueMiddleware(final ExecutorService executorService, final int maxConnection, final Duration maxWaitTime) {
028        this(Scheduler.of(executorService), maxConnection, maxWaitTime);
029    }
030
031    public QueueMiddleware(final ScheduledExecutorService executorService, final int maxConnection,
032            final Duration maxWaitTime) {
033        this(Scheduler.of(executorService), maxConnection, maxWaitTime);
034    }
035
036    public QueueMiddleware(final int maxConnection, final Duration maxWaitTime) {
037        this(Scheduler.DEFAULT, maxConnection, maxWaitTime);
038    }
039
040    public QueueMiddleware(final Scheduler scheduler, final int maxConnections, final Duration maxWaitTime) {
041        final Bulkhead<ApiHttpResponse<byte[]>> bulkhead = Bulkhead.<ApiHttpResponse<byte[]>> builder(maxConnections)
042                .withMaxWaitTime(maxWaitTime)
043                .build();
044        this.failsafeExecutor = Failsafe.with(bulkhead).with(scheduler);
045    }
046
047    @Override
048    public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
049            Function<ApiHttpRequest, CompletableFuture<ApiHttpResponse<byte[]>>> next) {
050        return failsafeExecutor.getStageAsync(() -> next.apply(request));
051    }
052
053    @Override
054    public void close() {
055    }
056}