Java Code Examples for java.util.concurrent.CompletableFuture#thenComposeAsync()

The following examples show how to use java.util.concurrent.CompletableFuture#thenComposeAsync() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: JavaAsyncFutureBenchmark.java    From future with Apache License 2.0 5 votes vote down vote up
@Benchmark
public String flatMapPromiseN() throws InterruptedException, ExecutionException {
  CompletableFuture<String> p = new CompletableFuture<>();
  CompletableFuture<String> f = p;
  for (int i = 0; i < N.n; i++)
    f = f.thenComposeAsync(flatMapF);
  p.complete(string);
  return f.get();
}
 
Example 2
Source File: Dispatcher.java    From flink with Apache License 2.0 5 votes vote down vote up
private CompletableFuture<Void> waitForTerminatingJobManager(JobID jobId, JobGraph jobGraph, FunctionWithException<JobGraph, CompletableFuture<Void>, ?> action) {
	final CompletableFuture<Void> jobManagerTerminationFuture = getJobTerminationFuture(jobId)
		.exceptionally((Throwable throwable) -> {
			throw new CompletionException(
				new DispatcherException(
					String.format("Termination of previous JobManager for job %s failed. Cannot submit job under the same job id.", jobId),
					throwable)); });

	return jobManagerTerminationFuture.thenComposeAsync(
		FunctionUtils.uncheckedFunction((ignored) -> {
			jobManagerTerminationFutures.remove(jobId);
			return action.apply(jobGraph);
		}),
		getMainThreadExecutor());
}
 
Example 3
Source File: JavaAsyncFutureBenchmark.java    From future with Apache License 2.0 5 votes vote down vote up
@Benchmark
public String flatMapPromise() throws InterruptedException, ExecutionException {
  CompletableFuture<String> p = new CompletableFuture<String>();
  p.thenComposeAsync(flatMapF);
  p.complete(string);
  return p.get();
}
 
Example 4
Source File: GuideTests.java    From reactor-core with Apache License 2.0 5 votes vote down vote up
@Test @SuppressWarnings("unchecked")
public void introFutureHell() {
	CompletableFuture<List<String>> ids = ifhIds(); // <1>

	CompletableFuture<List<String>> result = ids.thenComposeAsync(l -> { // <2>
		Stream<CompletableFuture<String>> zip =
				l.stream().map(i -> { // <3>
					         CompletableFuture<String> nameTask = ifhName(i); // <4>
					         CompletableFuture<Integer> statTask = ifhStat(i); // <5>

					         return nameTask.thenCombineAsync(statTask, (name, stat) -> "Name " + name + " has stats " + stat); // <6>
				         });
		List<CompletableFuture<String>> combinationList = zip.collect(Collectors.toList()); // <7>
		CompletableFuture<String>[] combinationArray = combinationList.toArray(new CompletableFuture[combinationList.size()]);

		CompletableFuture<Void> allDone = CompletableFuture.allOf(combinationArray); // <8>
		return allDone.thenApply(v -> combinationList.stream()
		                                             .map(CompletableFuture::join) // <9>
		                                             .collect(Collectors.toList()));
	});

	List<String> results = result.join(); // <10>
	assertThat(results).contains(
					"Name NameJoe has stats 103",
					"Name NameBart has stats 104",
					"Name NameHenry has stats 105",
					"Name NameNicole has stats 106",
					"Name NameABSLAJNFOAJNFOANFANSF has stats 121");
}
 
Example 5
Source File: TxnSweeper.java    From pravega with Apache License 2.0 5 votes vote down vote up
@Override
public CompletableFuture<Void> handleFailedProcess(String failedHost) {
    if (!transactionMetadataTasks.isReady()) {
        return Futures.failedFuture(new IllegalStateException(getClass().getName() + " not yet ready"));
    }
    log.info("Host={}, sweeping orphaned transactions", failedHost);
    CompletableFuture<Void> delay = Futures.delayedFuture(Duration.ofMillis(2 * maxTxnTimeoutMillis), executor);
    return delay.thenComposeAsync(x -> withRetriesAsync(() -> sweepOrphanedTxnsWithoutDelay(failedHost),
            RETRYABLE_PREDICATE, Integer.MAX_VALUE, executor));
}
 
