CompletableFutureQueue
Chain async transformations on top of CompletableFuture.
CompletableFutureQueue<T, R> lets you describe an async pipeline as an ordered list of plain Functions โ built once, applied later, fully type-safe across stages.
Building a pipeline
import com.svenruppert.functional.reactive.CompletableFutureQueue;
import java.util.function.Function;
import java.util.concurrent.CompletableFuture;
Function<String, CompletableFuture<Integer>> pipeline =
CompletableFutureQueue
.define((String s) -> s.length()) // first stage
.thenCombineAsync(len -> len * 2) // next stage
.resultFunction(); // โ Function<T, CompletableFuture<R>>
pipeline
.apply("hello")
.thenAccept(System.out::println); // 10
Two things to notice:
define()is the only entry point โ it lifts a plainFunction<T, R>into the queue.- The queue itself is not applied directly. You finalize it via
resultFunction()and apply that function to your input. Building the queue and running it are deliberately separate steps so you can construct pipelines as values, pass them around, decorate them and apply them later.
Each thenCombineAsync step runs on the common ForkJoinPool.
Variants
thenCombineAsync(Function<R, N>)โ append a single stage.thenCombineAsyncFromArray(Function<R, N>[])โ append several stages of the same shape from an array.
Why not just CompletableFuture.thenComposeAsync chains?
A raw thenComposeAsync chain forces you to either define the entire pipeline at the call site, or pass around CompletableFutures whose computation has already started. CompletableFutureQueue keeps the description and the execution separate: you build a queue at startup, hand it to whoever needs it, and they apply it whenever the input arrives.
Related
- Tutorial: Async pipelines.
Result.thenCombineAsyncโ when you want async combination on aResult<T>rather than at the pipeline level.