diff --git a/management/src/main/mima-filters/1.1.x.backwards.excludes/startup-checks.backwards.excludes b/management/src/main/mima-filters/1.1.x.backwards.excludes/startup-checks.backwards.excludes index 46d6454e..9bbf27b4 100644 --- a/management/src/main/mima-filters/1.1.x.backwards.excludes/startup-checks.backwards.excludes +++ b/management/src/main/mima-filters/1.1.x.backwards.excludes/startup-checks.backwards.excludes @@ -16,7 +16,5 @@ # under the License. # Add startup checks -ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.management.HealthCheckSettings.create") -ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.management.HealthCheckSettings.this") ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.management.scaladsl.HealthChecks.startup") ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.management.scaladsl.HealthChecks.startupResult") diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckSettings.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckSettings.scala index 7f884ed3..55e06bff 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckSettings.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckSettings.scala @@ -89,6 +89,25 @@ object HealthCheckSettings { readinessPath, livenessPath, checkDuration.asScala) + + /** + * Java API + */ + @deprecated("Use create that takes `startupChecks` and `startupPath` parameters instead", "1.1.0") + def create( + readinessChecks: java.util.List[NamedHealthCheck], + livenessChecks: java.util.List[NamedHealthCheck], + readinessPath: String, + livenessPath: String, + checkDuration: java.time.Duration) = + new HealthCheckSettings( + Nil, + readinessChecks.asScala.toList, + livenessChecks.asScala.toList, + "", + readinessPath, + livenessPath, + checkDuration.asScala) } /** @@ -109,6 +128,25 @@ final class HealthCheckSettings( val livenessPath: String, val checkTimeout: FiniteDuration) { + @deprecated("Use constructor that takes `startupChecks` and `startupPath` parameters instead", "1.1.0") + def this( + readinessChecks: immutable.Seq[NamedHealthCheck], + livenessChecks: immutable.Seq[NamedHealthCheck], + readinessPath: String, + livenessPath: String, + checkTimeout: FiniteDuration + ) = { + this( + Nil, + readinessChecks, + livenessChecks, + "", + readinessPath, + livenessPath, + checkTimeout + ) + } + /** * Java API */ diff --git a/management/src/test/java/org/apache/pekko/management/HealthCheckTest.java b/management/src/test/java/org/apache/pekko/management/HealthCheckTest.java index 4985a74d..ca951848 100644 --- a/management/src/test/java/org/apache/pekko/management/HealthCheckTest.java +++ b/management/src/test/java/org/apache/pekko/management/HealthCheckTest.java @@ -30,6 +30,7 @@ import org.apache.pekko.management.javadsl.HealthChecks; import org.apache.pekko.management.javadsl.LivenessCheckSetup; import org.apache.pekko.management.javadsl.ReadinessCheckSetup; +import org.apache.pekko.management.javadsl.StartupCheckSetup; import org.apache.pekko.testkit.javadsl.TestKit; import org.junit.AfterClass; import org.junit.Assert; @@ -85,8 +86,10 @@ public void okReturnsTrue() throws Exception { "ready", "alive", java.time.Duration.ofSeconds(1))); + assertEquals(true, checks.startupResult().toCompletableFuture().get().isSuccess()); assertEquals(true, checks.aliveResult().toCompletableFuture().get().isSuccess()); assertEquals(true, checks.readyResult().toCompletableFuture().get().isSuccess()); + assertEquals(true, checks.startup().toCompletableFuture().get()); assertEquals(true, checks.alive().toCompletableFuture().get()); assertEquals(true, checks.ready().toCompletableFuture().get()); } @@ -107,8 +110,28 @@ public void notOkayReturnsFalse() throws Exception { "ready", "alive", java.time.Duration.ofSeconds(1))); + assertEquals(true, checks.startupResult().toCompletableFuture().get().isSuccess()); assertEquals(true, checks.aliveResult().toCompletableFuture().get().isSuccess()); assertEquals(true, checks.readyResult().toCompletableFuture().get().isSuccess()); + assertEquals(true, checks.startup().toCompletableFuture().get()); + assertEquals(true, checks.alive().toCompletableFuture().get()); + assertEquals(true, checks.ready().toCompletableFuture().get()); + } + + @Test + public void creatableThroughLegacyConstructor() throws Exception { + List healthChecks = + Collections.singletonList( + new NamedHealthCheck("Ok", "org.apache.pekko.management.HealthCheckTest$Ok")); + HealthChecks checks = + new HealthChecks( + system, + HealthCheckSettings.create( + healthChecks, healthChecks, "ready", "alive", java.time.Duration.ofSeconds(1))); + assertEquals(true, checks.startupResult().toCompletableFuture().get().isSuccess()); + assertEquals(true, checks.aliveResult().toCompletableFuture().get().isSuccess()); + assertEquals(true, checks.readyResult().toCompletableFuture().get().isSuccess()); + assertEquals(true, checks.startup().toCompletableFuture().get()); assertEquals(true, checks.alive().toCompletableFuture().get()); assertEquals(true, checks.ready().toCompletableFuture().get()); } @@ -139,6 +162,8 @@ public void throwsReturnsFailed() throws Exception { @Test public void defineViaActorSystemSetup() throws Exception { + StartupCheckSetup startupCheckSetup = + StartupCheckSetup.create(system -> Collections.singletonList(new NotOk(system))); ReadinessCheckSetup readinessSetup = ReadinessCheckSetup.create(system -> Arrays.asList(new Ok(), new NotOk(system))); LivenessCheckSetup livenessSetup = @@ -146,7 +171,7 @@ public void defineViaActorSystemSetup() throws Exception { // bootstrapSetup is needed for config (otherwise default config) BootstrapSetup bootstrapSetup = BootstrapSetup.create(ConfigFactory.parseString("some=thing")); ActorSystemSetup actorSystemSetup = - ActorSystemSetup.create(bootstrapSetup, readinessSetup, livenessSetup); + ActorSystemSetup.create(bootstrapSetup, startupCheckSetup, readinessSetup, livenessSetup); ExtendedActorSystem sys2 = (ExtendedActorSystem) ActorSystem.create("HealthCheckTest2", actorSystemSetup); try { @@ -161,8 +186,10 @@ public void defineViaActorSystemSetup() throws Exception { "ready", "alive", java.time.Duration.ofSeconds(1))); + assertEquals(false, checks.startupResult().toCompletableFuture().get().isSuccess()); assertEquals(false, checks.aliveResult().toCompletableFuture().get().isSuccess()); assertEquals(false, checks.readyResult().toCompletableFuture().get().isSuccess()); + assertEquals(false, checks.startup().toCompletableFuture().get()); assertEquals(false, checks.alive().toCompletableFuture().get()); assertEquals(false, checks.ready().toCompletableFuture().get()); } finally { diff --git a/management/src/test/scala/org/apache/pekko/management/HealthCheckSettingsSpec.scala b/management/src/test/scala/org/apache/pekko/management/HealthCheckSettingsSpec.scala index 1b9e62d7..ae7aee8d 100644 --- a/management/src/test/scala/org/apache/pekko/management/HealthCheckSettingsSpec.scala +++ b/management/src/test/scala/org/apache/pekko/management/HealthCheckSettingsSpec.scala @@ -13,10 +13,15 @@ package org.apache.pekko.management +import scala.annotation.nowarn +import scala.concurrent.duration.DurationInt +import scala.jdk.CollectionConverters.SeqHasAsJava + import com.typesafe.config.ConfigFactory import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec +@nowarn("msg=deprecated") class HealthCheckSettingsSpec extends AnyWordSpec with Matchers { "Health Check Settings" should { @@ -55,6 +60,38 @@ class HealthCheckSettingsSpec extends AnyWordSpec with Matchers { check-timeout = 1s """)).livenessChecks shouldEqual Nil } + + "be creatable with primary constructor" in { + HealthCheckSettings.create( + startupChecks = Seq.empty[NamedHealthCheck].asJava, + readinessChecks = Seq.empty[NamedHealthCheck].asJava, + livenessChecks = Seq.empty[NamedHealthCheck].asJava, + startupPath = "", + readinessPath = "", + livenessPath = "", + checkDuration = java.time.Duration.ofSeconds(1L)) + .startupChecks shouldEqual Nil + } + + "be creatable with legacy create method" in { + HealthCheckSettings.create( + readinessChecks = Seq.empty[NamedHealthCheck].asJava, + livenessChecks = Seq.empty[NamedHealthCheck].asJava, + readinessPath = "", + livenessPath = "", + checkDuration = java.time.Duration.ofSeconds(1L)) + .startupChecks shouldEqual Nil + } + + "be creatable with legacy constructor" in { + val healthCheckSettings = new HealthCheckSettings( + readinessChecks = Nil, + livenessChecks = Nil, + readinessPath = "", + livenessPath = "", + checkTimeout = 1.seconds) + healthCheckSettings.livenessChecks shouldEqual Nil + } } } diff --git a/management/src/test/scala/org/apache/pekko/management/HealthChecksSpec.scala b/management/src/test/scala/org/apache/pekko/management/HealthChecksSpec.scala index 6ce9e33e..40e0d410 100644 --- a/management/src/test/scala/org/apache/pekko/management/HealthChecksSpec.scala +++ b/management/src/test/scala/org/apache/pekko/management/HealthChecksSpec.scala @@ -121,8 +121,10 @@ class HealthChecksSpec "HealthCheck" should { "succeed by default" in { val checks = HealthChecks(eas, settings(Nil, Nil, Nil)) + checks.startupResult().futureValue shouldEqual Right(()) checks.aliveResult().futureValue shouldEqual Right(()) checks.readyResult().futureValue shouldEqual Right(()) + checks.startup().futureValue shouldEqual true checks.alive().futureValue shouldEqual true checks.ready().futureValue shouldEqual true } @@ -133,8 +135,10 @@ class HealthChecksSpec im.Seq(OkCheck), im.Seq(OkCheck), im.Seq(OkCheck))) + checks.startupResult().futureValue shouldEqual Right(()) checks.aliveResult().futureValue shouldEqual Right(()) checks.readyResult().futureValue shouldEqual Right(()) + checks.startup().futureValue shouldEqual true checks.alive().futureValue shouldEqual true checks.ready().futureValue shouldEqual true } @@ -145,8 +149,10 @@ class HealthChecksSpec im.Seq(NoArgsCtrCheck), im.Seq(NoArgsCtrCheck), im.Seq(NoArgsCtrCheck))) + checks.startupResult().futureValue shouldEqual Right(()) checks.aliveResult().futureValue shouldEqual Right(()) checks.readyResult().futureValue shouldEqual Right(()) + checks.startup().futureValue shouldEqual true checks.alive().futureValue shouldEqual true checks.ready().futureValue shouldEqual true } @@ -157,8 +163,10 @@ class HealthChecksSpec im.Seq(FalseCheck), im.Seq(FalseCheck), im.Seq(FalseCheck))) + checks.startupResult().futureValue.isRight shouldEqual false checks.readyResult().futureValue.isRight shouldEqual false checks.aliveResult().futureValue.isRight shouldEqual false + checks.startup().futureValue shouldEqual false checks.ready().futureValue shouldEqual false checks.alive().futureValue shouldEqual false } @@ -169,10 +177,14 @@ class HealthChecksSpec im.Seq(ThrowsCheck), im.Seq(ThrowsCheck), im.Seq(ThrowsCheck))) + checks.startupResult().failed.futureValue shouldEqual + CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) checks.readyResult().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) checks.aliveResult().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) + checks.startup().failed.futureValue shouldEqual + CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) checks.ready().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) checks.alive().failed.futureValue shouldEqual @@ -184,10 +196,14 @@ class HealthChecksSpec ThrowsCheck, FalseCheck) val hc = HealthChecks(eas, settings(checks, checks, checks)) + hc.startupResult().failed.futureValue shouldEqual + CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) hc.readyResult().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) hc.aliveResult().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) + hc.startup().failed.futureValue shouldEqual + CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) hc.ready().failed.futureValue shouldEqual CheckFailedException("Check [org.apache.pekko.management.Throws] failed: null", failedCause) hc.alive().failed.futureValue shouldEqual @@ -197,8 +213,10 @@ class HealthChecksSpec val checks = im.Seq( NaughtyCheck) val hc = HealthChecks(eas, settings(checks, checks, checks)) + hc.startupResult().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" hc.readyResult().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" hc.aliveResult().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" + hc.startup().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" hc.ready().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" hc.alive().failed.futureValue.getMessage shouldEqual "Check [org.apache.pekko.management.Naughty] failed: bad" } @@ -207,10 +225,14 @@ class HealthChecksSpec SlowCheck, OkCheck) val hc = HealthChecks(eas, settings(checks, checks, checks)) + Await.result(hc.startupResult().failed, 1.second) shouldEqual CheckTimeoutException( + "Check [org.apache.pekko.management.Slow] timed out after 500 milliseconds") Await.result(hc.readyResult().failed, 1.second) shouldEqual CheckTimeoutException( "Check [org.apache.pekko.management.Slow] timed out after 500 milliseconds") Await.result(hc.aliveResult().failed, 1.second) shouldEqual CheckTimeoutException( "Check [org.apache.pekko.management.Slow] timed out after 500 milliseconds") + Await.result(hc.startup().failed, 1.second) shouldEqual CheckTimeoutException( + "Check [org.apache.pekko.management.Slow] timed out after 500 milliseconds") Await.result(hc.ready().failed, 1.second) shouldEqual CheckTimeoutException( "Check [org.apache.pekko.management.Slow] timed out after 500 milliseconds") Await.result(hc.alive().failed, 1.second) shouldEqual CheckTimeoutException(