@Override public <U> DefaultConnectionFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) { return adopt(delegate.handle(fn)); }
@Override public <U> Task<U> handle(final BiFunction<? super T, Throwable, ? extends U> fn) { final BiFunction<? super T, Throwable, ? extends U> wrap = TaskContext.wrap(fn); if (defaultExecutor != null) { return from(super.handleAsync(wrap, defaultExecutor)); } return from(super.handle(wrap)); }
@Override public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) { return wrap(super.handle(fn)); }
private void doCleanup() { final List<CompletableFuture<Void>> completionFutures = new ArrayList<>(downstreamSubscriptions.size()); downstreamSubscriptions.forEach(s -> { s.abort(); final CompletableFuture<Void> future = s.completionFuture(); completionFutures.add(future); }); downstreamSubscriptions.clear(); final CompletableFuture<Void> allDoneFuture = CompletableFuture.allOf( completionFutures.toArray(EMPTY_FUTURES)); allDoneFuture.handle((unused1, unused2) -> { signals.clear(); return null; }); } }
@Override public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) { return ctx.makeContextAware(super.handle(ctx.makeContextAware(fn))); }
@Override public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) { return wrap(orderedFuture().handle(fn)); }
/** * Aggregates this response. The returned {@link CompletableFuture} will be notified when the content and * the trailing headers of the response are received fully. {@link AggregatedHttpMessage#content()} will * return a pooled object, and the caller must ensure to release it. If you don't know what this means, * use {@link #aggregate()}. */ default CompletableFuture<AggregatedHttpMessage> aggregateWithPooledObjects(ByteBufAllocator alloc) { requireNonNull(alloc, "alloc"); final CompletableFuture<AggregatedHttpMessage> future = new CompletableFuture<>(); final HttpResponseAggregator aggregator = new HttpResponseAggregator(future, alloc); completionFuture().handle(aggregator); subscribe(aggregator, true); return future; }
private O unlimitedExecute(ClientRequestContext ctx, I req) throws Exception { numActiveRequests.incrementAndGet(); boolean success = false; try { final O res = delegate().execute(ctx, req); res.completionFuture().handle((unused, cause) -> { numActiveRequests.decrementAndGet(); return null; }); success = true; return res; } finally { if (!success) { numActiveRequests.decrementAndGet(); } } }
/** * Aggregates this request. The returned {@link CompletableFuture} will be notified when the content and * the trailing headers of the request is received fully. {@link AggregatedHttpMessage#content()} will * return a pooled object, and the caller must ensure to release it. If you don't know what this means, * use {@link #aggregate()}. */ default CompletableFuture<AggregatedHttpMessage> aggregateWithPooledObjects(ByteBufAllocator alloc) { requireNonNull(alloc, "alloc"); final CompletableFuture<AggregatedHttpMessage> future = new CompletableFuture<>(); final HttpRequestAggregator aggregator = new HttpRequestAggregator(this, future, alloc); completionFuture().handle(aggregator); subscribe(aggregator, true); return future; }
/** * Aggregates this response. The returned {@link CompletableFuture} will be notified when the content and * the trailing headers of the response are received fully. */ default CompletableFuture<AggregatedHttpMessage> aggregate() { final CompletableFuture<AggregatedHttpMessage> future = new CompletableFuture<>(); final HttpResponseAggregator aggregator = new HttpResponseAggregator(future, null); completionFuture().handle(aggregator); subscribe(aggregator); return future; }
/** * Aggregates this request. The returned {@link CompletableFuture} will be notified when the content and * the trailing headers of the request is received fully. */ default CompletableFuture<AggregatedHttpMessage> aggregate() { final CompletableFuture<AggregatedHttpMessage> future = new CompletableFuture<>(); final HttpRequestAggregator aggregator = new HttpRequestAggregator(this, future, null); completionFuture().handle(aggregator); subscribe(aggregator); return future; }
private CompletableFuture<Void> checkAndUpdateHealthyServers() { final List<ServerConnection> checkedServers = updateServerList(); final CompletableFuture<List<Boolean>> healthCheckResults = CompletableFutures.successfulAsList( checkedServers.stream() .map(connection -> connection.healthChecker.isHealthy(connection.endpoint())) .collect(toImmutableList()), t -> false); return healthCheckResults.handle((result, thrown) -> { final ImmutableList.Builder<Endpoint> newHealthyEndpoints = ImmutableList.builder(); for (int i = 0; i < result.size(); i++) { if (result.get(i)) { newHealthyEndpoints.add(checkedServers.get(i).endpoint()); } } setEndpoints(newHealthyEndpoints.build()); return null; }); }
for (Producer<T> producer : producers) { if (producer != null) { producer.closeAsync().handle((closed, ex) -> { if (ex != null) { closeFail.compareAndSet(null, ex);
@Override HttpResponseWrapper addResponse( int id, @Nullable HttpRequest req, DecodedHttpResponse res, RequestLogBuilder logBuilder, long responseTimeoutMillis, long maxContentLength) { final HttpResponseWrapper resWrapper = super.addResponse(id, req, res, logBuilder, responseTimeoutMillis, maxContentLength); resWrapper.completionFuture().handle((unused, cause) -> { // Cancel timeout future and abort the request if it exists. resWrapper.onSubscriptionCancelled(); if (cause != null) { // Disconnect when the response has been closed with an exception because there's no way // to recover from it in HTTP/1. channel().close(); } return null; }); return resWrapper; }
/** * Sets the delegate {@link StreamMessage} which will actually publish the stream. * * @throws IllegalStateException if the delegate has been set already or * if {@link #close()} or {@link #close(Throwable)} was called already. */ protected void delegate(StreamMessage<T> delegate) { requireNonNull(delegate, "delegate"); if (!delegateUpdater.compareAndSet(this, null, delegate)) { throw new IllegalStateException("delegate set already"); } if (abortPending != 0) { delegate.abort(); } if (!completionFuture().isDone()) { delegate.completionFuture().handle((unused, cause) -> { if (cause == null) { completionFuture().complete(null); } else { completionFuture().completeExceptionally(cause); } return null; }).exceptionally(CompletionActions::log); } safeOnSubscribeToDelegate(); }
/** * Creates a {@code Future} with the given {@link java.util.concurrent.CompletableFuture}, backed by given {@link Executor} * * @param executor An {@link Executor}. * @param future A {@link java.util.concurrent.CompletableFuture}. * @param <T> Result type of the Future * @return A new {@code Future} wrapping the result of the {@link java.util.concurrent.CompletableFuture} * @throws NullPointerException if executor or future is null */ @GwtIncompatible static <T> Future<T> fromCompletableFuture(Executor executor, CompletableFuture<T> future) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(future, "future is null"); if (future.isDone() || future.isCompletedExceptionally() || future.isCancelled()) { return fromTry(Try.of(future::get).recoverWith(error -> Try.failure(error.getCause()))); } else { return run(executor, complete -> future.handle((t, err) -> complete.with((err == null) ? Try.success(t) : Try.failure(err))) ); } }
@Override public void onSubscribe(Subscription s) { assert subscription == null; subscription = s; writer.closeFuture().handle((unused, cause) -> { if (cause != null) { s.cancel(); } return null; }); try { writer.onDemand(new Runnable() { @Override public void run() { s.request(1); writer.onDemand(this); } }); } catch (Exception e) { onError(e); } }
private void doCancel() { final Subscription delegateSubscription = this.delegateSubscription; if (delegateSubscription != null) { try { delegateSubscription.cancel(); } finally { // Clear the subscriber when we become sure that the delegate will not produce events anymore. final StreamMessage<T> delegate = this.delegate; assert delegate != null; if (delegate.isComplete()) { subscription.clearSubscriber(); } else { delegate.completionFuture().handle((u1, u2) -> { subscription.clearSubscriber(); return null; }); } } } else { cancelPending = true; } }
private static HttpResponseWriter aggregateFrom(CompletableFuture<?> future, HttpHeaders headers, HttpHeaders trailingHeaders, Function<Object, HttpData> contentConverter) { final HttpResponseWriter writer = HttpResponse.streaming(); future.handle((result, cause) -> { if (cause != null) { writer.close(cause); return null; } try { final HttpData content = contentConverter.apply(result); writer.write(headers); writer.write(content); if (!trailingHeaders.isEmpty()) { writer.write(trailingHeaders); } writer.close(); } catch (Exception e) { writer.close(e); } return null; }); return writer; }
private void acquireConnectionAndExecute(ClientRequestContext ctx, Endpoint endpoint, String ipAddr, HttpRequest req, DecodedHttpResponse res) { final EventLoop eventLoop = ctx.eventLoop(); if (!eventLoop.inEventLoop()) { eventLoop.execute(() -> acquireConnectionAndExecute(ctx, endpoint, ipAddr, req, res)); return; } final String host = extractHost(ctx, req, endpoint); final int port = endpoint.port(); final SessionProtocol protocol = ctx.sessionProtocol(); final HttpChannelPool pool = factory.pool(ctx.eventLoop()); final PoolKey key = new PoolKey(host, ipAddr, port); final PooledChannel pooledChannel = pool.acquireNow(protocol, key); if (pooledChannel != null) { doExecute(pooledChannel, ctx, req, res); } else { pool.acquireLater(protocol, key).handle((newPooledChannel, cause) -> { if (cause == null) { doExecute(newPooledChannel, ctx, req, res); } else { handleEarlyRequestException(ctx, req, cause); res.close(cause); } return null; }); } }