From 749e8d56043dc3f99d0283345bc599ca12d3fa36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinbo=CC=88lting?= Date: Mon, 12 Dec 2022 13:10:37 +0100 Subject: [PATCH 1/2] chore: simplify health route setup Turn Health Route into object and remove redundant indirection --- .../webapi/core/HttpServerWithZIOHttp.scala | 15 ++- .../org/knora/webapi/core/LayersLive.scala | 8 +- .../webapi/routing/ApiRoutesWithZIOHttp.scala | 33 ----- .../routing/HealthRouteWithZIOHttp.scala | 114 ++++++------------ 4 files changed, 44 insertions(+), 126 deletions(-) delete mode 100644 webapi/src/main/scala/org/knora/webapi/routing/ApiRoutesWithZIOHttp.scala diff --git a/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala b/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala index 8f05108009..528a5785a4 100644 --- a/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala +++ b/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala @@ -5,20 +5,19 @@ package org.knora.webapi.core -import zhttp.service.Server -import zio.ZLayer -import zio._ - import org.knora.webapi.config.AppConfig -import org.knora.webapi.core._ -import org.knora.webapi.routing.ApiRoutesWithZIOHttp +import org.knora.webapi.routing.HealthRouteWithZIOHttp +import zhttp.service.Server +import zio.{ZLayer, _} object HttpServerWithZIOHttp { - val layer: ZLayer[AppConfig & State & ApiRoutesWithZIOHttp, Nothing, Unit] = + + val routes = HealthRouteWithZIOHttp() + + val layer: ZLayer[AppConfig & State, Nothing, Unit] = ZLayer { for { appConfig <- ZIO.service[AppConfig] - routes <- ZIO.service[ApiRoutesWithZIOHttp].map(_.routes) port = appConfig.knoraApi.externalZioPort _ <- Server.start(port, routes).forkDaemon _ <- ZIO.logInfo(">>> Acquire ZIO HTTP Server <<<") diff --git a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala index b7334aa838..24b5da23bd 100644 --- a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala @@ -5,14 +5,9 @@ package org.knora.webapi.core -import zio.ULayer -import zio.ZLayer - import org.knora.webapi.auth.JWTService import org.knora.webapi.config.AppConfig import org.knora.webapi.routing.ApiRoutes -import org.knora.webapi.routing.ApiRoutesWithZIOHttp -import org.knora.webapi.routing.HealthRouteWithZIOHttp import org.knora.webapi.store.cache.CacheServiceManager import org.knora.webapi.store.cache.api.CacheService import org.knora.webapi.store.cache.impl.CacheServiceInMemImpl @@ -23,6 +18,7 @@ import org.knora.webapi.store.triplestore.TriplestoreServiceManager import org.knora.webapi.store.triplestore.api.TriplestoreService import org.knora.webapi.store.triplestore.impl.TriplestoreServiceHttpConnectorImpl import org.knora.webapi.store.triplestore.upgrade.RepositoryUpdater +import zio.{ULayer, ZLayer} object LayersLive { @@ -52,8 +48,6 @@ object LayersLive { ZLayer.make[DspEnvironmentLive]( ActorSystem.layer, ApiRoutes.layer, - ApiRoutesWithZIOHttp.layer, // this is the new layer that composes all new routes - HealthRouteWithZIOHttp.layer, // this is the new health route AppConfig.live, AppRouter.layer, CacheServiceManager.layer, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/ApiRoutesWithZIOHttp.scala b/webapi/src/main/scala/org/knora/webapi/routing/ApiRoutesWithZIOHttp.scala deleted file mode 100644 index 8efd0f9317..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/routing/ApiRoutesWithZIOHttp.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.routing - -import zhttp.http._ -import zio.ZLayer - -import org.knora.webapi.core._ - -/** - * The accumulated routes - * - * @param healthRoute - */ -final case class ApiRoutesWithZIOHttp( - healthRoute: HealthRouteWithZIOHttp -) { - // adds up all the routes - val routes: HttpApp[State, Nothing] = - healthRoute.route // TODO add more routes here with `++ projectRoutes.routes` - -} - -/** - * The layer providing all instantiated routes - */ -object ApiRoutesWithZIOHttp { - val layer: ZLayer[HealthRouteWithZIOHttp, Nothing, ApiRoutesWithZIOHttp] = - ZLayer.fromFunction(ApiRoutesWithZIOHttp.apply _) -} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala b/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala index 55477b3f1a..bf5cf73563 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala @@ -5,64 +5,49 @@ package org.knora.webapi.routing -import spray.json.JsObject -import spray.json.JsString -import zhttp.http._ -import zio._ - import org.knora.webapi.core.State import org.knora.webapi.core.domain.AppState +import spray.json.{JsObject, JsString} +import zhttp.http._ +import zio._ /** - * Provides health check logic + * Provides the '/healthZ' endpoint serving the health status. */ -trait HealthCheckWithZIOHttp { +object HealthRouteWithZIOHttp { - /** - * gets the application state from a state service called `State` - * - * @param state the state service - * @return a response with the application state - */ - protected def healthCheck(state: State): UIO[Response] = - for { - _ <- ZIO.logDebug("get application state") - state <- state.getAppState - result <- setHealthState(state) - _ <- ZIO.logDebug("set health state") - response <- createResponse(result) - _ <- ZIO.logDebug("getting application state done") - } yield response + def apply(): HttpApp[State, Nothing] = + Http.collectZIO[Request] { case Method.GET -> !! / "healthZ" => + State.getAppState.map(toHealthCheckResult).flatMap(createResponse) + } /** - * sets the application's health state to healthy or unhealthy according to the provided state + * Transforms the [[AppState]] into a [[HealthCheckResult]] * * @param state the application's state - * @return the result which is either unhealthy or healthy + * @return the result which is either unhealthy or healthy, containing a human readable explanation in case of unhealthy */ - private def setHealthState(state: AppState): UIO[HealthCheckResult] = - ZIO.succeed( - state match { - case AppState.Stopped => unhealthy("Stopped. Please retry later.") - case AppState.StartingUp => unhealthy("Starting up. Please retry later.") - case AppState.WaitingForTriplestore => unhealthy("Waiting for triplestore. Please retry later.") - case AppState.TriplestoreReady => unhealthy("Triplestore ready. Please retry later.") - case AppState.UpdatingRepository => unhealthy("Updating repository. Please retry later.") - case AppState.RepositoryUpToDate => unhealthy("Repository up to date. Please retry later.") - case AppState.CreatingCaches => unhealthy("Creating caches. Please retry later.") - case AppState.CachesReady => unhealthy("Caches ready. Please retry later.") - case AppState.UpdatingSearchIndex => unhealthy("Updating search index. Please retry later.") - case AppState.SearchIndexReady => unhealthy("Search index ready. Please retry later.") - case AppState.LoadingOntologies => unhealthy("Loading ontologies. Please retry later.") - case AppState.OntologiesReady => unhealthy("Ontologies ready. Please retry later.") - case AppState.WaitingForIIIFService => unhealthy("Waiting for IIIF service. Please retry later.") - case AppState.IIIFServiceReady => unhealthy("IIIF service ready. Please retry later.") - case AppState.WaitingForCacheService => unhealthy("Waiting for cache service. Please retry later.") - case AppState.CacheServiceReady => unhealthy("Cache service ready. Please retry later.") - case AppState.MaintenanceMode => unhealthy("Application is in maintenance mode. Please retry later.") - case AppState.Running => healthy - } - ) + private def toHealthCheckResult(state: AppState): HealthCheckResult = + state match { + case AppState.Stopped => unhealthy("Stopped. Please retry later.") + case AppState.StartingUp => unhealthy("Starting up. Please retry later.") + case AppState.WaitingForTriplestore => unhealthy("Waiting for triplestore. Please retry later.") + case AppState.TriplestoreReady => unhealthy("Triplestore ready. Please retry later.") + case AppState.UpdatingRepository => unhealthy("Updating repository. Please retry later.") + case AppState.RepositoryUpToDate => unhealthy("Repository up to date. Please retry later.") + case AppState.CreatingCaches => unhealthy("Creating caches. Please retry later.") + case AppState.CachesReady => unhealthy("Caches ready. Please retry later.") + case AppState.UpdatingSearchIndex => unhealthy("Updating search index. Please retry later.") + case AppState.SearchIndexReady => unhealthy("Search index ready. Please retry later.") + case AppState.LoadingOntologies => unhealthy("Loading ontologies. Please retry later.") + case AppState.OntologiesReady => unhealthy("Ontologies ready. Please retry later.") + case AppState.WaitingForIIIFService => unhealthy("Waiting for IIIF service. Please retry later.") + case AppState.IIIFServiceReady => unhealthy("IIIF service ready. Please retry later.") + case AppState.WaitingForCacheService => unhealthy("Waiting for cache service. Please retry later.") + case AppState.CacheServiceReady => unhealthy("Cache service ready. Please retry later.") + case AppState.MaintenanceMode => unhealthy("Application is in maintenance mode. Please retry later.") + case AppState.Running => healthy + } /** * creates the HTTP response from the health check result (healthy/unhealthy) @@ -103,10 +88,10 @@ trait HealthCheckWithZIOHttp { /** * The result of a health check which is either unhealthy or healthy. * - * @param name ??? - * @param severity ??? - * @param status the status (either false = unhealthy or true = healthy) - * @param message the message + * @param name ??? + * @param severity ??? + * @param status the status (either false = unhealthy or true = healthy) + * @param message the message */ private case class HealthCheckResult(name: String, severity: String, status: Boolean, message: String) @@ -126,30 +111,3 @@ trait HealthCheckWithZIOHttp { message = "Application is healthy" ) } - -/** - * Provides the '/healthZ' endpoint serving the health status. - */ -final case class HealthRouteWithZIOHttp(state: State) extends HealthCheckWithZIOHttp { - - /** - * Returns the route. - */ - val route: HttpApp[State, Nothing] = - Http.collectZIO[Request] { case Method.GET -> !! / "healthZ" => - for { - // ec <- ZIO.executor.map(_.asExecutionContext) // leave this for reference about how to get the execution context - state <- ZIO.service[State] - response <- healthCheck(state) - } yield response - - } -} - -/** - * Companion object providing the layer - */ -object HealthRouteWithZIOHttp { - val layer: ZLayer[State, Nothing, HealthRouteWithZIOHttp] = - ZLayer.fromFunction(HealthRouteWithZIOHttp.apply _) -} From 6adba1ef5069d87bae8ad664eb10fc8027041336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinbo=CC=88lting?= Date: Mon, 12 Dec 2022 13:31:55 +0100 Subject: [PATCH 2/2] formatting --- .../org/knora/webapi/core/HttpServerWithZIOHttp.scala | 6 ++++-- .../src/main/scala/org/knora/webapi/core/LayersLive.scala | 4 +++- .../org/knora/webapi/routing/HealthRouteWithZIOHttp.scala | 8 +++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala b/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala index 528a5785a4..3cf16f33e5 100644 --- a/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala +++ b/webapi/src/main/scala/org/knora/webapi/core/HttpServerWithZIOHttp.scala @@ -5,10 +5,12 @@ package org.knora.webapi.core +import zhttp.service.Server +import zio.ZLayer +import zio._ + import org.knora.webapi.config.AppConfig import org.knora.webapi.routing.HealthRouteWithZIOHttp -import zhttp.service.Server -import zio.{ZLayer, _} object HttpServerWithZIOHttp { diff --git a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala index 24b5da23bd..d45fb48dc0 100644 --- a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala @@ -5,6 +5,9 @@ package org.knora.webapi.core +import zio.ULayer +import zio.ZLayer + import org.knora.webapi.auth.JWTService import org.knora.webapi.config.AppConfig import org.knora.webapi.routing.ApiRoutes @@ -18,7 +21,6 @@ import org.knora.webapi.store.triplestore.TriplestoreServiceManager import org.knora.webapi.store.triplestore.api.TriplestoreService import org.knora.webapi.store.triplestore.impl.TriplestoreServiceHttpConnectorImpl import org.knora.webapi.store.triplestore.upgrade.RepositoryUpdater -import zio.{ULayer, ZLayer} object LayersLive { diff --git a/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala b/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala index bf5cf73563..aa7ac232e4 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/HealthRouteWithZIOHttp.scala @@ -5,12 +5,14 @@ package org.knora.webapi.routing -import org.knora.webapi.core.State -import org.knora.webapi.core.domain.AppState -import spray.json.{JsObject, JsString} +import spray.json.JsObject +import spray.json.JsString import zhttp.http._ import zio._ +import org.knora.webapi.core.State +import org.knora.webapi.core.domain.AppState + /** * Provides the '/healthZ' endpoint serving the health status. */