Example 6
Source File: TxnSweeper.java    From pravega with Apache License 2.0 5 votes vote down vote up
@Override
public CompletableFuture<Void> sweepFailedProcesses(Supplier<Set<String>> activeHosts) {
    if (!transactionMetadataTasks.isReady()) {
        return Futures.failedFuture(new IllegalStateException(getClass().getName() + " not yet ready"));
    }
    CompletableFuture<Set<String>> hostsOwningTxns = withRetriesAsync(streamMetadataStore::listHostsOwningTxn,
            RETRYABLE_PREDICATE, Integer.MAX_VALUE, executor);
    return hostsOwningTxns.thenComposeAsync(index -> {
        index.removeAll(activeHosts.get());
        log.info("Failed hosts {} have orphaned tasks", index);
        return Futures.allOf(index.stream().map(this::handleFailedProcess).collect(Collectors.toList()));
    }, executor);
}
 
Example 7
Source File: InMemoryDurableDataLog.java    From pravega with Apache License 2.0 5 votes vote down vote up
@Override
public CompletableFuture<LogAddress> append(CompositeArrayView data, Duration timeout) {
    ensurePreconditions();
    if (data.getLength() > getWriteSettings().getMaxWriteLength()) {
        return Futures.failedFuture(new WriteTooLongException(data.getLength(), getWriteSettings().getMaxWriteLength()));
    }

    CompletableFuture<LogAddress> result;
    try {
        Entry entry = new Entry(data);
        synchronized (this.entries) {
            entry.sequenceNumber = this.offset;
            this.entries.add(entry, clientId);

            // Only update internals after a successful add.
            this.offset += entry.data.length;
        }
        result = CompletableFuture.completedFuture(new InMemoryLogAddress(entry.sequenceNumber));
    } catch (Throwable ex) {
        return Futures.failedFuture(ex);
    }

    Duration delay = this.appendDelayProvider.get();
    if (delay.compareTo(Duration.ZERO) <= 0) {
        // No delay, execute right away.
        return result;
    } else {
        // Schedule the append after the given delay.
        return result.thenComposeAsync(
                logAddress -> Futures.delayedFuture(delay, this.executorService)
                                     .thenApply(ignored -> logAddress),
                this.executorService);
    }
}
 
Example 8
Source File: Dispatcher.java    From flink with Apache License 2.0 5 votes vote down vote up
private CompletableFuture<Void> waitForTerminatingJobManager(JobID jobId, JobGraph jobGraph, FunctionWithException<JobGraph, CompletableFuture<Void>, ?> action) {
	final CompletableFuture<Void> jobManagerTerminationFuture = getJobTerminationFuture(jobId)
		.exceptionally((Throwable throwable) -> {
			throw new CompletionException(
				new DispatcherException(
					String.format("Termination of previous JobManager for job %s failed. Cannot submit job under the same job id.", jobId),
					throwable)); });

	return jobManagerTerminationFuture.thenComposeAsync(
		FunctionUtils.uncheckedFunction((ignored) -> {
			jobManagerTerminationFutures.remove(jobId);
			return action.apply(jobGraph);
		}),
		getMainThreadExecutor());
}
 
Example 9
Source File: SegmentAggregator.java    From pravega with Apache License 2.0 5 votes vote down vote up
/**
 * Flushes the contents of the Aggregator exactly once to the Storage in a 'normal' mode (where it does not need to
 * do any reconciliation).
 *
 * @param timer Timer for the operation.
 * @return A CompletableFuture that, when completed, will contain the result from the flush operation.
 */
