我正在学习ZIO 2.x,当使用bootstrap
层配置Runtime
时,它不工作。
object RuntimeCustom extends ZIOAppDefault {
// It's not work, And I don't know why?
override val bootstrap = EmailService.live
def run = (for {
_ <- ZIO.debug("Start...")
_ <- EmailService.send("God", "Hi")
_ <- ZIO.debug("End...")
} yield ())
}
出现一个错误:
[error] /Users/changzhi/github-repo/zio-start/src/main/scala/zio/reference/experiment/core/RuntimeCustom.scala:35:7:
[error]
[error] ──── ZIO APP ERROR ───────────────────────────────────────────────────
[error]
[error] Your effect requires a service that is not in the environment.
[error] Please provide a layer for the following type:
[error]
[error] 1. example.EmailService
[error]
[error] Call your effect's provide method with the layers you need.
[error] You can read more about layers and providing services here:
[error]
[error] https://zio.dev/next/datatypes/contextual/
[error]
[error] ──────────────────────────────────────────────────────────────────────
[error]
[error] _ <- EmailService.send("God", "Hi")
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
如果我用provide
替换,它可以工作。
object RuntimeCustom extends ZIOAppDefault {
def run = (for {
_ <- ZIO.debug("Start...")
_ <- EmailService.send("God", "Hi")
_ <- ZIO.debug("End...")
} yield ())
// This can works, have no doubt
.provide(EmailService.live)
}
完整版程序在此
package example
import zio._
trait EmailService {
def send(user: String, content: String): Task[Unit]
}
object EmailService {
def send(user: String, content: String): ZIO[EmailService, Throwable, Unit] =
ZIO.serviceWithZIO[EmailService](_.send(user, content))
val live: ZLayer[Any, Nothing, EmailService] =
ZLayer.fromZIO( ZIO.succeed(EmailServiceFake()) <* Console.printLine("Init EmailService") ).orDie
}
case class EmailServiceFake() extends EmailService {
override def send(user: String, content: String): Task[Unit] =
Console.printLine(s"sending email to $user")
}
object RuntimeCustom extends ZIOAppDefault {
// It's not work, And I don't know why?
//override val bootstrap = EmailService.live
def run = (for {
_ <- ZIO.debug("Start...")
_ <- EmailService.send("God", "Hi")
_ <- ZIO.debug("End...")
} yield ())
// This can works, have no doubt
.provide(EmailService.live)
}
2条答案
按热度按时间ohfgkhjo1#
ZIOAppDefault
是为不需要额外服务的应用程序设计的,假设它们将只“需要”内置服务,因为您已经用provide
方法提供了其他要求。如果要使用
bootstrap
方法,则应该扩展ZIOApp
并覆盖environmentTag
和Environment
字段,以便run
机制知道如何构造最终环境。编辑
使用原始示例来说明这是可行的:
https://scastie.scala-lang.org/02MMaWS2S6Wwe55a24H7Sg
liwlm1x92#
像这样的事情应该会奏效: