首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Akka Http和Circe,如何序列化封装在无标记的最终方法中的实体(猫效应)

Akka Http和Circe,如何序列化封装在无标记的最终方法中的实体(猫效应)
EN

Stack Overflow用户
提问于 2021-08-13 16:46:55
回答 1查看 399关注 0票数 1

我正在构建一个学习Scala 3的玩具项目,我陷入了一个问题,首先,我遵循了使用cats effect的无标记-决赛方法,除了实体序列化之外,这个方法是正常工作的,当我尝试使用akka-http创建一个路由时,我遇到了以下问题:

代码语言:javascript
运行
复制
def routes: Route = pathPrefix("security") {
(path("auth") & post) {
  entity(as[LoginUserByCredentialsCommand]) {
    (command: LoginUserByCredentialsCommand) =>
      complete {
        login(command)
      }
  }
}}

F[
  Either[com.moralyzr.magickr.security.core.errors.AuthError, 
    com.moralyzr.magickr.security.core.types.TokenType.Token
  ]
]
Required: akka.http.scaladsl.marshalling.ToResponseMarshallable
where:    F is a type in class SecurityApi with bounds <: [_] =>> Any

据我所知,akka-http不知道如何序列化F高度类型,通过搜索我找到的跟随解,它包括创建一个名为StackOverflow的隐式,以向akka-http显示如何序列化该类型,但是当我实现它时,我会得到一个StackOverflow错误:(

代码语言:javascript
运行
复制
import akka.http.scaladsl.marshalling.ToResponseMarshaller
import cats.effect.IO

trait Marshallable[F[_]]:
  def marshaller[A: ToResponseMarshaller]: ToResponseMarshaller[F[A]]

object Marshallable:
  implicit def marshaller[F[_], A : ToResponseMarshaller](implicit M: Marshallable[F]): ToResponseMarshaller[F[A]] =
    M.marshaller

  given ioMarshaller: Marshallable[IO] with
    def marshaller[A: ToResponseMarshaller] = implicitly

我现在真的被困住了,有没有人知道我该如何解决这个问题?完整的代码可以找到这里

编辑:这是登录代码

为了清晰起见,下面是实例化安全api和安全api本身的类。

代码语言:javascript
运行
复制
  object Magickr extends IOApp:

  override def run(args: List[String]): IO[ExitCode] =
    val server = for {
      // Actors
      actorsSystem <- ActorsSystemResource[IO]()
      streamMaterializer <- AkkaMaterializerResource[IO](actorsSystem)
      // Configs
      configs <- Resource.eval(MagickrConfigs.makeConfigs[IO]())
      httpConfigs = AkkaHttpConfig[IO](configs)
      databaseConfigs = DatabaseConfig[IO](configs)
      flywayConfigs = FlywayConfig[IO](configs)
      jwtConfig = JwtConfig[IO](configs)
      // Interpreters
      jwtManager = JwtBuilder[IO](jwtConfig)
      authentication = InternalAuthentication[IO](
        passwordValidationAlgebra = new SecurityValidationsInterpreter(),
        jwtManager = jwtManager
      )
      // Database
      _ <- Resource.eval(
        DbMigrations.migrate[IO](flywayConfigs, databaseConfigs)
      )
      transactor <- DatabaseConnection.makeTransactor[IO](databaseConfigs)
      userRepository = UserRepository[IO](transactor)
      // Services
      securityManagement = SecurityManagement[IO](
        findUser = userRepository,
        authentication = authentication
      )
      // Api
      secApi = new SecurityApi[IO](securityManagement)
      routes = pathPrefix("api") {
        secApi.routes()
      }
      akkaHttp <- AkkaHttpResource.makeHttpServer[IO](
        akkaHttpConfig = httpConfigs,
        routes = routes,
        actorSystem = actorsSystem,
        materializer = streamMaterializer
      )
    } yield (actorsSystem)
    return server.useForever

代码语言:javascript
运行
复制
class SecurityApi[F[_]: Async](
    private val securityManagement: SecurityManagement[F]
) extends LoginUserByCredentials[F]
    with SecurityProtocols:

  def routes()(using marshaller: Marshallable[F]): Route = pathPrefix("security") {
    (path("auth") & post) {
      entity(as[LoginUserByCredentialsCommand]) {
        (command: LoginUserByCredentialsCommand) =>
          complete {
            login(command)
          }
      }
    }
  }

override def login(
  command: LoginUserByCredentialsCommand
): F[Either[AuthError, Token]] =
  securityManagement.loginWithCredentials(command = command).value

=================用Luis提供的洞察力编辑2 =========================================,我需要在Marshaller级别将IO解压到未来,这一点更清楚,如下所示:

代码语言:javascript
运行
复制
  def ioToResponseMarshaller[A: ToResponseMarshaller](
      M: Marshallable[IO]
  ): ToResponseMarshaller[IO[A]] =
    Marshaller.futureMarshaller.compose(M.entity.unsafeToFuture())

不过,我有这样的问题:

代码语言:javascript
运行
复制
Found:    cats.effect.unsafe.IORuntime => scala.concurrent.Future[A]
Required: cats.effect.IO[A] => scala.concurrent.Future[A]

我想我快到了!是否有一种方法可以打开保持IO类型的IO?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-15 09:07:07

我设法让它运转起来了!由于@luismiguel的洞察力,问题在于Akka HTTP无法处理Cats-Effect IO monad,因此解决方案是使用封送器中的unsafeToFuture解锁IO monad,这样我就可以从点到点保持无标记的最终样式,下面是解决方案:

此隐式获取类型的内部封送处理程序。

代码语言:javascript
运行
复制
import akka.http.scaladsl.marshalling.ToResponseMarshaller
import cats.effect.IO

trait Marshallable[F[_]]:
  def marshaller[A: ToResponseMarshaller]: ToResponseMarshaller[F[A]]

object Marshallable:
  implicit def marshaller[F[_], A: ToResponseMarshaller](implicit
      M: Marshallable[F]
  ): ToResponseMarshaller[F[A]] = M.marshaller

  given ioMarshallable: Marshallable[IO] with
    def marshaller[A: ToResponseMarshaller] = CatsEffectsMarshallers.ioMarshaller

这篇文章公开了IO monad和使用未来的封送处理程序flatMaps,akka-http知道如何处理这个问题。

代码语言:javascript
运行
复制
import akka.http.scaladsl.marshalling.{
  LowPriorityToResponseMarshallerImplicits,
  Marshaller,
  ToResponseMarshaller
}
import cats.effect.IO
import cats.effect.unsafe.implicits.global

trait CatsEffectsMarshallers extends LowPriorityToResponseMarshallerImplicits:
  implicit def ioMarshaller[A](implicit
      m: ToResponseMarshaller[A]
  ): ToResponseMarshaller[IO[A]] =
    Marshaller(implicit ec => _.unsafeToFuture().flatMap(m(_)))

object CatsEffectsMarshallers extends CatsEffectsMarshallers
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68775841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档