diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index f6279504..37ca6345 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -7,7 +7,7 @@ jobs:
test:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#choosing-github-hosted-runners
runs-on: ubuntu-latest
- timeout-minutes: 10
+ timeout-minutes: 15
name: CI by multiply java versions
steps:
@@ -26,7 +26,6 @@ jobs:
21
22
distribution: zulu
- # only first java setup need enable cache
cache: maven
- name: Run integration test
diff --git a/.github/workflows/fast_ci.yaml b/.github/workflows/fast_ci.yaml
index 6ee48d24..bb046d3a 100644
--- a/.github/workflows/fast_ci.yaml
+++ b/.github/workflows/fast_ci.yaml
@@ -23,24 +23,6 @@ jobs:
with:
java-version: 21
distribution: microsoft
- # only first java setup need enable cache
cache: maven
- name: Build and test with Java 21
run: ./mvnw -V --no-transfer-progress clean install
-
- - name: Setup Java 8
- uses: actions/setup-java@v4
- with:
- java-version: 8
- distribution: zulu
- - name: Test with Java 8
- run: ./mvnw -V --no-transfer-progress surefire:test
-
- - name: 'Remove self maven install files(OS: *nix)'
- run: rm -rf $HOME/.m2/repository/io/foldright/cffu*
- # https://docs.github.com/en/actions/learn-github-actions/expressions
- # https://docs.github.com/en/actions/learn-github-actions/variables#detecting-the-operating-system
- if: runner.os != 'Windows'
- - name: 'Remove self maven install files(OS: Windows)'
- run: Remove-Item -Recurse -Force $home/.m2/repository/io/foldright/cffu*
- if: runner.os == 'Windows'
diff --git a/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java b/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java
index dbcd53d2..d7050fee 100644
--- a/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java
+++ b/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java
@@ -33,7 +33,6 @@
* About factory methods conventions of {@link CffuFactory}:
*
* factory methods return {@link Cffu} instead of {@link CompletableFuture}.
- * new methods, aka. no equivalent method in {@link CompletableFuture}, prefix method name with {@code cffu}.
* only provide varargs methods for multiply Cffu/CF input arguments;
* if you have {@code List} input, use static util methods {@link #cffuListToArray(List)}
* or {@link #completableFutureListToArray(List)} to convert it to array first.
@@ -293,11 +292,11 @@ public final Cffu[] asCffuArray(CompletionStage... stages) {
}
////////////////////////////////////////////////////////////////////////////////
- //# allOf / anyOf methods, without return result type enhancement
+ //# allOf / anyOf methods
// - allOf*, return Cffu, equivalent to same name methods:
// - CompletableFuture.allOf()
// - CompletableFutureUtils.allOfFastFail()
- // - anyOf*, return Cffu, equivalent to same name methods:
+ // - anyOf*, equivalent to same name methods:
// - CompletableFuture.anyOf()
// - CompletableFutureUtils.anyOfSuccess()
////////////////////////////////////////////////////////////////////////////////
@@ -567,10 +566,7 @@ public Executor delayedExecutor(long delay, TimeUnit unit, Executor executor) {
}
////////////////////////////////////////////////////////////////////////////////
- //# New type-safe allOf/anyOf Factory Methods
- // method name prefix with `cffu`
- //
- // - allResultsOf
+ //# New allResultsOf* Factory Methods
////////////////////////////////////////////////////////////////////////////////
/**
diff --git a/cffu-core/src/test/java/io/foldright/showcases/CompletableFutureUsageShowcaseTest.kt b/cffu-core/src/test/java/io/foldright/showcases/CompletableFutureUsageShowcaseTest.kt
index 2aaf749d..145c0b7a 100644
--- a/cffu-core/src/test/java/io/foldright/showcases/CompletableFutureUsageShowcaseTest.kt
+++ b/cffu-core/src/test/java/io/foldright/showcases/CompletableFutureUsageShowcaseTest.kt
@@ -1,5 +1,3 @@
-@file:OptIn(ExperimentalTime::class)
-
package io.foldright.showcases
import io.foldright.test_utils.*
@@ -18,7 +16,6 @@ import java.lang.System.currentTimeMillis
import java.lang.Thread.currentThread
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicBoolean
-import kotlin.time.ExperimentalTime
class CompletableFutureUsageShowcaseTest : FunSpec({
val n = 42
diff --git a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt
index 678fab42..d0bff955 100644
--- a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt
+++ b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt
@@ -50,10 +50,10 @@ fun Array>.asCffu(cffuFactory: CffuFactory): Array>.allOfFastFailCffu(cffuFactory: CffuFactory):
// anyOf* methods
//
// - anyOfCffu
-// - anyOfCffuAny
// - anyOfSuccessCffu
-// - anyOfSuccessCffuAny
////////////////////////////////////////
/**
diff --git a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt
index 5ed95679..c9ae9c5f 100644
--- a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt
+++ b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt
@@ -1,3 +1,5 @@
+@file:Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+
package io.foldright.cffu.kotlin
import io.foldright.cffu.CffuState
@@ -10,6 +12,8 @@ import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionStage
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
+import java.util.function.Function
+import java.util.function.Supplier
////////////////////////////////////////////////////////////////////////////////
@@ -383,8 +387,6 @@ fun CompletableFuture.combineFastFail(
////////////////////////////////////////////////////////////////////////////////
//# Backport CF instance methods
// compatibility for low Java version
-//
-// all methods name prefix with `cffu`
////////////////////////////////////////////////////////////////////////////////
//# Error Handling methods of CompletionStage
@@ -399,7 +401,7 @@ fun CompletableFuture.combineFastFail(
* if given CompletionStage completed exceptionally
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuExceptionallyAsync(fn: (Throwable) -> T): CompletableFuture =
+fun CompletableFuture.exceptionallyAsync(fn: Function): CompletableFuture =
CompletableFutureUtils.exceptionallyAsync(this, fn)
/**
@@ -412,20 +414,22 @@ fun CompletableFuture.cffuExceptionallyAsync(fn: (Throwable) -> T): Compl
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuExceptionallyAsync(fn: (Throwable) -> T, executor: Executor): CompletableFuture =
+fun CompletableFuture.exceptionallyAsync(
+ fn: Function, executor: Executor
+): CompletableFuture =
CompletableFutureUtils.exceptionallyAsync(this, fn, executor)
//# Timeout Control methods
/**
- * Exceptionally completes this CompletableFuture with a [TimeoutException][java.util.concurrent.TimeoutException]
+ * Exceptionally completes this CompletableFuture with a TimeoutException
* if not otherwise completed before the given timeout.
*
* @param timeout how long to wait before completing exceptionally with a TimeoutException, in units of `unit`
* @param unit a `TimeUnit` determining how to interpret the `timeout` parameter
* @return this CompletableFuture
*/
-fun CompletableFuture.cffuOrTimeout(timeout: Long, unit: TimeUnit): CompletableFuture =
+fun CompletableFuture.orTimeout(timeout: Long, unit: TimeUnit): CompletableFuture =
CompletableFutureUtils.orTimeout(this, timeout, unit)
/**
@@ -436,7 +440,7 @@ fun CompletableFuture.cffuOrTimeout(timeout: Long, unit: TimeUnit): Compl
* @param unit a `TimeUnit` determining how to interpret the `timeout` parameter
* @return given CompletableFuture
*/
-fun CompletableFuture.cffuCompleteOnTimeout(value: T, timeout: Long, unit: TimeUnit): CompletableFuture =
+fun CompletableFuture.completeOnTimeout(value: T, timeout: Long, unit: TimeUnit): CompletableFuture =
CompletableFutureUtils.completeOnTimeout(this, value, timeout, unit)
//# Advanced methods of CompletionStage
@@ -449,7 +453,9 @@ fun CompletableFuture.cffuCompleteOnTimeout(value: T, timeout: Long, unit
* CompletionStage if given CompletionStage completed exceptionally
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuExceptionallyCompose(fn: (Throwable) -> CompletionStage): CompletableFuture =
+fun CompletableFuture.exceptionallyCompose(
+ fn: Function>
+): CompletableFuture =
CompletableFutureUtils.exceptionallyCompose(this, fn)
/**
@@ -461,8 +467,8 @@ fun CompletableFuture.cffuExceptionallyCompose(fn: (Throwable) -> Complet
* CompletionStage if given CompletionStage completed exceptionally
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuExceptionallyComposeAsync(
- fn: (Throwable) -> CompletionStage
+fun CompletableFuture.exceptionallyComposeAsync(
+ fn: Function>
): CompletableFuture =
CompletableFutureUtils.exceptionallyComposeAsync(this, fn)
@@ -475,8 +481,8 @@ fun CompletableFuture.cffuExceptionallyComposeAsync(
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuExceptionallyComposeAsync(
- fn: (Throwable) -> CompletionStage, executor: Executor
+fun CompletableFuture.exceptionallyComposeAsync(
+ fn: Function>, executor: Executor
): CompletableFuture =
CompletableFutureUtils.exceptionallyComposeAsync(this, fn, executor)
@@ -501,9 +507,8 @@ fun CompletableFuture.cffuExceptionallyComposeAsync(
* ```
*
* CAUTION:
- * if the wait timed out, this method throws an (unchecked) [CompletionException][java.util.concurrent.CompletionException]
- * with the [TimeoutException][java.util.concurrent.TimeoutException] as its cause;
- * NOT throws a (checked) [TimeoutException][java.util.concurrent.TimeoutException] like [CompletableFuture.get].
+ * if the wait timed out, this method throws an (unchecked) CompletionException with the TimeoutException as its cause;
+ * NOT throws a (checked) TimeoutException like [CompletableFuture.get].
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
@@ -530,7 +535,7 @@ fun CompletableFuture.join(timeout: Long, unit: TimeUnit): T =
* ```
*/
@Suppress("UNCHECKED_CAST")
-fun CompletableFuture.cffuResultNow(): T =
+fun CompletableFuture.resultNow(): T =
CompletableFutureUtils.resultNow(this) as T
/**
@@ -543,7 +548,7 @@ fun CompletableFuture.cffuResultNow(): T =
* or the task was cancelled
* @see CompletableFuture#resultNow()
*/
-fun CompletableFuture.cffuExceptionNow(): Throwable =
+fun CompletableFuture.exceptionNow(): Throwable =
CompletableFutureUtils.exceptionNow(this)
/**
@@ -566,7 +571,7 @@ fun CompletableFuture.cffuState(): CffuState =
* @param supplier a function returning the value to be used to complete given CompletableFuture
* @return given CompletableFuture
*/
-fun CompletableFuture.cffuCompleteAsync(supplier: () -> T): CompletableFuture =
+fun CompletableFuture.completeAsync(supplier: Supplier): CompletableFuture =
CompletableFutureUtils.completeAsync(this, supplier)
/**
@@ -577,7 +582,7 @@ fun CompletableFuture.cffuCompleteAsync(supplier: () -> T): CompletableFu
* @param executor the executor to use for asynchronous execution
* @return given CompletableFuture
*/
-fun CompletableFuture.cffuCompleteAsync(supplier: () -> T, executor: Executor): CompletableFuture =
+fun CompletableFuture.completeAsync(supplier: Supplier, executor: Executor): CompletableFuture =
CompletableFutureUtils.completeAsync(this, supplier, executor)
//# Re-Config methods
@@ -594,7 +599,7 @@ fun CompletableFuture.cffuCompleteAsync(supplier: () -> T, executor: Exec
*
* @return the new CompletionStage
*/
-fun CompletableFuture.cffuMinimalCompletionStage(): CompletionStage =
+fun CompletableFuture.minimalCompletionStage(): CompletionStage =
CompletableFutureUtils.minimalCompletionStage(this)
/**
@@ -606,7 +611,7 @@ fun CompletableFuture.cffuMinimalCompletionStage(): CompletionStage =
*
* @return the new CompletableFuture
*/
-fun CompletableFuture.cffuCopy(): CompletableFuture =
+fun CompletableFuture.copy(): CompletableFuture =
CompletableFutureUtils.copy(this)
/**
@@ -615,5 +620,5 @@ fun CompletableFuture.cffuCopy(): CompletableFuture =
* @param the type of the value
* @return a new CompletableFuture
*/
-fun CompletableFuture.cffuNewIncompleteFuture(): CompletableFuture =
+fun CompletableFuture.newIncompleteFuture(): CompletableFuture =
CompletableFutureUtils.newIncompleteFuture(this)
diff --git a/cffu-kotlin/src/test/java/io/foldright/cffu/test/CompletableFutureExtensionsTest.kt b/cffu-kotlin/src/test/java/io/foldright/cffu/test/CompletableFutureExtensionsTest.kt
index f99fcb5d..95ac14fa 100644
--- a/cffu-kotlin/src/test/java/io/foldright/cffu/test/CompletableFutureExtensionsTest.kt
+++ b/cffu-kotlin/src/test/java/io/foldright/cffu/test/CompletableFutureExtensionsTest.kt
@@ -264,61 +264,59 @@ class CompletableFutureExtensionsTest : FunSpec({
////////////////////////////////////////////////////////////////////////////////
//# Backport CF instance methods
// compatibility for low Java version
- //
- // all methods name prefix with `cffu`
////////////////////////////////////////////////////////////////////////////////
test("exceptionallyAsync") {
val cf = CompletableFutureUtils.failedFuture(rte)
- cf.cffuExceptionallyAsync { n }.get() shouldBe n
- cf.cffuExceptionallyAsync({ n }, testThreadPoolExecutor).get() shouldBe n
+ cf.exceptionallyAsync { n }.get() shouldBe n
+ cf.exceptionallyAsync({ n }, testThreadPoolExecutor).get() shouldBe n
}
- test(" test_timeout") {
+ test("test_timeout") {
var cf = CompletableFuture()
shouldThrow {
- cf.cffuOrTimeout(1, TimeUnit.MILLISECONDS).get()
+ cf.orTimeout(1, TimeUnit.MILLISECONDS).get()
}.cause.shouldBeTypeOf()
cf = CompletableFuture()
- cf.cffuCompleteOnTimeout(n, 1, TimeUnit.MILLISECONDS).get() shouldBe n
+ cf.completeOnTimeout(n, 1, TimeUnit.MILLISECONDS).get() shouldBe n
}
test("exceptionallyCompose") {
val cf = CompletableFutureUtils.failedFuture(rte)
- cf.cffuExceptionallyCompose { CompletableFuture.completedFuture(n) }.get() shouldBe n
- cf.cffuExceptionallyComposeAsync { CompletableFuture.completedFuture(n) }.get() shouldBe n
- cf.cffuExceptionallyComposeAsync({ CompletableFuture.completedFuture(n) }, testThreadPoolExecutor)
+ cf.exceptionallyCompose { CompletableFuture.completedFuture(n) }.get() shouldBe n
+ cf.exceptionallyComposeAsync { CompletableFuture.completedFuture(n) }.get() shouldBe n
+ cf.exceptionallyComposeAsync({ CompletableFuture.completedFuture(n) }, testThreadPoolExecutor)
.get() shouldBe n
}
- test("read") {
+ test("read methods") {
val cf = CompletableFuture.completedFuture(n)
val ff = CompletableFutureUtils.failedFuture(rte)
cf.join(1, TimeUnit.MILLISECONDS) shouldBe n
- cf.cffuResultNow() shouldBe n
- ff.cffuExceptionNow() shouldBeSameInstanceAs rte
+ cf.resultNow() shouldBe n
+ ff.exceptionNow() shouldBeSameInstanceAs rte
cf.cffuState() shouldBe CffuState.SUCCESS
ff.cffuState() shouldBe CffuState.FAILED
}
- test("write") {
+ test("write methods") {
val cf = CompletableFuture()
- cf.cffuCompleteAsync { n }.get() shouldBe n
- cf.cffuCompleteAsync({ n }, testThreadPoolExecutor).get() shouldBe n
+ cf.completeAsync { n }.get() shouldBe n
+ cf.completeAsync({ n }, testThreadPoolExecutor).get() shouldBe n
}
test("re_config") {
- CompletableFuture.completedFuture(n).cffuMinimalCompletionStage()
+ CompletableFuture.completedFuture(n).minimalCompletionStage()
.toCompletableFuture().get() shouldBe n
val cf = CompletableFuture()
- cf.cffuCopy().complete(n)
+ cf.copy().complete(n)
cf.isDone.shouldBeFalse()
- val incomplete = cf.cffuNewIncompleteFuture()
+ val incomplete: CompletableFuture = cf.newIncompleteFuture()
incomplete.isDone.shouldBeFalse()
incomplete.complete(n)
cf.isDone.shouldBeFalse()
diff --git a/scripts/integration_test b/scripts/integration_test
index e0b15d73..a37f6e65 100755
--- a/scripts/integration_test
+++ b/scripts/integration_test
@@ -74,5 +74,44 @@ for jdk_version in "${JDK_VERSIONS[@]}"; do
kt_version_var_name="KT_VERSION_FOR_JAVA${jdk_version}"
kt_version_opt="${!kt_version_var_name:+-Dkotlin.version=${!kt_version_var_name}}"
- mvu::mvn_cmd ${CI_MORE_BEGIN_OPTS:-} dependency:properties surefire:test ${CI_MORE_END_OPTS:-} $kt_version_opt
+
+ pl=
+ if ((jdk_version < default_build_jdk_version)); then
+ pl='-pl cffu-core,cffu-ttl-executor-wrapper'
+ fi
+
+ mvu::mvn_cmd ${pl:-} ${CI_MORE_BEGIN_OPTS:-} dependency:properties surefire:test ${CI_MORE_END_OPTS:-} $kt_version_opt
+done
+
+# test the kotlin extension methods works
+#
+# CAUTION: MUST re-compile the client sources(test codes) by Java 8
+# Extensions are resolved statically.
+# If a class has a member function, and an extension function is defined
+# which has the same receiver type, the same name, and is applicable to given arguments,
+# the member always wins
+# https://kotlinlang.org/docs/extensions.html#extensions-are-resolved-statically
+
+jvu::switch_to_jdk 8
+
+cd cffu-kotlin
+
+# recompile cffu-kotlin and run test
+rm -rf target/*test*
+cu::head_line_echo "recompile and test cffu-kotlin with Java 8: $JAVA_HOME"
+mvu::mvn_cmd -P'!gen-git-properties' -Dmaven.main.skip -Denforcer.skip ${CI_MORE_BEGIN_OPTS:-} dependency:properties test-compile surefire:test ${CI_MORE_END_OPTS:-}
+
+for jdk_version in "${JDK_VERSIONS[@]}"; do
+ # skip default jdk, already tested above
+ ((jdk_version == 8)) && continue
+
+ jvu::switch_to_jdk "$jdk_version"
+
+ # just test without build
+ cu::head_line_echo "test cffu-kotlin with Java $jdk_version: $JAVA_HOME"
+
+ kt_version_var_name="KT_VERSION_FOR_JAVA${jdk_version}"
+ kt_version_opt="${!kt_version_var_name:+-Dkotlin.version=${!kt_version_var_name}}"
+
+ mvu::mvn_cmd -Dmaven.main.skip -Denforcer.skip ${CI_MORE_BEGIN_OPTS:-} dependency:properties surefire:test ${CI_MORE_END_OPTS:-} $kt_version_opt
done