private CompletableFuture<WriterFlushResult> flushOnce(TimeoutTimer timer) {
    boolean hasDelete = this.hasDeletePending.get();
    boolean hasMerge = this.mergeTransactionCount.get() > 0;
    boolean hasSeal = this.hasSealPending.get();
    boolean hasTruncate = this.truncateCount.get() > 0;
    long traceId = LoggerHelpers.traceEnterWithContext(log, this.traceObjectId, "flushOnce", this.operations.size(),
            this.mergeTransactionCount, hasSeal, hasTruncate, hasDelete);

    CompletableFuture<WriterFlushResult> result;
    if (hasDelete) {
        // If we have a Deletes, simply delete the Segment and move on. No other operation matters now.
        result = deleteSegment(timer);
    } else if (hasSeal || hasMerge || hasTruncate) {
        // If we have a Seal, Merge or Truncate Pending, flush everything until we reach that operation.
        result = flushFully(timer);
        if (hasMerge) {
            // If we have a merge, do it after we flush fully.
            result = result.thenComposeAsync(flushResult -> mergeIfNecessary(flushResult, timer), this.executor);
        }

        if (hasSeal) {
            // If we have a seal, do it after every other operation.
            result = result.thenComposeAsync(flushResult -> sealIfNecessary(flushResult, timer), this.executor);
        }
    } else {
        // Otherwise, just flush the excess as long as we have something to flush.
        result = flushExcess(timer);
    }

    if (log.isTraceEnabled()) {
        result = result.thenApply(r -> {
            LoggerHelpers.traceLeave(log, this.traceObjectId, "flushOnce", traceId, r);
            return r;
        });
    }

    return result;
}
 
Example 10
Source File: AnnotatedService.java    From armeria with Apache License 2.0 4 votes vote down vote up
/**
 * Executes the service method in different ways regarding its return type and whether the request is
 * required to be aggregated. If the return type of the method is not a {@link CompletionStage} or
 * {@link HttpResponse}, it will be executed in the blocking task executor.
 */
private CompletionStage<HttpResponse> serve0(ServiceRequestContext ctx, HttpRequest req) {
    ctx.logBuilder().name(serviceName(), methodName());

    final CompletableFuture<AggregatedHttpRequest> f;
    if (AggregationStrategy.aggregationRequired(aggregationStrategy, req)) {
        f = req.aggregate();
    } else {
        f = CompletableFuture.completedFuture(null);
    }

    ctx.mutateAdditionalResponseHeaders(mutator -> mutator.add(defaultHttpHeaders));
    ctx.mutateAdditionalResponseTrailers(mutator -> mutator.add(defaultHttpTrailers));

    switch (responseType) {
        case HTTP_RESPONSE:
            final Function<AggregatedHttpRequest, HttpResponse> httpResponseApplyFunction =
                    msg -> new ExceptionFilteredHttpResponse(
                            ctx, req, (HttpResponse) invoke(ctx, req, msg), exceptionHandler);
            if (useBlockingTaskExecutor) {
                return f.thenApplyAsync(httpResponseApplyFunction, ctx.blockingTaskExecutor());
            } else {
                return f.thenApply(httpResponseApplyFunction);
            }

        case COMPLETION_STAGE:
            final CompletableFuture<?> composedFuture;
            if (useBlockingTaskExecutor) {
                composedFuture = f.thenComposeAsync(msg -> toCompletionStage(invoke(ctx, req, msg)),
                                                    ctx.blockingTaskExecutor());
            } else {
                composedFuture = f.thenCompose(msg -> toCompletionStage(invoke(ctx, req, msg)));
            }
            return composedFuture.handle(
                    (result, cause) -> {
                        if (cause != null) {
                            return handleExceptionWithContext(exceptionHandler, ctx, req, cause);
                        }
                        return convertResponse(ctx, req, null, result, HttpHeaders.of());
                    });

        default:
            final Function<AggregatedHttpRequest, HttpResponse> defaultApplyFunction =
                    msg -> convertResponse(ctx, req, null, invoke(ctx, req, msg), HttpHeaders.of());
            if (useBlockingTaskExecutor) {
                return f.thenApplyAsync(defaultApplyFunction, ctx.blockingTaskExecutor());
            } else {
                return f.thenApply(defaultApplyFunction);
            }
    }
}
 
