Проблема компиляции между HttpRoutes [RIO [E, *]] и HttpRoutes [zio.Task]

Попытка скомпилировать это небольшое описание конечной точки, дружественного к ZIO, Tapir/Http4s

import io.circe.generic.auto._
import org.http4s.HttpRoutes
import sttp.tapir.json.circe
import sttp.tapir.ztapir._
import sttp.tapir.server.http4s.ztapir._
import sttp.tapir.endpoint
import zio.RIO
import zio.interop.catz._

case class HealthReplyDTO(message: String)

final class HealthEndpointZTapir[E]() {
  private val prefixPath = "/health"
  val healthOkReply = HealthReplyDTO("OK")

  private val routeDescription: ZEndpoint[Unit, Unit, HealthReplyDTO] =
    endpoint.get.in(prefixPath).out(circe.jsonBody[HealthReplyDTO]).description("Health Endpoint")

  val route: HttpRoutes[RIO[E, *]]
  = routeDescription.toRoutes( _ => RIO.succeed(healthOkReply))

}

и продолжайте получать это в последней строке.

Type mismatch. Required: HttpRoutes[RIO[E, *]], found: HttpRoutes[zio.Task]

Задача - это подтип RIO, так что все должно работать нормально? Или мне что-то здесь не хватает. Немного новичок в этом мире, так что некоторая помощь будет очень признательна.

2 ответа

Task действительно является подтипом RIO[R, *], но HttpRoutes from http4s инвариантно, а значит, и сообщение об ошибке.

В .toRoutes метод возвращает HttpRoutes[Task]как следствие интеграции с http4s, в котором нет типизированных ошибок. В общем, http4s может генерировать исключения любого типа при настройке сервера и обработке маршрутов, поэтому нам нужно работать с Task.

В конце концов, я сделал что-то подобное. Компилятору нужна небольшая помощь в последней строке, где имплицитов оказалось недостаточно. В ztapir часть тапира закреплена в типе эффекта ZIO Task так что в моем случае это не годилось

import io.circe.generic.auto._
import org.http4s.HttpRoutes
import sttp.tapir.json.circe
import sttp.tapir.server.http4s._
import sttp.tapir.endpoint
import zio.RIO
import zio.interop.catz._
import sttp.tapir._

final class HealthEndpointTapir[E]() extends TapirHttp4sServer {

  private val prefixPath = "/health"
  val healthOkReply: HealthReplyDTO = HealthReplyDTO("OK")
  implicit val customServerOptions: Http4sServerOptions[RIO[E, *]] = Http4sServerOptions
    .default[RIO[E, *]]

  private val routeDescription: Endpoint[Unit, Unit, HealthReplyDTO, Any] =
    endpoint.get.in(prefixPath).out(circe.jsonBody[HealthReplyDTO]).description("Health Endpoint")

  val route: HttpRoutes[RIO[E, *]]
  = RichHttp4sHttpEndpoint[Unit, Unit, HealthReplyDTO, RIO[E, *]
(routeDescription).toRoutes( _ => RIO.succeed(Right(healthOkReply)))

}
Другие вопросы по тегам