From 1ecc3d006bacd27ae484d9accadb935bc74e1c06 Mon Sep 17 00:00:00 2001 From: Kai <450507+neko-kai@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:29:12 +0100 Subject: [PATCH] Update to ZIO 2 & http4s 0.23.23 (#412) --- README.md | 1 - build.sbt | 9 ++++--- .../scala/leaderboard/api/ProfileApi.scala | 2 +- .../scala/leaderboard/http/HttpServer.scala | 18 ++++++------- .../leaderboard/WiringTest.scala | 0 src/test/scala/leaderboard/tests.scala | 8 +++--- src/test/scala/leaderboard/zioenv.scala | 27 ++++++++----------- 7 files changed, 29 insertions(+), 36 deletions(-) rename src/test/{scala-2 => scala}/leaderboard/WiringTest.scala (100%) diff --git a/README.md b/README.md index 7e6e339..17d43a2 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,3 @@ It seems like we've managed to build an exhaustive ruleset for `docker-java` so If something is wrong and you need to generate the rules for `docker-java`, run the agent twice in both hot and cold state. - Only `PluginConfig.const` works reliably under Native Image. So, ClassGraph analysis is disabled in `ni-filter.json`. You can't make dynamic plugin resolution working under Native Image. - diff --git a/build.sbt b/build.sbt index ab602d1..834bf9a 100644 --- a/build.sbt +++ b/build.sbt @@ -3,11 +3,11 @@ val V = new { val logstage = distage val scalatest = "3.2.17" val scalacheck = "1.17.0" - val http4s = "0.23.15" + val http4s = "0.23.23" val doobie = "1.0.0-RC4" val catsCore = "2.10.0" val zio = "2.0.18" - val zioCats = "13.0.0.2" + val zioCats = "23.0.0.8" val kindProjector = "0.13.2" val circeGeneric = "0.14.6" val graalMetadata = "0.9.27" @@ -25,8 +25,8 @@ val Deps = new { val logstageSlf4j = "io.7mind.izumi" %% "logstage-adapter-slf4j" % V.logstage val http4sDsl = "org.http4s" %% "http4s-dsl" % V.http4s - val http4sServer = "org.http4s" %% "http4s-blaze-server" % V.http4s - val http4sClient = "org.http4s" %% "http4s-blaze-client" % V.http4s + val http4sServer = "org.http4s" %% "http4s-ember-server" % V.http4s + val http4sClient = "org.http4s" %% "http4s-ember-client" % V.http4s val http4sCirce = "org.http4s" %% "http4s-circe" % V.http4s val circeGeneric = "io.circe" %% "circe-generic" % V.circeGeneric @@ -93,6 +93,7 @@ lazy val leaderboard = project }, scalacOptions -= "-Xfatal-warnings", scalacOptions -= "-Ykind-projector", + scalacOptions -= "-Wnonunit-statement", scalacOptions ++= { if (scalaVersion.value.startsWith("2")) { Seq( diff --git a/src/main/scala/leaderboard/api/ProfileApi.scala b/src/main/scala/leaderboard/api/ProfileApi.scala index 0c745cd..2d5e18e 100644 --- a/src/main/scala/leaderboard/api/ProfileApi.scala +++ b/src/main/scala/leaderboard/api/ProfileApi.scala @@ -28,7 +28,7 @@ final class ProfileApi[F[+_, +_]: Async2: Fork2: Primitives2]( case rq @ POST -> Root / "profile" / UUIDVar(userId) => Ok(for { profile <- rq.decodeJson[UserProfile] - _ <- log.info(s"Sending $profile") + _ <- log.info(s"Saving $profile") _ <- profiles.setProfile(userId, profile) } yield ()) } diff --git a/src/main/scala/leaderboard/http/HttpServer.scala b/src/main/scala/leaderboard/http/HttpServer.scala index 5c7426f..a8a2fb5 100644 --- a/src/main/scala/leaderboard/http/HttpServer.scala +++ b/src/main/scala/leaderboard/http/HttpServer.scala @@ -2,14 +2,13 @@ package leaderboard.http import cats.effect.Async import cats.implicits.* -import distage.Id +import com.comcast.ip4s.Port +import fs2.io.net.Network import izumi.distage.model.definition.Lifecycle import leaderboard.api.HttpApi -import org.http4s.blaze.server.BlazeServerBuilder +import org.http4s.ember.server.EmberServerBuilder import org.http4s.server.Server -import scala.concurrent.ExecutionContext - final case class HttpServer( server: Server ) @@ -17,19 +16,18 @@ final case class HttpServer( object HttpServer { final class Impl[F[+_, +_]]( - allHttpApis: Set[HttpApi[F]], - cpuPool: ExecutionContext @Id("cpu"), + allHttpApis: Set[HttpApi[F]] )(implicit async: Async[F[Throwable, _]] ) extends Lifecycle.Of[F[Throwable, _], HttpServer]( Lifecycle.fromCats { val combinedApis = allHttpApis.map(_.http).toList.foldK - BlazeServerBuilder[F[Throwable, _]] - .withExecutionContext(cpuPool) + EmberServerBuilder + .default(async, Network.forAsync) .withHttpApp(combinedApis.orNotFound) - .bindLocal(8080) - .resource + .withPort(Port.fromInt(8080).get) + .build .map(HttpServer(_)) } ) diff --git a/src/test/scala-2/leaderboard/WiringTest.scala b/src/test/scala/leaderboard/WiringTest.scala similarity index 100% rename from src/test/scala-2/leaderboard/WiringTest.scala rename to src/test/scala/leaderboard/WiringTest.scala diff --git a/src/test/scala/leaderboard/tests.scala b/src/test/scala/leaderboard/tests.scala index 6bf4a98..e9cac04 100644 --- a/src/test/scala/leaderboard/tests.scala +++ b/src/test/scala/leaderboard/tests.scala @@ -5,7 +5,7 @@ import izumi.distage.model.definition.Activation import izumi.distage.model.definition.StandardAxis.Repo import izumi.distage.plugins.PluginConfig import izumi.distage.testkit.scalatest.{AssertIO3, Spec3} -import leaderboard.model.{QueryFailure, RankedProfile, Score, UserId, UserProfile} +import leaderboard.model.* import leaderboard.repo.{Ladder, Profiles} import leaderboard.services.Ranks import leaderboard.zioenv.* @@ -86,7 +86,7 @@ abstract class LadderTest extends LeaderboardTest { assertIO(user1Rank < user2Rank) } else if (score2 > score1) { assertIO(user2Rank < user1Rank) - } else IO.unit + } else ZIO.unit } yield () } @@ -100,7 +100,7 @@ abstract class ProfilesTest extends LeaderboardTest { /** that's what the ZIO signature looks like for ZIO Env injection: */ "set & get" in { - val zioValue: ZIO[ProfilesEnv & RndEnv, QueryFailure, Unit] = for { + val zioValue: ZIO[Profiles[IO] & Rnd[IO], QueryFailure, Unit] = for { user <- rnd[UserId] name <- rnd[String] desc <- rnd[String] @@ -170,7 +170,7 @@ abstract class RanksTest extends LeaderboardTest { assertIO(user1Rank < user2Rank) } else if (score2 > score1) { assertIO(user2Rank < user1Rank) - } else IO.unit + } else ZIO.unit } yield () } diff --git a/src/test/scala/leaderboard/zioenv.scala b/src/test/scala/leaderboard/zioenv.scala index 17e2a62..ba04497 100644 --- a/src/test/scala/leaderboard/zioenv.scala +++ b/src/test/scala/leaderboard/zioenv.scala @@ -4,31 +4,26 @@ import leaderboard.model.* import leaderboard.repo.{Ladder, Profiles} import leaderboard.services.Ranks import org.scalacheck.Arbitrary -import zio.{Has, IO, URIO, ZIO} +import zio.{IO, URIO, ZIO} object zioenv { - object ladder extends Ladder[ZIO[LadderEnv, _, _]] { - def submitScore(userId: UserId, score: Score): ZIO[LadderEnv, QueryFailure, Unit] = ZIO.accessM(_.get.submitScore(userId, score)) - def getScores: ZIO[LadderEnv, QueryFailure, List[(UserId, Score)]] = ZIO.accessM(_.get.getScores) + object ladder extends Ladder[ZIO[Ladder[IO], _, _]] { + def submitScore(userId: UserId, score: Score): ZIO[Ladder[IO], QueryFailure, Unit] = ZIO.serviceWithZIO(_.submitScore(userId, score)) + def getScores: ZIO[Ladder[IO], QueryFailure, List[(UserId, Score)]] = ZIO.serviceWithZIO(_.getScores) } - object profiles extends Profiles[ZIO[ProfilesEnv, _, _]] { - override def setProfile(userId: UserId, profile: UserProfile): ZIO[ProfilesEnv, QueryFailure, Unit] = ZIO.accessM(_.get.setProfile(userId, profile)) - override def getProfile(userId: UserId): ZIO[ProfilesEnv, QueryFailure, Option[UserProfile]] = ZIO.accessM(_.get.getProfile(userId)) + object profiles extends Profiles[ZIO[Profiles[IO], _, _]] { + override def setProfile(userId: UserId, profile: UserProfile): ZIO[Profiles[IO], QueryFailure, Unit] = ZIO.serviceWithZIO(_.setProfile(userId, profile)) + override def getProfile(userId: UserId): ZIO[Profiles[IO], QueryFailure, Option[UserProfile]] = ZIO.serviceWithZIO(_.getProfile(userId)) } - object ranks extends Ranks[ZIO[RanksEnv, _, _]] { - override def getRank(userId: UserId): ZIO[RanksEnv, QueryFailure, Option[RankedProfile]] = ZIO.accessM(_.get.getRank(userId)) + object ranks extends Ranks[ZIO[Ranks[IO], _, _]] { + override def getRank(userId: UserId): ZIO[Ranks[IO], QueryFailure, Option[RankedProfile]] = ZIO.serviceWithZIO(_.getRank(userId)) } - object rnd extends Rnd[ZIO[RndEnv, _, _]] { - override def apply[A: Arbitrary]: URIO[RndEnv, A] = ZIO.accessM(_.get.apply[A]) + object rnd extends Rnd[ZIO[Rnd[IO], _, _]] { + override def apply[A: Arbitrary]: URIO[Rnd[IO], A] = ZIO.serviceWithZIO(_.apply[A]) } - type LadderEnv = Has[Ladder[IO]] - type ProfilesEnv = Has[Profiles[IO]] - type RanksEnv = Has[Ranks[IO]] - type RndEnv = Has[Rnd[IO]] - }