use of reactor.netty.resources.DefaultPooledConnectionProvider.PooledConnection in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method fixedPoolTwoAcquire.
@Test
void fixedPoolTwoAcquire() throws Exception {
final ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
int echoServerPort = SocketUtils.findAvailableTcpPort();
TcpClientTests.EchoServer echoServer = new TcpClientTests.EchoServer(echoServerPort);
EventLoopGroup group = new NioEventLoopGroup(2);
java.util.concurrent.Future<?> f1 = null;
java.util.concurrent.Future<?> f2 = null;
Future<?> sf = null;
try (AddressResolverGroup<?> resolver = NameResolverProvider.builder().build().newNameResolverGroup(TcpResources.get(), true)) {
final InetSocketAddress address = InetSocketAddress.createUnresolved("localhost", echoServerPort);
ConnectionProvider pool = ConnectionProvider.create("fixedPoolTwoAcquire", 2);
Supplier<? extends SocketAddress> remoteAddress = () -> address;
ConnectionObserver observer = ConnectionObserver.emptyListener();
ClientTransportConfigImpl config = new ClientTransportConfigImpl(group, pool, Collections.emptyMap(), remoteAddress, resolver);
// fail a couple
StepVerifier.create(pool.acquire(config, observer, remoteAddress, config.resolverInternal())).verifyErrorMatches(msg -> msg.getCause() instanceof ConnectException);
StepVerifier.create(pool.acquire(config, observer, remoteAddress, config.resolverInternal())).verifyErrorMatches(msg -> msg.getCause() instanceof ConnectException);
// start the echo server
f1 = service.submit(echoServer);
Thread.sleep(100);
// acquire 2
final PooledConnection c1 = (PooledConnection) pool.acquire(config, observer, remoteAddress, config.resolverInternal()).block(Duration.ofSeconds(30));
assertThat(c1).isNotNull();
final PooledConnection c2 = (PooledConnection) pool.acquire(config, observer, remoteAddress, config.resolverInternal()).block(Duration.ofSeconds(30));
assertThat(c2).isNotNull();
// make room for 1 more
c2.disposeNow();
final PooledConnection c3 = (PooledConnection) pool.acquire(config, observer, remoteAddress, config.resolverInternal()).block(Duration.ofSeconds(30));
assertThat(c3).isNotNull();
// next one will block until a previous one is released
long start = System.currentTimeMillis();
sf = service.schedule(() -> c1.onStateChange(c1, ConnectionObserver.State.DISCONNECTING), 500, TimeUnit.MILLISECONDS);
final PooledConnection c4 = (PooledConnection) pool.acquire(config, observer, remoteAddress, config.resolverInternal()).block(Duration.ofSeconds(30));
assertThat(c4).isNotNull();
long end = System.currentTimeMillis();
assertThat(end - start).as("channel4 acquire blocked until channel1 released").isGreaterThanOrEqualTo(500);
c3.onStateChange(c3, ConnectionObserver.State.DISCONNECTING);
c4.onStateChange(c4, ConnectionObserver.State.DISCONNECTING);
assertThat(c1).isEqualTo(c4);
assertThat(c1.pool).isEqualTo(c2.pool).isEqualTo(c3.pool).isEqualTo(c4.pool);
InstrumentedPool<PooledConnection> defaultPool = c1.pool;
CountDownLatch latch = new CountDownLatch(1);
f2 = service.submit(() -> {
while (defaultPool.metrics().acquiredSize() > 0) {
LockSupport.parkNanos(100);
}
latch.countDown();
});
assertThat(latch.await(5, TimeUnit.SECONDS)).as("activeConnections fully released").isTrue();
} finally {
service.shutdownNow();
echoServer.close();
group.shutdownGracefully().get(5, TimeUnit.SECONDS);
assertThat(f1).isNotNull();
assertThat(f1.get()).isNull();
assertThat(f2).isNotNull();
assertThat(f2.get()).isNull();
assertThat(sf).isNotNull();
assertThat(sf.get()).isNull();
}
}
use of reactor.netty.resources.DefaultPooledConnectionProvider.PooledConnection in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method testIssue673_TimeoutException.
@Test
void testIssue673_TimeoutException() throws InterruptedException {
DisposableServer server = TcpServer.create().port(0).handle((in, out) -> out.sendString(Mono.just("test").delayElement(Duration.ofMillis(100)))).wiretap(true).bindNow();
DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue673_TimeoutException").maxConnections(1).pendingAcquireMaxCount(4).pendingAcquireTimeout(Duration.ofMillis(10)).build();
CountDownLatch latch = new CountDownLatch(2);
try {
AtomicReference<InstrumentedPool<PooledConnection>> pool = new AtomicReference<>();
List<? extends Signal<? extends Connection>> list = Flux.range(0, 5).flatMapDelayError(i -> TcpClient.create(provider).port(server.port()).doOnConnected(conn -> {
ConcurrentMap<PooledConnectionProvider.PoolKey, InstrumentedPool<PooledConnection>> pools = provider.channelPools;
pool.set(pools.get(pools.keySet().toArray()[0]));
}).doOnDisconnected(conn -> latch.countDown()).handle((in, out) -> in.receive().then()).wiretap(true).connect().materialize(), 256, 32).collectList().doFinally(fin -> latch.countDown()).block(Duration.ofSeconds(30));
assertThat(latch.await(30, TimeUnit.SECONDS)).as("latch 30s").isTrue();
assertThat(list).isNotNull().hasSize(5);
int onNext = 0;
int onError = 0;
String msg = "Pool#acquire(Duration) has been pending for more than the configured timeout of 10ms";
for (int i = 0; i < 5; i++) {
Signal<? extends Connection> signal = list.get(i);
if (signal.isOnNext()) {
onNext++;
} else if (signal.getThrowable() instanceof TimeoutException && msg.equals(signal.getThrowable().getMessage())) {
onError++;
}
}
assertThat(onNext).isEqualTo(1);
assertThat(onError).isEqualTo(4);
assertThat(pool.get().metrics().acquiredSize()).as("currently acquired").isEqualTo(0);
assertThat(pool.get().metrics().idleSize()).as("currently idle").isEqualTo(0);
} finally {
server.disposeNow();
provider.dispose();
}
}
use of reactor.netty.resources.DefaultPooledConnectionProvider.PooledConnection in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method testIssue951_MaxPendingAcquire.
@Test
void testIssue951_MaxPendingAcquire() throws InterruptedException {
DisposableServer server = TcpServer.create().port(0).handle((in, out) -> out.sendString(Mono.just("test").delayElement(Duration.ofMillis(100)))).wiretap(true).bindNow();
DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue951_MaxPendingAcquire").maxConnections(1).pendingAcquireTimeout(Duration.ofMillis(30)).pendingAcquireMaxCount(1).build();
CountDownLatch latch = new CountDownLatch(2);
try {
AtomicReference<InstrumentedPool<PooledConnection>> pool = new AtomicReference<>();
List<? extends Signal<? extends Connection>> list = Flux.range(0, 3).flatMapDelayError(i -> TcpClient.create(provider).port(server.port()).doOnConnected(conn -> {
ConcurrentMap<PooledConnectionProvider.PoolKey, InstrumentedPool<PooledConnection>> pools = provider.channelPools;
pool.set(pools.get(pools.keySet().toArray()[0]));
}).doOnDisconnected(conn -> latch.countDown()).handle((in, out) -> in.receive().then()).wiretap(true).connect().materialize(), 256, 32).collectList().doFinally(fin -> latch.countDown()).block(Duration.ofSeconds(30));
assertThat(latch.await(30, TimeUnit.SECONDS)).as("latch 30s").isTrue();
assertThat(list).isNotNull().hasSize(3);
int onNext = 0;
int onErrorTimeout = 0;
int onErrorPendingAcquire = 0;
String msg1 = "Pool#acquire(Duration) has been pending for more than the configured timeout of 30ms";
String msg2 = "Pending acquire queue has reached its maximum size of 1";
for (int i = 0; i < 3; i++) {
Signal<? extends Connection> signal = list.get(i);
if (signal.isOnNext()) {
onNext++;
} else if (signal.getThrowable() instanceof TimeoutException && msg1.equals(signal.getThrowable().getMessage())) {
onErrorTimeout++;
} else if (signal.getThrowable() instanceof PoolAcquirePendingLimitException && msg2.equals(signal.getThrowable().getMessage())) {
onErrorPendingAcquire++;
}
}
assertThat(onNext).isEqualTo(1);
assertThat(onErrorTimeout).isEqualTo(1);
assertThat(onErrorPendingAcquire).isEqualTo(1);
assertThat(pool.get().metrics().acquiredSize()).as("currently acquired").isEqualTo(0);
assertThat(pool.get().metrics().idleSize()).as("currently idle").isEqualTo(0);
} finally {
server.disposeNow();
provider.dispose();
}
}
Aggregations