diff --git a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index 85b4cca5..38530b0b 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -2132,6 +2132,252 @@ public static CompletableFuture allTupleOf0(true, wrapFunctions(executor, v, fns))); } + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, + long timeout, TimeUnit unit, Function fn1, Function fn2) { + return tupleMApplyMostSuccessAsync(cf, AsyncPoolHolder.ASYNC_POOL, timeout, unit, fn1, fn2); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, Executor executor, long timeout, TimeUnit unit, Function fn1, Function fn2) { + requireNonNull(executor, "executor is null"); + requireNonNull(unit, "unit is null"); + requireArrayAndEleNonNull("fn", fn1, fn2); + + return f_toCf(cf).thenCompose(v -> mostTupleOfSuccess0(executor, timeout, unit, CompletableFuture.supplyAsync(() -> fn1.apply(v), executor), CompletableFuture.supplyAsync(() -> fn2.apply(v), executor))); + } + + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, + long timeout, TimeUnit unit, Function fn1, Function fn2, Function fn3) { + return tupleMApplyMostSuccessAsync(cf, AsyncPoolHolder.ASYNC_POOL, timeout, unit, fn1, fn2, fn3); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, Executor executor, long timeout, TimeUnit unit, Function fn1, Function fn2, Function fn3) { + requireNonNull(executor, "executor is null"); + requireNonNull(unit, "unit is null"); + requireArrayAndEleNonNull("fn", fn1, fn2, fn3); + + return f_toCf(cf).thenCompose(v -> mostTupleOfSuccess0(executor, timeout, unit, CompletableFuture.supplyAsync(() -> fn1.apply(v), executor), + CompletableFuture.supplyAsync(() -> fn2.apply(v), executor), CompletableFuture.supplyAsync(() -> fn3.apply(v), executor))); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param fn4 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, long timeout, TimeUnit unit, Function fn1, + Function fn2, Function fn3, Function fn4) { + return tupleMApplyMostSuccessAsync(cf, AsyncPoolHolder.ASYNC_POOL, timeout, unit, fn1, fn2, fn3, fn4); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param fn4 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, Executor executor, long timeout, TimeUnit unit, Function fn1, + Function fn2, Function fn3, Function fn4) { + requireNonNull(executor, "executor is null"); + requireNonNull(unit, "unit is null"); + requireArrayAndEleNonNull("fn", fn1, fn2, fn3, fn4); + + return f_toCf(cf).thenCompose(v -> mostTupleOfSuccess0(executor, timeout, unit, CompletableFuture.supplyAsync(() -> fn1.apply(v), executor), + CompletableFuture.supplyAsync(() -> fn2.apply(v), executor), CompletableFuture.supplyAsync(() -> fn3.apply(v), executor), CompletableFuture.supplyAsync(() -> fn4.apply(v), executor))); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param fn4 the function to use to compute the values of the returned CompletableFuture + * @param fn5 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, long timeout, TimeUnit unit, Function fn1, + Function fn2, Function fn3, Function fn4, + Function fn5) { + return tupleMApplyMostSuccessAsync(cf, AsyncPoolHolder.ASYNC_POOL, timeout, unit, fn1, fn2, fn3, fn4, fn5); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @param fn1 the function to use to compute the values of the returned CompletableFuture + * @param fn2 the function to use to compute the values of the returned CompletableFuture + * @param fn3 the function to use to compute the values of the returned CompletableFuture + * @param fn4 the function to use to compute the values of the returned CompletableFuture + * @param fn5 the function to use to compute the values of the returned CompletableFuture + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @param the function return type + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMApplyMostSuccessAsync( + CompletionStage cf, Executor executor, long timeout, TimeUnit unit, Function fn1, + Function fn2, Function fn3, Function fn4, + Function fn5) { + requireNonNull(executor, "executor is null"); + requireNonNull(unit, "unit is null"); + requireArrayAndEleNonNull("fn", fn1, fn2, fn3, fn4, fn5); + + return f_toCf(cf).thenCompose(v -> mostTupleOfSuccess0(executor, timeout, unit, CompletableFuture.supplyAsync(() -> fn1.apply(v), executor), + CompletableFuture.supplyAsync(() -> fn2.apply(v), executor), CompletableFuture.supplyAsync(() -> fn3.apply(v), executor), + CompletableFuture.supplyAsync(() -> fn4.apply(v), executor), CompletableFuture.supplyAsync(() -> fn5.apply(v), executor))); + } + + /** * Returns a new CompletableFuture that, when the given stage completes normally, * is executed using the CompletableFuture's default asynchronous execution facility, diff --git a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java index 9590ac62..045adc02 100644 --- a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java +++ b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java @@ -822,6 +822,45 @@ void test_tupleMSupplyMostSuccessAsync() throws Exception { assertEquals(Tuple5.of(n, s, d, anotherN, n + n), tupleMSupplyMostSuccessAsync(defaultExecutor(), 100, TimeUnit.MILLISECONDS, supplier_n, supplier_s, supplier_d, supplier_an, supplier_nn).get()); } + + @Test + void test_tupleMApplyMostSuccessAsync() throws Exception { + final CompletableFuture completed = completedFuture(n); + final Function function_n = (x) -> { + sleep(100); + return n; + }; + + final Function function_s = (x) -> { + sleep(100); + return s; + }; + + final Function function_d = (x) -> { + sleep(100); + return d; + }; + final Function function_an = (x) -> { + sleep(100); + return anotherN; + }; + final Function function_nn = (x) -> { + sleep(100); + return n + n; + }; + assertEquals(Tuple2.of(n, s), tupleMApplyMostSuccessAsync(completed, 100, TimeUnit.MILLISECONDS, function_n, function_s).get()); + assertEquals(Tuple2.of(n, s), tupleMApplyMostSuccessAsync(completed, defaultExecutor(), 100, TimeUnit.MILLISECONDS, function_n, function_s).get()); + + assertEquals(Tuple3.of(n, s, d), tupleMApplyMostSuccessAsync(completed, 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d).get()); + assertEquals(Tuple3.of(n, s, d), tupleMApplyMostSuccessAsync(completed, defaultExecutor(), 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d).get()); + + assertEquals(Tuple4.of(n, s, d, anotherN), tupleMApplyMostSuccessAsync(completed, 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d, function_an).get()); + assertEquals(Tuple4.of(n, s, d, anotherN), tupleMApplyMostSuccessAsync(completed, defaultExecutor(), 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d, function_an).get()); + + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), tupleMApplyMostSuccessAsync(completed, 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d, function_an, function_nn).get()); + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), tupleMApplyMostSuccessAsync(completed, defaultExecutor(), 100, TimeUnit.MILLISECONDS, function_n, function_s, function_d, function_an, function_nn).get()); + } + @Test void test_thenTupleMApplyAsync() throws Exception { final CompletableFuture completed = completedFuture(n);