From fd336ab3ecee3d9cdf367820beacf2817d120ef3 Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 2 Oct 2024 18:43:14 +0500 Subject: [PATCH 1/6] - Created an extension for HealthCheckRoutes, so users can get the routes and add it to their own server --- .../pekko/management/HealthCheckRoutes.scala | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala index 61ec3a70..37d6fe69 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala @@ -14,12 +14,18 @@ package org.apache.pekko.management import org.apache.pekko -import pekko.actor.ExtendedActorSystem -import pekko.annotation.InternalApi -import pekko.http.scaladsl.model._ -import pekko.http.scaladsl.server.Directives._ -import pekko.http.scaladsl.server.{ PathMatchers, Route } -import pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, ManagementRouteProviderSettings } +import org.apache.pekko.actor.{ + ActorSystem, + ClassicActorSystemProvider, + ExtendedActorSystem, + ExtensionId, + ExtensionIdProvider +} +import org.apache.pekko.annotation.InternalApi +import org.apache.pekko.http.scaladsl.model._ +import org.apache.pekko.http.scaladsl.server.Directives._ +import org.apache.pekko.http.scaladsl.server.{ PathMatchers, Route } +import org.apache.pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, ManagementRouteProviderSettings } import scala.util.{ Failure, Success, Try } @@ -47,7 +53,12 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana StatusCodes.InternalServerError -> s"Health Check Failed: ${t.getMessage}") } - override def routes(mrps: ManagementRouteProviderSettings): Route = { + override def routes(mrps: ManagementRouteProviderSettings): Route = routes() + + // overload method, so user can get the routes without have to unnecessarily provide the + // settings + + def routes(): Route = { concat( path(PathMatchers.separateOnSlashes(settings.startupPath)) { get { @@ -66,3 +77,16 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana }) } } + +/** + * Providing an extension, so users can get the routes and add it to their own server + */ +object HealthCheckRoutes extends ExtensionId[HealthCheckRoutes] with ExtensionIdProvider { + override def get(system: ActorSystem): HealthCheckRoutes = super.get(system) + + override def get(system: ClassicActorSystemProvider): HealthCheckRoutes = super.get(system) + + override def lookup: HealthCheckRoutes.type = HealthCheckRoutes + + override def createExtension(system: ExtendedActorSystem): HealthCheckRoutes = new HealthCheckRoutes(system) +} From 3be732ab728596739784d0437a3942b785f53313 Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 2 Oct 2024 18:47:06 +0500 Subject: [PATCH 2/6] - optimized imports --- .../pekko/management/HealthCheckRoutes.scala | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala index 37d6fe69..01fd8605 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala @@ -14,18 +14,12 @@ package org.apache.pekko.management import org.apache.pekko -import org.apache.pekko.actor.{ - ActorSystem, - ClassicActorSystemProvider, - ExtendedActorSystem, - ExtensionId, - ExtensionIdProvider -} -import org.apache.pekko.annotation.InternalApi -import org.apache.pekko.http.scaladsl.model._ -import org.apache.pekko.http.scaladsl.server.Directives._ -import org.apache.pekko.http.scaladsl.server.{ PathMatchers, Route } -import org.apache.pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, ManagementRouteProviderSettings } +import pekko.actor.{ ActorSystem, ClassicActorSystemProvider, ExtendedActorSystem, ExtensionId, ExtensionIdProvider } +import pekko.annotation.InternalApi +import pekko.http.scaladsl.model._ +import pekko.http.scaladsl.server.Directives._ +import pekko.http.scaladsl.server.{ PathMatchers, Route } +import pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, ManagementRouteProviderSettings } import scala.util.{ Failure, Success, Try } From c2bb457b10546a454246036b9ec57e7554aff460 Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 2 Oct 2024 19:50:46 +0500 Subject: [PATCH 3/6] - updated scaladoc --- .../org/apache/pekko/management/HealthCheckRoutes.scala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala index 01fd8605..251e4bf1 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala @@ -24,10 +24,7 @@ import pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, Manage import scala.util.{ Failure, Success, Try } /** - * INTERNAL API - * - * We could make this public so users can add it to their own server, not sure - * for ManagementRouteProviders + * @since 1.1.0 Users can use [[HealthCheckRoutes]] extension to add the routes to their own server. */ @InternalApi private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends ManagementRouteProvider { @@ -49,9 +46,6 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana override def routes(mrps: ManagementRouteProviderSettings): Route = routes() - // overload method, so user can get the routes without have to unnecessarily provide the - // settings - def routes(): Route = { concat( path(PathMatchers.separateOnSlashes(settings.startupPath)) { @@ -73,6 +67,7 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana } /** + * @since 1.1.0 * Providing an extension, so users can get the routes and add it to their own server */ object HealthCheckRoutes extends ExtensionId[HealthCheckRoutes] with ExtensionIdProvider { From 3cad9415c39c8d39b82c337967ad191d6e46e7f0 Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 2 Oct 2024 20:03:05 +0500 Subject: [PATCH 4/6] - updated scaladoc --- .../org/apache/pekko/management/HealthCheckRoutes.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala index 251e4bf1..9a44fcce 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala @@ -24,7 +24,10 @@ import pekko.management.scaladsl.{ HealthChecks, ManagementRouteProvider, Manage import scala.util.{ Failure, Success, Try } /** - * @since 1.1.0 Users can use [[HealthCheckRoutes]] extension to add the routes to their own server. + * INTERNAL API + * + * We could make this public so users can add it to their own server, not sure + * for ManagementRouteProviders */ @InternalApi private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends ManagementRouteProvider { @@ -46,6 +49,9 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana override def routes(mrps: ManagementRouteProviderSettings): Route = routes() + /** + * @since 1.1.0 + */ def routes(): Route = { concat( path(PathMatchers.separateOnSlashes(settings.startupPath)) { @@ -68,7 +74,6 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana /** * @since 1.1.0 - * Providing an extension, so users can get the routes and add it to their own server */ object HealthCheckRoutes extends ExtensionId[HealthCheckRoutes] with ExtensionIdProvider { override def get(system: ActorSystem): HealthCheckRoutes = super.get(system) From 95d1b4418ccfbf9fc6e3b7a6da1648619bce5af4 Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 2 Oct 2024 20:40:27 +0500 Subject: [PATCH 5/6] - updated scaladoc --- .../scala/org/apache/pekko/management/HealthCheckRoutes.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala index 9a44fcce..8e090964 100644 --- a/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala +++ b/management/src/main/scala/org/apache/pekko/management/HealthCheckRoutes.scala @@ -73,6 +73,7 @@ private[pekko] class HealthCheckRoutes(system: ExtendedActorSystem) extends Mana } /** + * Providing an extension, so users can get the routes and add it to their own server * @since 1.1.0 */ object HealthCheckRoutes extends ExtensionId[HealthCheckRoutes] with ExtensionIdProvider { From 6a2f13cce257f6807d0cd407ab883a937ac1c2df Mon Sep 17 00:00:00 2001 From: HP Date: Wed, 20 Nov 2024 16:59:50 +0500 Subject: [PATCH 6/6] - added unit test --- .../management/HealthCheckRoutesSpec.scala | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/management/src/test/scala/org/apache/pekko/management/HealthCheckRoutesSpec.scala b/management/src/test/scala/org/apache/pekko/management/HealthCheckRoutesSpec.scala index de08ce17..747feed9 100644 --- a/management/src/test/scala/org/apache/pekko/management/HealthCheckRoutesSpec.scala +++ b/management/src/test/scala/org/apache/pekko/management/HealthCheckRoutesSpec.scala @@ -28,7 +28,7 @@ class HealthCheckRoutesSpec extends AnyWordSpec with Matchers with ScalatestRout private val eas = system.asInstanceOf[ExtendedActorSystem] - private def testRoute( + private def testRouteWithProviderSettings( startupResultValue: Future[Either[String, Unit]] = Future.successful(Right(())), readyResultValue: Future[Either[String, Unit]] = Future.successful(Right(())), aliveResultValue: Future[Either[String, Unit]] = Future.successful(Right(()))): Route = { @@ -44,12 +44,33 @@ class HealthCheckRoutesSpec extends AnyWordSpec with Matchers with ScalatestRout }.routes(ManagementRouteProviderSettings(Uri("http://whocares"), readOnly = false)) } + private def testRoute( + startupResultValue: Future[Either[String, Unit]] = Future.successful(Right(())), + readyResultValue: Future[Either[String, Unit]] = Future.successful(Right(())), + aliveResultValue: Future[Either[String, Unit]] = Future.successful(Right(()))): Route = { + new HealthCheckRoutes(eas) { + override protected val healthChecks: HealthChecks = new HealthChecks { + override def startupResult(): Future[Either[String, Unit]] = startupResultValue + override def startup(): Future[Boolean] = startupResultValue.map(_.isRight) + override def readyResult(): Future[Either[String, Unit]] = readyResultValue + override def ready(): Future[Boolean] = readyResultValue.map(_.isRight) + override def aliveResult(): Future[Either[String, Unit]] = aliveResultValue + override def alive(): Future[Boolean] = aliveResultValue.map(_.isRight) + } + }.routes() + } + tests("/startup", result => testRoute(startupResultValue = result)) tests("/ready", result => testRoute(readyResultValue = result)) tests("/alive", result => testRoute(aliveResultValue = result)) - def tests(endpoint: String, route: Future[Either[String, Unit]] => Route) = { - s"Health check $endpoint endpoint" should { + // testRoutes with provider settings + tests("/startup", result => testRouteWithProviderSettings(startupResultValue = result), withSettings = true) + tests("/ready", result => testRouteWithProviderSettings(readyResultValue = result), withSettings = true) + tests("/alive", result => testRouteWithProviderSettings(aliveResultValue = result), withSettings = true) + + def tests(endpoint: String, route: Future[Either[String, Unit]] => Route, withSettings: Boolean = false) = { + s"Health check $endpoint endpoint - withSettingsProvided: $withSettings" should { "return 200 for Right" in { Get(endpoint) ~> route(Future.successful(Right(()))) ~> check { status shouldEqual StatusCodes.OK