All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teamapps.ux.task.ProgressCompletableFuture Maven / Gradle / Ivy

There is a newer version: 0.9.194
Show newest version
/*-
 * ========================LICENSE_START=================================
 * TeamApps
 * ---
 * Copyright (C) 2014 - 2023 TeamApps.org
 * ---
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */
package org.teamapps.ux.task;

import org.teamapps.ux.session.CurrentSessionContext;
import org.teamapps.ux.session.SessionContext;
import org.teamapps.ux.task.function.ProgressReportingBiConsumer;
import org.teamapps.ux.task.function.ProgressReportingBiFunction;
import org.teamapps.ux.task.function.ProgressReportingConsumer;
import org.teamapps.ux.task.function.ProgressReportingFunction;
import org.teamapps.ux.task.function.ProgressReportingRunnable;
import org.teamapps.ux.task.function.ProgressReportingSupplier;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class ProgressCompletableFuture extends CompletableFuture {

	// basically copy and paste from CompletableFuture...
	private static final boolean USE_COMMON_POOL = (ForkJoinPool.getCommonPoolParallelism() > 1);
	// basically copy and paste from CompletableFuture...
	public static final Executor ASYNC_POOL = USE_COMMON_POOL ? ForkJoinPool.commonPool() : r -> new Thread(r).start();

	private final Progress progress;

	public ProgressCompletableFuture() {
		this(new Progress());
	}

	public ProgressCompletableFuture(Progress progress) {
		this.progress = progress;
	}

	public ObservableProgress getProgress() {
		return progress;
	}

	public boolean complete(T value) {
		progress.markCompleted();
		return super.complete(value);
	}

	public boolean completeExceptionally(Throwable ex) {
		progress.markFailed();
		return super.completeExceptionally(ex);
	}

	@Override
	public  ProgressCompletableFuture newIncompleteFuture() {
		return new ProgressCompletableFuture<>();
	}

	// ========== static =========================


	public static  ProgressCompletableFuture supplyAsync(ProgressReportingSupplier supplier) {
		return supplyAsync(supplier, ASYNC_POOL);
	}

	public static  ProgressCompletableFuture supplyAsync(ProgressReportingSupplier supplier, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		executor.execute(() -> {
			future.progress.start();
			try {
				U result = supplier.get(future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		});
		return future;
	}

	public static ProgressCompletableFuture runAsync(ProgressReportingRunnable runnable) {
		return runAsync(runnable, ASYNC_POOL);
	}

	public static ProgressCompletableFuture runAsync(ProgressReportingRunnable runnable, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		executor.execute(runWrapped(runnable, future));
		return future;
	}

	public static  ProgressCompletableFuture supplyAsync(Supplier supplier) {
		return supplyAsync(supplier, ASYNC_POOL);
	}

	public static  ProgressCompletableFuture supplyAsync(Supplier supplier, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		executor.execute(() -> {
			future.progress.start();
			try {
				U result = supplier.get();
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		});
		return future;
	}

	public static ProgressCompletableFuture runAsync(Runnable runnable) {
		return runAsync(runnable, ASYNC_POOL);
	}

	public static ProgressCompletableFuture runAsync(Runnable runnable, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		executor.execute(runWrapped(runnable, future));
		return future;
	}


	// ========== with session context ===========

	public  ProgressCompletableFuture thenApplyWithSessionContext(Function fn) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return thenApply(t -> {
			Object[] result = new Object[1];
			sessionContext.runWithContext(() -> result[0] = fn.apply(t));
			return (U) result[0];
		});
	}

	public ProgressCompletableFuture thenAcceptWithCurrentSessionContext(Consumer action) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return thenAccept(t -> sessionContext.runWithContext(() -> action.accept(t)));
	}

	public ProgressCompletableFuture thenRunWithCurrentSessionContext(Runnable action) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return thenRun(() -> sessionContext.runWithContext(action));
	}

	public ProgressCompletableFuture whenCompleteWithCurrentSessionContext(BiConsumer action) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return whenComplete((t, throwable) -> sessionContext.runWithContext(() -> action.accept(t, throwable)));
	}

	public  ProgressCompletableFuture handleWithCurrentSessionContext(BiFunction fn) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return handle((t, throwable) -> {
			Object[] result = new Object[1];
			sessionContext.runWithContext(() -> result[0] = fn.apply(t, throwable));
			return (U) result[0];
		});
	}

	public ProgressCompletableFuture exceptionallyWithCurrentSessionContext(Function fn) {
		SessionContext sessionContext = CurrentSessionContext.get();
		return exceptionally(throwable -> {
			Object[] result = new Object[1];
			sessionContext.runWithContext(() -> result[0] = fn.apply(throwable));
			return (T) result[0];
		});
	}

	// ========= simple overrides =============

	@Override
	public  ProgressCompletableFuture thenApply(Function fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApply(applyWrapped(fn, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	@Override
	public  ProgressCompletableFuture thenApplyAsync(Function fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApplyAsync(applyWrapped(fn, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	@Override
	public  ProgressCompletableFuture thenApplyAsync(Function fn, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApplyAsync(applyWrapped(fn, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private  Function applyWrapped(Function fn, ProgressCompletableFuture future) {
		return t -> {
			future.progress.start();
			try {
				U result = fn.apply(t);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		};
	}

	@Override
	public ProgressCompletableFuture thenAccept(Consumer action) {
		ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAccept(acceptWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	@Override
	public ProgressCompletableFuture thenAcceptAsync(Consumer action) {
		ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAcceptAsync(acceptWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	@Override
	public ProgressCompletableFuture thenAcceptAsync(Consumer action, Executor executor) {
		ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAcceptAsync(acceptWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private Consumer acceptWrapped(Consumer action, ProgressCompletableFuture future) {
		return t -> {
			future.progress.start();
			try {
				action.accept(t);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(null);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		};
	}

	public ProgressCompletableFuture thenRun(Runnable action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRun(runWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenRunAsync(Runnable action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRunAsync(runWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenRunAsync(Runnable action, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRunAsync(runWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private static Runnable runWrapped(Runnable action, ProgressCompletableFuture future) {
		return () -> {
			future.progress.start();
			try {
				action.run();
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(null);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		};
	}

	public ProgressCompletableFuture whenComplete(BiConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenComplete(whenCompleteWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture whenCompleteAsync(BiConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenCompleteAsync(whenCompleteWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenCompleteAsync(whenCompleteWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private BiConsumer whenCompleteWrapped(BiConsumer action, ProgressCompletableFuture future) {
		return (t, throwable) -> {
			future.progress.start();
			try {
				action.accept(t, throwable);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
			} catch (Exception e) {
				future.progress.markFailed();
			} finally {
				if (throwable != null) {
					future.completeExceptionally(throwable);
				} else {
					future.complete(t);
				}
			}
		};
	}

	public  ProgressCompletableFuture handle(BiFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handle(handleWrapped(fn, future));
		return future;
	}

	public  ProgressCompletableFuture handleAsync(BiFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handleAsync(handleWrapped(fn, future));
		return future;
	}

	public  ProgressCompletableFuture handleAsync(BiFunction fn, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handleAsync(handleWrapped(fn, future), executor);
		return future;
	}

	private  BiFunction handleWrapped(BiFunction fn, ProgressCompletableFuture future) {
		return (t, throwable) -> {
			future.progress.start();
			try {
				U result = fn.apply(t, throwable);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		};
	}

	@Override
	public ProgressCompletableFuture toCompletableFuture() {
		return (ProgressCompletableFuture) super.toCompletableFuture();
	}

	public ProgressCompletableFuture exceptionally(Function fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.exceptionally(throwable -> {
			future.progress.start();
			try {
				T result = fn.apply(throwable);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		});
		return future;
	}

	public ProgressCompletableFuture completeAsync(Supplier supplier, Executor executor) {
		return (ProgressCompletableFuture) super.completeAsync(completeWrapped(supplier), executor);
	}

	public ProgressCompletableFuture completeAsync(Supplier supplier) {
		return (ProgressCompletableFuture) super.completeAsync(completeWrapped(supplier));
	}

	private Supplier completeWrapped(Supplier supplier) {
		return () -> {
			this.progress.start();
			try {
				T result = supplier.get();
				this.progress.markCompleted(); // will get ignored if the progress is already in a final state
				this.complete(result);
			} catch (Exception e) {
				this.progress.markFailed();
				this.completeExceptionally(e);
			}
			return null;
		};
	}

	@Override
	public ProgressCompletableFuture orTimeout(long timeout, TimeUnit unit) {
		return (ProgressCompletableFuture) super.orTimeout(timeout, unit);
	}

	@Override
	public ProgressCompletableFuture completeOnTimeout(T value, long timeout, TimeUnit unit) {
		return (ProgressCompletableFuture) super.completeOnTimeout(value, timeout, unit);
	}


	// ========== overloaded methods with progress ==================

	public  ProgressCompletableFuture thenApply(ProgressReportingFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApply(applyWrapped(fn, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public  ProgressCompletableFuture thenApplyAsync(ProgressReportingFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApplyAsync(applyWrapped(fn, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public  ProgressCompletableFuture thenApplyAsync(ProgressReportingFunction fn, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenApplyAsync(applyWrapped(fn, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private  Function applyWrapped(ProgressReportingFunction fn, ProgressCompletableFuture future) {
		return t -> {
			future.progress.start();
			try {
				U result = fn.apply(t, future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		};
	}

	public ProgressCompletableFuture thenAccept(ProgressReportingConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAccept(acceptWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenAcceptAsync(ProgressReportingConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAcceptAsync(acceptWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenAcceptAsync(ProgressReportingConsumer action, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenAcceptAsync(acceptWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private Consumer acceptWrapped(ProgressReportingConsumer action, ProgressCompletableFuture future) {
		return t -> {
			future.progress.start();
			try {
				action.accept(t, future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(null);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		};
	}

	public ProgressCompletableFuture thenRun(ProgressReportingRunnable action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRun(runWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenRunAsync(ProgressReportingRunnable action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRunAsync(runWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture thenRunAsync(ProgressReportingRunnable action, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.thenRunAsync(runWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private static Runnable runWrapped(ProgressReportingRunnable action, ProgressCompletableFuture future) {
		return () -> {
			future.progress.start();
			try {
				action.run(future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(null);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
		};
	}

	public ProgressCompletableFuture whenComplete(ProgressReportingBiConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenComplete(whenCompleteWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture whenCompleteAsync(ProgressReportingBiConsumer action) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenCompleteAsync(whenCompleteWrapped(action, future))
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	public ProgressCompletableFuture whenCompleteAsync(ProgressReportingBiConsumer action, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.whenCompleteAsync(whenCompleteWrapped(action, future), executor)
				.exceptionally(throwable -> {
					future.completeExceptionally(throwable);
					return null;
				});
		return future;
	}

	private BiConsumer whenCompleteWrapped(ProgressReportingBiConsumer action, ProgressCompletableFuture future) {
		return (t, throwable) -> {
			future.progress.start();
			try {
				action.accept(t, throwable, future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
			} catch (Exception e) {
				future.progress.markFailed();
			} finally {
				if (throwable != null) {
					future.completeExceptionally(throwable);
				} else {
					future.complete(t);
				}
			}
		};
	}

	public  ProgressCompletableFuture handle(ProgressReportingBiFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handle(handleWrapped(fn, future));
		return future;
	}

	public  ProgressCompletableFuture handleAsync(ProgressReportingBiFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handleAsync(handleWrapped(fn, future));
		return future;
	}

	public  ProgressCompletableFuture handleAsync(ProgressReportingBiFunction fn, Executor executor) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.handleAsync(handleWrapped(fn, future), executor);
		return future;
	}

	private  BiFunction handleWrapped(ProgressReportingBiFunction fn, ProgressCompletableFuture future) {
		return (t, throwable) -> {
			future.progress.start();
			try {
				U result = fn.apply(t, throwable, future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		};
	}

	public ProgressCompletableFuture exceptionally(ProgressReportingFunction fn) {
		final ProgressCompletableFuture future = new ProgressCompletableFuture<>();
		super.exceptionally(throwable -> {
			future.progress.start();
			try {
				T result = fn.apply(throwable, future.progress);
				future.progress.markCompleted(); // will get ignored if the progress is already in a final state
				future.complete(result);
			} catch (Exception e) {
				future.progress.markFailed();
				future.completeExceptionally(e);
			}
			return null;
		});
		return future;
	}

	public ProgressCompletableFuture completeAsync(ProgressReportingSupplier supplier, Executor executor) {
		return (ProgressCompletableFuture) super.completeAsync(completeWrapped(supplier), executor);
	}

	public ProgressCompletableFuture completeAsync(ProgressReportingSupplier supplier) {
		return (ProgressCompletableFuture) super.completeAsync(completeWrapped(supplier));
	}

	private Supplier completeWrapped(ProgressReportingSupplier supplier) {
		return () -> {
			this.progress.start();
			try {
				T result = supplier.get(this.progress);
				this.progress.markCompleted(); // will get ignored if the progress is already in a final state
				this.complete(result);
			} catch (Exception e) {
				this.progress.markFailed();
				this.completeExceptionally(e);
			}
			return null;
		};
	}

	/* ========== TODO ==============
		public  ProgressingCompletableFuture thenCombine(CompletionStage other, BiFunction fn)
		public  ProgressingCompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn)
		public  ProgressingCompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor)
		public  ProgressingCompletableFuture thenAcceptBoth(CompletionStage other, BiConsumer action)
		public  ProgressingCompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action)
		public  ProgressingCompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor)
		public ProgressingCompletableFuture runAfterBoth(CompletionStage other, Runnable action)
		public ProgressingCompletableFuture runAfterBothAsync(CompletionStage other, Runnable action)
		public ProgressingCompletableFuture runAfterBothAsync(CompletionStage other, Runnable action, Executor executor)
		public  ProgressingCompletableFuture applyToEither(CompletionStage other, Function fn)
		public  ProgressingCompletableFuture applyToEitherAsync(CompletionStage other, Function fn)
		public  ProgressingCompletableFuture applyToEitherAsync(CompletionStage other, Function fn, Executor executor)
		public ProgressingCompletableFuture acceptEither(CompletionStage other, Consumer action)
		public ProgressingCompletableFuture acceptEitherAsync(CompletionStage other, Consumer action)
		public ProgressingCompletableFuture acceptEitherAsync(CompletionStage other, Consumer action, Executor executor)
		public ProgressingCompletableFuture runAfterEither(CompletionStage other, Runnable action)
		public ProgressingCompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action)
		public ProgressingCompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor)
		public  ProgressingCompletableFuture thenCompose(Function> fn)
		public  ProgressingCompletableFuture thenComposeAsync(Function> fn)
		public  ProgressingCompletableFuture thenComposeAsync(Function> fn, Executor executor)
	 */
}