问题描述
请帮助我使用ZLayers定义http4s。我正在学习,我很困惑。我想将http服务器作为一个组件。但是我不知道如何组合ZManageds和ZLayers以便能够进行编译。
创建需要Runtime[ZEnv]
的图层也有意义吗?或者,创建需要ZEnv
的图层并为其生成运行时是否更有意义?
object HttpServer {
def createHttp4Server: ZManaged[Runtime[ZEnv],Throwable,Server] =
ZManaged.accessManaged { implicit runtime: Runtime[ZEnv] =>
BlazeServerBuilder[Task](runtime.platform.executor.asEC)
.bindHttp(8080,"localhost")
.withHttpApp(Routes.helloWorldService)
.resource
.toManagedZIO
}
def createHttp4Layer: ZLayer[RuntimeLayer,Http4ServerLayer] =
ZLayer.succeed(createHttp4Server)
}
object Routes {
val helloWorldService = ...
}
package object simple {
type Http4ServerLayer = Has[ZManaged[Runtime[ZEnv],Server]]
type RuntimeLayer = Has[Runtime[ZEnv]]
}
我不知道如何从这里的ZManaged[...,...,Server]
访问Layer
。
我不完全了解access
方法。
object ItsAren extends App {
def run(args: List[String]): URIO[ZEnv,ExitCode] = {
val toProvide: ZIO[Http4ServerLayer,Nothing,ExitCode] =
ZIO
.accessM[Http4ServerLayer](_.get.useForever) //compile error
.as(ExitCode.success)
.catchAll(ZIO.succeed(ExitCode.failure))
val runtimeLayer: ZLayer[Any,RuntimeLayer] = ZLayer.succeed(Runtime.default)
val http4Layer: ZLayer[RuntimeLayer,Http4ServerLayer] = HttpServer.createHttp4Layer
val fullLayer: ZLayer[Any,Http4ServerLayer] = runtimeLayer >>> http4Layer
val provided = toProvide.provideCustomLayer(fullLayer)
provided //compile error
}
}
type mismatch
found : ZIO[Runtime[ZEnv],Nothing]
required: ZIO[Http4ServerLayer,?,?]
也位于底部,但是重要性较低
found : ZIO[ZEnv,ExitCode]
required: URIO[ZEnv,ExitCode]
PR中的相同内容,请随时发表评论 https://github.com/kovacshuni/itsaren/pull/1
解决方法
解决方案是ZLayer持有托管对象时本身就是托管对象。因此,当某些东西在这样的层上运行时,将在这段时间内使用包含的Managed。因此,如果您在层上运行ZIO.never
,则服务器将保持活动状态。
构建图层本身是使用fromManaged
的另一个技巧。而且createHttp4Server
仅需要一个ZEnv
,我现在承认并不需要一个Runtime
。 ZManaged.runtime
是他们不使用ZManaged.accessManaged { implicit runtime: Runtime[ZEnv] =>
的另一个技巧。
完整解决方案https://github.com/kovacshuni/zio-http4s-zlayer-example
object Main extends App {
def run(args: List[String]): URIO[ZEnv,ExitCode] = {
val program: ZIO[Has[Server] with Console,Nothing,Nothing] =
ZIO.never
val httpServerLayer: ZLayer[ZEnv,Throwable,Http4Server] = Http4Server.createHttp4sLayer
program
.provideLayer(httpServerLayer ++ Console.live)
.exitCode
}
}
import zio._
import zio.interop.catz._
import zio.interop.catz.implicits._
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder
object Http4Server {
type Http4Server = Has[Server]
def createHttp4Server: ZManaged[ZEnv,Server] =
ZManaged.runtime[ZEnv].flatMap { implicit runtime: Runtime[ZEnv] =>
BlazeServerBuilder[Task](runtime.platform.executor.asEC)
.bindHttp(8080,"localhost")
.withHttpApp(Routes.helloWorldService)
.resource
.toManagedZIO
}
def createHttp4sLayer: ZLayer[ZEnv,Http4Server] =
ZLayer.fromManaged(createHttp4Server)
}