Example 11
Source File: StreamSegmentContainer.java    From pravega with Apache License 2.0 4 votes vote down vote up
/**
 * Gets the values of the given (Core and Extended) Attribute Ids for the given segment.
 *
 * @param segmentMetadata The SegmentMetadata for the Segment to retrieve attribute values for.
 * @param attributeIds    A Collection of AttributeIds to retrieve.
 * @param cache           If true, any Extended Attribute value that is not present in the SegmentMetadata cache will
 *                        be added to that (using a conditional updateAttributes() call) before completing.
 * @param timer           Timer for the operation.
 * @return A CompletableFuture that, when completed normally, will contain the desired result. If the operation failed,
 * it will be completed with the appropriate exception. If cache==true and the conditional call to updateAttributes()
 * could not be completed because of a conflicting update, it will be failed with BadAttributeUpdateException, in which
 * case a retry is warranted.
 */
private CompletableFuture<Map<UUID, Long>> getAndCacheAttributes(SegmentMetadata segmentMetadata, Collection<UUID> attributeIds, boolean cache, TimeoutTimer timer) {
    // Collect Core Attributes and Cached Extended Attributes.
    Map<UUID, Long> result = new HashMap<>();
    Map<UUID, Long> metadataAttributes = segmentMetadata.getAttributes();
    ArrayList<UUID> extendedAttributeIds = new ArrayList<>();
    attributeIds.forEach(attributeId -> {
        Long v = metadataAttributes.get(attributeId);
        if (v != null) {
            // This attribute is cached in the Segment Metadata, even if it has a value equal to Attributes.NULL_ATTRIBUTE_VALUE.
            result.put(attributeId, v);
        } else if (!Attributes.isCoreAttribute(attributeId)) {
            extendedAttributeIds.add(attributeId);
        }
    });

    if (extendedAttributeIds.isEmpty()) {
        // Nothing to lookup in the Attribute Index, so bail out early.
        return CompletableFuture.completedFuture(result);
    }

    // Collect remaining Extended Attributes.
    CompletableFuture<Map<UUID, Long>> r = this.attributeIndex
            .forSegment(segmentMetadata.getId(), timer.getRemaining())
            .thenComposeAsync(idx -> idx.get(extendedAttributeIds, timer.getRemaining()), this.executor)
            .thenApplyAsync(extendedAttributes -> {
                if (extendedAttributeIds.size() == extendedAttributes.size()) {
                    // We found a value for each Attribute Id. Nothing more to do.
                    return extendedAttributes;
                }

                // Insert a NULL_ATTRIBUTE_VALUE for each missing value.
                Map<UUID, Long> allValues = new HashMap<>(extendedAttributes);
                extendedAttributeIds.stream()
                                    .filter(id -> !extendedAttributes.containsKey(id))
                                    .forEach(id -> allValues.put(id, Attributes.NULL_ATTRIBUTE_VALUE));
                return allValues;
            }, this.executor);

    if (cache && !segmentMetadata.isSealed()) {
        // Add them to the cache if requested.
        r = r.thenComposeAsync(extendedAttributes -> {
            // Update the in-memory Segment Metadata using a special update (AttributeUpdateType.None, which should
            // complete if the attribute is not currently set). If it has some value, then a concurrent update
            // must have changed it and we cannot update anymore.
            List<AttributeUpdate> updates = extendedAttributes
                    .entrySet().stream()
                    .map(e -> new AttributeUpdate(e.getKey(), AttributeUpdateType.None, e.getValue()))
                    .collect(Collectors.toList());

            // We need to make sure not to update attributes via updateAttributes() as that method may indirectly
            // invoke this one again.
            return this.durableLog.add(new UpdateAttributesOperation(segmentMetadata.getId(), updates), timer.getRemaining())
                                  .thenApply(v -> extendedAttributes);
        }, this.executor);
    }

    // Compile the final result.
    return r.thenApply(extendedAttributes -> {
        result.putAll(extendedAttributes);
        return result;
    });
}
 
