From 0f6def662f3dc9a8920670c63ab2d6b487bf8a69 Mon Sep 17 00:00:00 2001 From: "He-Pin(kerr)" Date: Sat, 13 Sep 2025 15:45:20 +0800 Subject: [PATCH] chore: Make use of japi.funtion.* in Patterns (#2198) --- .../pekko/japi/function/IntFunction.java | 37 +++++++++++++++++++ .../pekko/japi/function/package-info.java | 19 ++++++++++ .../javaapi-functions.excludes | 1 + .../org/apache/pekko/pattern/Patterns.scala | 17 ++++----- .../test/java/jdocs/future/FutureDocTest.java | 19 ++++++++++ 5 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 actor/src/main/java/org/apache/pekko/japi/function/IntFunction.java create mode 100644 actor/src/main/java/org/apache/pekko/japi/function/package-info.java diff --git a/actor/src/main/java/org/apache/pekko/japi/function/IntFunction.java b/actor/src/main/java/org/apache/pekko/japi/function/IntFunction.java new file mode 100644 index 0000000000..58234b8962 --- /dev/null +++ b/actor/src/main/java/org/apache/pekko/japi/function/IntFunction.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package org.apache.pekko.japi.function; + +/** + * Int function that can throw exceptions. + * + * @since 2.0.0 + */ +@FunctionalInterface +public interface IntFunction extends java.io.Serializable { + long serialVersionUID = 1L; + + /** + * Applies this function to the given argument. + * + * @param value the function argument + * @return the function result + * @throws Throwable if an error occurs + */ + R apply(int value) throws Throwable; +} diff --git a/actor/src/main/java/org/apache/pekko/japi/function/package-info.java b/actor/src/main/java/org/apache/pekko/japi/function/package-info.java new file mode 100644 index 0000000000..7bc8717bcf --- /dev/null +++ b/actor/src/main/java/org/apache/pekko/japi/function/package-info.java @@ -0,0 +1,19 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/** Java API for functional programming in Pekko. */ +package org.apache.pekko.japi.function; diff --git a/actor/src/main/mima-filters/2.0.x.backwards.excludes/javaapi-functions.excludes b/actor/src/main/mima-filters/2.0.x.backwards.excludes/javaapi-functions.excludes index 12cfcac7a2..755be7d74e 100644 --- a/actor/src/main/mima-filters/2.0.x.backwards.excludes/javaapi-functions.excludes +++ b/actor/src/main/mima-filters/2.0.x.backwards.excludes/javaapi-functions.excludes @@ -35,4 +35,5 @@ ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.japi.Predicate") ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.japi.Procedure") ProblemFilters.exclude[IncompatibleMethTypeProblem]("org.apache.pekko.pattern.Patterns.askWithReplyTo") ProblemFilters.exclude[IncompatibleMethTypeProblem]("org.apache.pekko.serialization.SerializationSetup.create") +ProblemFilters.exclude[IncompatibleMethTypeProblem]("org.apache.pekko.pattern.Patterns.retry") diff --git a/actor/src/main/scala/org/apache/pekko/pattern/Patterns.scala b/actor/src/main/scala/org/apache/pekko/pattern/Patterns.scala index 2465aeccd8..de4dd2fab2 100644 --- a/actor/src/main/scala/org/apache/pekko/pattern/Patterns.scala +++ b/actor/src/main/scala/org/apache/pekko/pattern/Patterns.scala @@ -15,7 +15,6 @@ package org.apache.pekko.pattern import java.util.Optional import java.util.concurrent.{ Callable, CompletionStage, TimeUnit } -import java.util.function.BiPredicate import scala.concurrent.ExecutionContext @@ -518,7 +517,7 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, ec: ExecutionContext): CompletionStage[T] = { require(attempt != null, "Parameter attempt should not be null.") @@ -585,7 +584,7 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, minBackoff: java.time.Duration, maxBackoff: java.time.Duration, @@ -662,7 +661,7 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, minBackoff: java.time.Duration, maxBackoff: java.time.Duration, @@ -738,7 +737,7 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, delay: java.time.Duration, system: ClassicActorSystemProvider): CompletionStage[T] = @@ -787,7 +786,7 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, delay: java.time.Duration, scheduler: Scheduler, @@ -813,7 +812,7 @@ object Patterns { def retry[T]( attempt: Callable[CompletionStage[T]], attempts: Int, - delayFunction: java.util.function.IntFunction[Optional[java.time.Duration]], + delayFunction: japi.function.IntFunction[Optional[java.time.Duration]], scheduler: Scheduler, context: ExecutionContext): CompletionStage[T] = { import pekko.util.OptionConverters._ @@ -852,9 +851,9 @@ object Patterns { */ def retry[T]( attempt: Callable[CompletionStage[T]], - shouldRetry: BiPredicate[T, Throwable], + shouldRetry: japi.function.Predicate2[T, Throwable], attempts: Int, - delayFunction: java.util.function.IntFunction[Optional[java.time.Duration]], + delayFunction: japi.function.IntFunction[Optional[java.time.Duration]], scheduler: Scheduler, context: ExecutionContext): CompletionStage[T] = { import pekko.util.OptionConverters._ diff --git a/docs/src/test/java/jdocs/future/FutureDocTest.java b/docs/src/test/java/jdocs/future/FutureDocTest.java index 82b80eefe3..80c88e9cbc 100644 --- a/docs/src/test/java/jdocs/future/FutureDocTest.java +++ b/docs/src/test/java/jdocs/future/FutureDocTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import java.time.Duration; import java.util.Arrays; +import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -97,4 +98,22 @@ public class FutureDocTest extends AbstractJavaTest { retriedFuture.toCompletableFuture().get(2, SECONDS); } + + @Test + public void useRetryWithPredicateWithIntFunction() throws Exception { + // #retry + Callable> attempt = () -> CompletableFuture.completedFuture("test"); + + CompletionStage retriedFuture = + Patterns.retry( + attempt, + (notUsed, e) -> e != null, + 3, + current -> Optional.of(java.time.Duration.ofMillis(200)), + system.classicSystem().scheduler(), + system.executionContext()); + // #retry + + retriedFuture.toCompletableFuture().get(2, SECONDS); + } }