Help me define an http4s using ZLayers. I'm learning and I'm confused. I'd like to factor out the http server as a component. But I don't know how to compose the ZManageds and the the ZLayers so that it would compile.
Also does it makes sense to create a layer that requires a Runtime[ZEnv]? Or does that make more sense to create a layer that requires a ZEnv and generate the runtime for it.
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, Throwable, Http4ServerLayer] =
ZLayer.succeed(createHttp4Server)
}
object Routes {
val helloWorldService = ...
}
package object simple {
type Http4ServerLayer = Has[ZManaged[Runtime[ZEnv], Throwable, Server]]
type RuntimeLayer = Has[Runtime[ZEnv]]
}
I don't know how to access the ZManaged[..., ..., Server] from the Layer in here in the main.
I don't understand the access methods completely.
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, Nothing, RuntimeLayer] = ZLayer.succeed(Runtime.default)
val http4Layer: ZLayer[RuntimeLayer, Throwable, Http4ServerLayer] = HttpServer.createHttp4Layer
val fullLayer: ZLayer[Any, Throwable, Http4ServerLayer] = runtimeLayer >>> http4Layer
val provided = toProvide.provideCustomLayer(fullLayer)
provided //compile error
}
}
type mismatch
found : ZIO[Runtime[ZEnv], Throwable, Nothing]
required: ZIO[Http4ServerLayer, ?, ?]
also at the bottom, but that's lower importance
found : ZIO[ZEnv, Throwable, ExitCode]
required: URIO[ZEnv, ExitCode]
Same thing in a PR, feel free to comment https://github.com/kovacshuni/itsaren/pull/1
Solution is that a ZLayer when holding a Managed, is a Managed itself. So when something is running on a layer like this, the included Managed will be used through that time. So if you run a
ZIO.neveron a layer, the server will be kept alive.To build the layer itself was another trick to use
fromManaged. And thecreateHttp4Serverrequires aZEnvonly, no point in requiring aRuntimeI admit now.ZManaged.runtimeis another trick they have for not to useZManaged.accessManaged { implicit runtime: Runtime[ZEnv] =>.Full solution https://github.com/kovacshuni/zio-http4s-zlayer-example