@Test public void sameInstance() throws Exception { ClientPool pool = new ClientPool(2); assertEquals(0, pool.countAvailable()); Client client = mockClient("localhost"); IntStream.range(0, 10).forEach(i -> pool.release(client)); assertEquals(1, pool.countAvailable()); Client client2 = mockClient("google"); IntStream.range(0, 10).forEach(i -> pool.release(client2)); assertEquals(2, pool.countAvailable()); }
public Client acquire( ChannelHandlerContext ctx, ClientConfig config, Supplier<Client> clientSupplier) { return getPool(config.remote()) .values() .stream() .filter(meta -> checkClientMetaState(ctx, config, meta)) .findFirst() .map(mta -> mta.client) .orElseGet(clientSupplier); }
@Test public void releaseAndAcquire() throws Exception { ClientPool pool = new ClientPool(2); assertEquals(0, pool.countAvailable()); IntStream.range(0, 10).forEach(i -> pool.release(mockClient("localhost"))); assertEquals(2, pool.countAvailable()); IntStream.range(0, 10).forEach(i -> pool.release(mockClient("google"))); assertEquals(4, pool.countAvailable()); IntStream.range(0, 2) .forEach( i -> pool.acquire( mockFrontContext(), mockConfig("localhost"), () -> mockClient("localhost"))); assertEquals(2, pool.countAvailable()); IntStream.range(0, 2) .forEach( i -> pool.acquire( mockFrontContext(), mockConfig("google"), () -> mockClient("localhost"))); assertEquals(0, pool.countAvailable()); }
public ProxyClientFactory(ApplicationState state) { super(state.tracing()); this.clientPool = new ClientPool(state.config().getClientPoolSize()); }
@Override public Client getClient(ChannelHandlerContext ctx, ClientConfig config) { Client client = getHandlerClient(ctx, config.remote()) .orElseGet(() -> clientPool.acquire(ctx, config, () -> createClient(ctx, config))); updateChannelAttr(ctx, config.remote(), client); return client; } }
@Override public Client createClient(ChannelHandlerContext ctx, ClientConfig config) { ClientState clientState = new ClientState(channelConfig(ctx), config); ClientChannelInitializer clientChannelInit = new ClientChannelInitializer(clientState, () -> new ProxyBackendHandler(ctx), getTracing()); ClientConnectionManager connManager = new ClientConnectionManager(clientState, clientChannelInit); Client client = new Client(clientState, connManager); ctx.channel().closeFuture().addListener(f -> clientPool.release(client)); log.debug("creating client"); return client; }
public void release(Client client) { log.debug("recycling client {}", client); client.recycle(); ConcurrentMap<Client, Meta> pool = getPool(client.remoteAddress()); if (pool.size() < maxSizePerAddress && !pool.containsKey(client)) { log.debug("releasing client to pool {}", client); pool.put(client, new Meta(client)); } else { Meta meta = pool.get(client); if (meta != null) { log.debug("setting client available in pool {}", client); meta.available.set(true); } } }
@Test public void releaseAndAcquireThreadSafety() throws Exception { // given a client pool ClientPool pool = new ClientPool(25); // when acquire and release occurs many times on multiple threads List<Completable> completables = IntStream.range(0, 1000) .mapToObj(index -> acquireAndReleaseAsync(pool)) .collect(Collectors.toList()); // then an exception is NOT thrown Completable.merge(completables).blockingAwait(); }
private Observable<Client> acquireAsync(ClientPool pool) { return Observable.<Client>create( emitter -> { Client client = pool.acquire( mockFrontContext(), mockConfig("localhost"), () -> mockClient("localhost")); log.debug("acquiring client"); emitter.onNext(client); emitter.onComplete(); }) .subscribeOn(Schedulers.io()) .compose(new RandomInterval<>(100)); // wait randomly up to 100ms }
private Completable releaseAsync(ClientPool pool, Client client) { return Completable.create( emitter -> { log.debug("releasing client"); pool.release(client); emitter.onComplete(); }) .subscribeOn(Schedulers.io()); }