use of reactor.netty.internal.shaded.reactor.pool.PoolShutdownException in project reactor-netty by reactor.
the class Http2Pool method drainLoop.
void drainLoop() {
recordInteractionTimestamp();
int maxPending = poolConfig.maxPending();
for (; ; ) {
@SuppressWarnings("unchecked") ConcurrentLinkedQueue<Slot> resources = CONNECTIONS.get(this);
@SuppressWarnings("unchecked") ConcurrentLinkedDeque<Borrower> borrowers = PENDING.get(this);
if (resources == null || borrowers == TERMINATED) {
return;
}
int borrowersCount = borrowers.size();
if (borrowersCount != 0) {
// find a connection that can be used for opening a new stream
Slot slot = findConnection(resources);
if (slot != null) {
Borrower borrower = borrowers.pollFirst();
if (borrower == null) {
resources.offer(slot);
continue;
}
if (isDisposed()) {
borrower.fail(new PoolShutdownException());
return;
}
if (slot.incrementConcurrencyAndGet() > 1) {
borrower.stopPendingCountdown();
if (log.isDebugEnabled()) {
log.debug(format(slot.connection.channel(), "Channel activated"));
}
ACQUIRED.incrementAndGet(this);
// we are ready here, the connection can be used for opening another stream
slot.deactivate();
poolConfig.acquisitionScheduler().schedule(() -> borrower.deliver(new Http2PooledRef(slot)));
} else {
borrowers.offerFirst(borrower);
continue;
}
} else {
int permits = poolConfig.allocationStrategy().getPermits(1);
if (permits <= 0) {
if (maxPending >= 0) {
borrowersCount = borrowers.size();
int toCull = borrowersCount - maxPending;
for (int i = 0; i < toCull; i++) {
Borrower extraneous = borrowers.pollFirst();
if (extraneous != null) {
pendingAcquireLimitReached(extraneous, maxPending);
}
}
}
} else {
Borrower borrower = borrowers.pollFirst();
if (borrower == null) {
continue;
}
if (isDisposed()) {
borrower.fail(new PoolShutdownException());
return;
}
borrower.stopPendingCountdown();
Mono<Connection> allocator = poolConfig.allocator();
Mono<Connection> primary = allocator.doOnEach(sig -> {
if (sig.isOnNext()) {
Connection newInstance = sig.get();
assert newInstance != null;
Slot newSlot = new Slot(this, newInstance);
if (log.isDebugEnabled()) {
log.debug(format(newInstance.channel(), "Channel activated"));
}
ACQUIRED.incrementAndGet(this);
newSlot.incrementConcurrencyAndGet();
newSlot.deactivate();
borrower.deliver(new Http2PooledRef(newSlot));
} else if (sig.isOnError()) {
Throwable error = sig.getThrowable();
assert error != null;
poolConfig.allocationStrategy().returnPermits(1);
borrower.fail(error);
}
}).contextWrite(borrower.currentContext());
primary.subscribe(alreadyPropagated -> {
}, alreadyPropagatedOrLogged -> drain(), this::drain);
}
}
}
if (WIP.decrementAndGet(this) == 0) {
recordInteractionTimestamp();
break;
}
}
}
use of reactor.netty.internal.shaded.reactor.pool.PoolShutdownException in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method testPoolGracefulShutdown.
@ParameterizedTest(name = "{displayName}({argumentsWithNames})")
@ValueSource(booleans = { false, true })
void testPoolGracefulShutdown(boolean enableGracefulShutdown) {
disposableServer = createServer().handle((req, res) -> res.sendString(Mono.just("testPoolGracefulShutdown").delayElement(Duration.ofMillis(50)))).bindNow();
ConnectionProvider.Builder providerBuilder = ConnectionProvider.builder("testPoolGracefulShutdown").maxConnections(1);
if (enableGracefulShutdown) {
providerBuilder.disposeTimeout(Duration.ofMillis(200));
}
ConnectionProvider provider = providerBuilder.build();
HttpClient client = createClient(provider, disposableServer.port()).doOnDisconnected(conn -> {
if (!provider.isDisposed()) {
provider.dispose();
}
});
List<Signal<String>> result = Flux.range(0, 2).flatMap(i -> client.get().uri("/").responseContent().aggregate().asString()).materialize().collectList().block(Duration.ofSeconds(5));
assertThat(result).isNotNull();
int onNext = 0;
int onError = 0;
for (Signal<String> signal : result) {
if (signal.isOnNext()) {
onNext++;
assertThat(signal.get()).isEqualTo("testPoolGracefulShutdown");
} else if (signal.getThrowable() instanceof PoolShutdownException) {
onError++;
}
}
if (enableGracefulShutdown) {
assertThat(onNext).isEqualTo(2);
assertThat(onError).isEqualTo(0);
} else {
assertThat(onNext).isEqualTo(1);
assertThat(onError).isEqualTo(1);
}
}
use of reactor.netty.internal.shaded.reactor.pool.PoolShutdownException in project reactor-netty by reactor.
the class Http2Pool method doAcquire.
void doAcquire(Borrower borrower) {
if (isDisposed()) {
borrower.fail(new PoolShutdownException());
return;
}
pendingOffer(borrower);
drain();
}
use of reactor.netty.internal.shaded.reactor.pool.PoolShutdownException in project reactor-netty by reactor.
the class Http2Pool method disposeLater.
@Override
public Mono<Void> disposeLater() {
return Mono.defer(() -> {
recordInteractionTimestamp();
@SuppressWarnings("unchecked") ConcurrentLinkedDeque<Borrower> q = PENDING.getAndSet(this, TERMINATED);
if (q != TERMINATED) {
Borrower p;
while ((p = q.pollFirst()) != null) {
p.fail(new PoolShutdownException());
}
// the last stream on that connection will release the connection to the parent pool
// the structure should not contain connections with 0 streams as the last stream on that connection
// always removes the connection from this pool
CONNECTIONS.getAndSet(this, null);
}
return Mono.empty();
});
}
Aggregations