Example 12
Source File: CompletableFutureTest.java    From j2objc with Apache License 2.0 4 votes vote down vote up
public <T,U> CompletableFuture<U> thenCompose
    (CompletableFuture<T> f,
     Function<? super T,? extends CompletionStage<U>> a) {
    return f.thenComposeAsync(a, new ThreadExecutor());
}
 
Example 13
Source File: EvalOnDartLibrary.java    From flutter-intellij with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
public CompletableFuture<Instance> getInstance(CompletableFuture<InstanceRef> instanceFuture, InspectorService.ObjectGroup isAlive) {
  return instanceFuture.thenComposeAsync((instance) -> getInstance(instance, isAlive));
}
 
Example 14
Source File: EvalOnDartLibrary.java    From flutter-intellij with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
public CompletableFuture<Instance> getInstance(CompletableFuture<InstanceRef> instanceFuture, InspectorService.ObjectGroup isAlive) {
  return instanceFuture.thenComposeAsync((instance) -> getInstance(instance, isAlive));
}
 
Example 15
Source File: CompletableFutureTest.java    From j2objc with Apache License 2.0 4 votes vote down vote up
public <T,U> CompletableFuture<U> thenCompose
    (CompletableFuture<T> f,
     Function<? super T,? extends CompletionStage<U>> a) {
    return f.thenComposeAsync(a);
}
 
Example 16
Source File: SimpleResolver.java    From dnsjava with BSD 2-Clause "Simplified" License 4 votes vote down vote up
CompletableFuture<Message> sendAsync(Message query, boolean forceTcp) {
  int qid = query.getHeader().getID();
  byte[] out = query.toWire(Message.MAXLENGTH);
  int udpSize = maxUDPSize(query);
  boolean tcp = forceTcp || out.length > udpSize;
  log.debug(
      "Sending {}/{}, id={} to {}/{}:{}",
      query.getQuestion().getName(),
      Type.string(query.getQuestion().getType()),
      qid,
      tcp ? "tcp" : "udp",
      address.getAddress().getHostAddress(),
      address.getPort());
  log.trace("Query:\n{}", query);

  CompletableFuture<byte[]> result;
  if (tcp) {
    result = NioTcpClient.sendrecv(localAddress, address, query, out, timeoutValue);
  } else {
    result = NioUdpClient.sendrecv(localAddress, address, out, udpSize, timeoutValue);
  }

  return result.thenComposeAsync(
      in -> {
        CompletableFuture<Message> f = new CompletableFuture<>();

        // Check that the response is long enough.
        if (in.length < Header.LENGTH) {
          f.completeExceptionally(new WireParseException("invalid DNS header - too short"));
          return f;
        }

        // Check that the response ID matches the query ID. We want
        // to check this before actually parsing the message, so that
        // if there's a malformed response that's not ours, it
        // doesn't confuse us.
        int id = ((in[0] & 0xFF) << 8) + (in[1] & 0xFF);
        if (id != qid) {
          f.completeExceptionally(
              new WireParseException("invalid message id: expected " + qid + "; got id " + id));
          return f;
        }

        Message response;
        try {
          response = parseMessage(in);
        } catch (WireParseException e) {
          f.completeExceptionally(e);
          return f;
        }

        // validate name, class and type (rfc5452#section-9.1)
        if (!query.getQuestion().getName().equals(response.getQuestion().getName())) {
          f.completeExceptionally(
              new WireParseException(
                  "invalid name in message: expected "
                      + query.getQuestion().getName()
                      + "; got "
                      + response.getQuestion().getName()));
          return f;
        }

        if (query.getQuestion().getDClass() != response.getQuestion().getDClass()) {
          f.completeExceptionally(
              new WireParseException(
                  "invalid class in message: expected "
                      + DClass.string(query.getQuestion().getDClass())
                      + "; got "
                      + DClass.string(response.getQuestion().getDClass())));
          return f;
        }

        if (query.getQuestion().getType() != response.getQuestion().getType()) {
          f.completeExceptionally(
              new WireParseException(
                  "invalid type in message: expected "
                      + Type.string(query.getQuestion().getType())
                      + "; got "
                      + Type.string(response.getQuestion().getType())));
          return f;
        }

        verifyTSIG(query, response, in, tsig);
        if (!tcp && !ignoreTruncation && response.getHeader().getFlag(Flags.TC)) {
          log.debug("Got truncated response for id {}, retrying via TCP", qid);
          log.trace("Truncated response: {}", response);
          return sendAsync(query, true);
        }

        response.setResolver(this);
        f.complete(response);
        return f;
      });
}
 
