Skip to content

Commit

Permalink
refactor/docs: reorder methods of CffuFactoryBuilder; revise README…
Browse files Browse the repository at this point in the history
… and javadoc
  • Loading branch information
oldratlee committed Aug 9, 2024
1 parent 5681a2e commit 078d9e4
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 61 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
- [2.4 支持超时的`join`的方法](#24-%E6%94%AF%E6%8C%81%E8%B6%85%E6%97%B6%E7%9A%84join%E7%9A%84%E6%96%B9%E6%B3%95)
- [2.5 `Backport`支持`Java 8`](#25-backport%E6%94%AF%E6%8C%81java-8)
- [2.6 返回具体类型的`anyOf`方法](#26-%E8%BF%94%E5%9B%9E%E5%85%B7%E4%BD%93%E7%B1%BB%E5%9E%8B%E7%9A%84anyof%E6%96%B9%E6%B3%95)
- [2.7 输入宽泛类型的`allof/anyOf`方法](#27-%E8%BE%93%E5%85%A5%E5%AE%BD%E6%B3%9B%E7%B1%BB%E5%9E%8B%E7%9A%84allofanyof%E6%96%B9%E6%B3%95)
- [更多功能说明](#%E6%9B%B4%E5%A4%9A%E5%8A%9F%E8%83%BD%E8%AF%B4%E6%98%8E)
- [3. 如何从直接使用`CompletableFuture`类迁移到`Cffu`](#3-%E5%A6%82%E4%BD%95%E4%BB%8E%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8completablefuture%E7%B1%BB%E8%BF%81%E7%A7%BB%E5%88%B0cffu%E7%B1%BB)
- [🔌 API Docs](#-api-docs)
Expand Down Expand Up @@ -81,13 +82,14 @@
- 支持设置缺省的业务线程池并封装携带,`CffuFactory#builder(executor)`方法
- 支持超时的`join`的方法,`join(timeout, unit)`方法
- 超时执行安全的`cffuOrTimeout`/`cffuCompleteOnTimeout`方法
- 一定不会修改结果的处理`peek`方法
- 一定不会修改结果的`peek`处理方法
`CompletableFuture#whenComplete`方法会修改输入`CF`的结果)
- 支持禁止强制篡改,`CffuFactoryBuilder#forbidObtrudeMethods`方法
- 在类方法附加完善的代码质量注解,在编码时`IDE`能尽早提示出问题
`@NonNull``@Nullable``@CheckReturnValue``@Contract`
- 🧩 缺失的基础基本功能,除了上面面向安全而新实现方法(如`join(timeout, unit)`/`cffuOrTimeout`/`peek`),还有
- 异步异常完成,`completeExceptionallyAsync`方法
- 非阻塞地获取成功结果,`getSuccessNow`方法
- 非阻塞地获取成功结果,如果`CF`失败或还没有运行完成则返回指定的缺省值,`getSuccessNow`方法
- 解包装`CF`异常成业务异常,`unwrapCfException`方法
- 💪 **已有功能的增强**,如
- `anyOf`方法:返回具体类型`T`(类型安全),而不是返回`Object``CompletableFuture#anyOf`
Expand Down Expand Up @@ -453,7 +455,6 @@ public class DefaultExecutorSettingForCffu {
- 业务有容错逻辑时,有处理出错时可以使用成功那部分结果,而不是整体失败
- `cffu`提供了相应的`allSuccessOf`等方法
- 返回指定时间内多个`CF`中成功的结果,对于失败或还没有运行完成的`CF`返回指定的缺省值
- 忽略失败或还没有运行完成的`CF`(返回指定的缺省值)
- 业务最终一致性时,能返回就尽量返回有的;对于没有及时返回还在运行中处理的`CF`,结果会写到分布式缓存中避免重复计算,下次就有了
- 这是个常见业务使用模式,`cffu`提供了相应的`mostSuccessResultsOf`等方法

Expand Down Expand Up @@ -557,7 +558,15 @@ public class ConcurrencyStrategyDemo {

`cffu`提供的`anySuccessOf`/`anyOf`方法,返回具体类型`T`,而不是返回`Object`

这个新方法使用简单类似,不附代码示例。
这个方法使用简单类似,不附代码示例。

### 2.7 输入宽泛类型的`allof/anyOf`方法

`CompletableFuture#allof/anyOf`方法输入参数类型是`CompletableFuture`,而输入更宽泛的`CompletionStage`类型;对于`CompletionStage`类型的输入,则需要调用`CompletionStage#toCompletableFuture`方法做转换。

`cffu`提供的`allof`/`anyOf`方法输入更宽泛的`CompletionStage`参数类型,使用更方便。

方法使用简单类似,不附代码示例。

### 更多功能说明

Expand Down
25 changes: 16 additions & 9 deletions cffu-core/src/main/java/io/foldright/cffu/Cffu.java
Original file line number Diff line number Diff line change
Expand Up @@ -2703,18 +2703,16 @@ public boolean cancel(boolean mayInterruptIfRunning) {
* If this Cffu completes exceptionally, then the returned CompletionStage completes
* exceptionally with a CompletionException with this exception as cause.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
* <p>
* demo code about re-config methods of Cffu:
*
* <pre>{@code cffu2 = cffu
* .resetCffuFactory(cffuFactory2) // reset to use config from cffuFactory2
* .minimalCompletionStage(); // restrict to methods of CompletionStage
* .resetDefaultExecutor(executor2) // reset to use executor2
* .minimalCompletionStage(); // restrict to methods of CompletionStage
* }</pre>
*
* @see #resetCffuFactory(CffuFactory)
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8(not support *minimal* CompletionStage), just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*/
@Contract(pure = true)
public CompletionStage<T> minimalCompletionStage() {
Expand All @@ -2723,10 +2721,19 @@ public CompletionStage<T> minimalCompletionStage() {

/**
* Returns a new Cffu with the given defaultExecutor.
* <p>
* demo code about re-config methods of Cffu:
*
* <pre>{@code cffu2 = cffu
* .resetDefaultExecutor(executor2) // reset to use executor2
* .minimalCompletionStage(); // restrict to methods of CompletionStage
* }</pre>
*
* @see #minimalCompletionStage()
*/
@Contract(pure = true)
public Cffu<T> resetDefaultExecutor(Executor defaultExecutor) {
return new Cffu<>(fac.resetDefaultExecutor(defaultExecutor), isMinimalStage, cf);
return resetCffuFactory(fac.resetDefaultExecutor(defaultExecutor));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,7 @@ public <T> Cffu<T> completedFuture(@Nullable T value) {
* and supports only those methods in interface {@link CompletionStage}.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* if run on old Java 8(not support *minimal* CompletionStage), just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param value the value
Expand Down Expand Up @@ -1524,7 +1524,7 @@ public <T> Cffu<T> failedFuture(Throwable ex) {
* with the given exception and supports only those methods in interface {@link CompletionStage}.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* if run on old Java 8(not support *minimal* CompletionStage), just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param ex the exception
Expand Down
84 changes: 47 additions & 37 deletions cffu-core/src/main/java/io/foldright/cffu/CffuFactoryBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
*/
@ThreadSafe
public final class CffuFactoryBuilder {
////////////////////////////////////////////////////////////////////////////////
// region# Internal constructor and fields
////////////////////////////////////////////////////////////////////////////////

private final Executor defaultExecutor;

private volatile boolean forbidObtrudeMethods = false;
Expand All @@ -32,44 +36,9 @@ public final class CffuFactoryBuilder {
this.defaultExecutor = makeExecutor(defaultExecutor);
}

private static Executor makeExecutor(Executor executor) {
// check CffuMadeExecutor interface to avoid re-wrapping.
if (executor instanceof CffuMadeExecutor) return executor;

Executor wrapByProviders = wrapExecutorByProviders(CompletableFutureUtils.screenExecutor(executor));
return CffuMadeExecutor.wrapMadeInterface(wrapByProviders);
}

/**
* An interface for avoiding re-wrapping.
*/
@VisibleForTesting
interface CffuMadeExecutor extends Executor {
static CffuMadeExecutor wrapMadeInterface(Executor executor) {
return new CffuMadeExecutor() {
@Override
public Executor unwrap() {
return executor;
}

@Override
public void execute(Runnable command) {
executor.execute(command);
}

@Override
public String toString() {
return "CffuMadeExecutor of executor(" + executor + ")";
}
};
}

@VisibleForTesting
Executor unwrap();
}

// endregion
////////////////////////////////////////////////////////////////////////////////
// Builder Methods
// region# Builder Methods
////////////////////////////////////////////////////////////////////////////////

/**
Expand All @@ -94,11 +63,52 @@ public CffuFactory build() {
return new CffuFactory(defaultExecutor, forbidObtrudeMethods);
}

// endregion
////////////////////////////////////////////////////////////////////////////////
// region# Internal helper methods and fields
////////////////////////////////////////////////////////////////////////////////

@Contract(pure = true)
static CffuFactory resetDefaultExecutor(CffuFactory fac, Executor defaultExecutor) {
return new CffuFactory(makeExecutor(defaultExecutor), fac.forbidObtrudeMethods());
}

private static Executor makeExecutor(Executor executor) {
// check CffuMadeExecutor interface to avoid re-wrapping.
if (executor instanceof CffuMadeExecutor) return executor;

Executor wrapByProviders = wrapExecutorByProviders(CompletableFutureUtils.screenExecutor(executor));
return wrapMadeInterface(wrapByProviders);
}

private static CffuMadeExecutor wrapMadeInterface(Executor executor) {
return new CffuMadeExecutor() {
@Override
public void execute(Runnable command) {
executor.execute(command);
}

@Override
public Executor unwrap() {
return executor;
}

@Override
public String toString() {
return "CffuMadeExecutor of executor(" + executor + ")";
}
};
}

/**
* An interface for avoiding re-wrapping.
*/
@VisibleForTesting
interface CffuMadeExecutor extends Executor {
@VisibleForTesting
Executor unwrap();
}

private static Executor wrapExecutorByProviders(Executor executor) {
for (ExecutorWrapperProvider provider : EXECUTOR_WRAPPER_PROVIDERS) {
Supplier<String> msg = () -> provider + "(class: " + provider.getClass().getName() + ") return null";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1922,7 +1922,8 @@ public static <T> CompletableFuture<T> failedFuture(Throwable ex) {
* and supports only those methods in interface {@link CompletionStage}.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
* if run on old Java 8(not support *minimal* CompletionStage),
* just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param value the value
* @param <T> the type of the value
Expand All @@ -1941,7 +1942,8 @@ public static <T> CompletionStage<T> completedStage(@Nullable T value) {
* the given exception and supports only those methods in interface {@link CompletionStage}.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
* if run on old Java 8(not support *minimal* CompletionStage),
* just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param ex the exception
* @param <T> the type of the value
Expand Down Expand Up @@ -4366,7 +4368,8 @@ C completeExceptionallyAsync(C cfThis, Supplier<? extends Throwable> supplier, E
* with a CompletionException with given exception as cause.
* <p>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
* if run on old Java 8(not support *minimal* CompletionStage),
* just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @return the new CompletionStage
* @see CompletableFuture#minimalCompletionStage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ import io.foldright.cffu.CffuFactoryBuilder
internal object CffuArchTest {
@ArchTest
private val constructorOfCffuFactory: ArchRule = run {
val description = ": Accessing CffuFactory constructor is only allowed by class CffuFactoryBuilder"
val description = "only contain the constructors that only accessed by class CffuFactoryBuilder," +
" aka. accessing CffuFactory constructor is only allowed by class CffuFactoryBuilder"

val condition = object : ArchCondition<JavaClass>(description) {
val cffuFactoryBuilderClass = CffuFactoryBuilder::class.java

override fun check(javaClass: JavaClass, events: ConditionEvents) {
val codeUnitAccesses = javaClass.constructorCallsToSelf + javaClass.constructorReferencesToSelf
override fun check(clazz: JavaClass, events: ConditionEvents) {
val codeUnitAccesses = clazz.constructorCallsToSelf + clazz.constructorReferencesToSelf

codeUnitAccesses.filterNot { it.originOwner.isEquivalentTo(cffuFactoryBuilderClass) }.forEach {
val msg = "Accessing constructor of ${it.target.fullName} is not allowed" +
val msg = "Accessing constructor `${it.target.fullName}` is not allowed" +
" by class ${it.originOwner.name}${it.sourceCodeLocation}"
events.add(SimpleConditionEvent.violated(it, msg))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1132,8 +1132,8 @@ fun <C : CompletableFuture<*>> C.completeExceptionallyAsync(supplier: Supplier<o
* If given CompletableFuture completes exceptionally, then the returned CompletionStage completes exceptionally
* with a CompletionException with given exception as cause.
*
* ***CAUTION:*** if run on old Java 8, just return a ***normal*** CompletableFuture
* which is NOT with a ***minimal*** CompletionStage.
* ***CAUTION:*** if run on old Java 8(not support *minimal* CompletionStage),
* just return a ***normal*** CompletableFuture which is NOT with a ***minimal*** CompletionStage.
*
* @return the new CompletionStage
*/
Expand Down

0 comments on commit 078d9e4

Please sign in to comment.