Example 17
Source File: CompletableFutureTest.java    From openjdk-jdk9 with GNU General Public License v2.0 4 votes vote down vote up
public <T,U> CompletableFuture<U> thenCompose
    (CompletableFuture<T> f,
     Function<? super T,? extends CompletionStage<U>> a) {
    return f.thenComposeAsync(a, new ThreadExecutor());
}
 
Example 18
Source File: CompletableFutureTest.java    From openjdk-jdk9 with GNU General Public License v2.0 4 votes vote down vote up
public <T,U> CompletableFuture<U> thenCompose
    (CompletableFuture<T> f,
     Function<? super T,? extends CompletionStage<U>> a) {
    return f.thenComposeAsync(a);
}
 
Example 19
Source File: FutureUtils.java    From flink with Apache License 2.0 3 votes vote down vote up
/**
 * This function takes a {@link CompletableFuture} and a function to compose with this future. If the input future
 * is already done, this function returns {@link CompletableFuture#thenCompose(Function)}. Otherwise, the return
 * value is {@link CompletableFuture#thenComposeAsync(Function, Executor)} with the given executor.
 *
 * @param completableFuture the completable future for which we want to compose.
 * @param executor the executor to run the compose function if the future is not yet done.
 * @param composeFun the function to compose.
 * @param <IN> type of the input future.
 * @param <OUT> type of the output future.
 * @return a completable future that is a composition of the input future and the function.
 */
public static <IN, OUT> CompletableFuture<OUT> thenComposeAsyncIfNotDone(
	CompletableFuture<IN> completableFuture,
	Executor executor,
	Function<? super IN, ? extends CompletionStage<OUT>> composeFun) {
	return completableFuture.isDone() ?
		completableFuture.thenCompose(composeFun) :
		completableFuture.thenComposeAsync(composeFun, executor);
}
 
Example 20
Source File: FutureUtils.java    From flink with Apache License 2.0 3 votes vote down vote up
/**
 * This function takes a {@link CompletableFuture} and a function to compose with this future. If the input future
 * is already done, this function returns {@link CompletableFuture#thenCompose(Function)}. Otherwise, the return
 * value is {@link CompletableFuture#thenComposeAsync(Function, Executor)} with the given executor.
 *
 * @param completableFuture the completable future for which we want to compose.
 * @param executor the executor to run the compose function if the future is not yet done.
 * @param composeFun the function to compose.
 * @param <IN> type of the input future.
 * @param <OUT> type of the output future.
 * @return a completable future that is a composition of the input future and the function.
 */
public static <IN, OUT> CompletableFuture<OUT> thenComposeAsyncIfNotDone(
	CompletableFuture<IN> completableFuture,
	Executor executor,
	Function<? super IN, ? extends CompletionStage<OUT>> composeFun) {
	return completableFuture.isDone() ?
		completableFuture.thenCompose(composeFun) :
		completableFuture.thenComposeAsync(composeFun, executor);
}