我正在尝试在码头上运行基于http4s的 webapp 。http4s 库提供了AsyncHttp4sServlet[IO]类来扩展,我使用如下:
class UserSvcServlet
extends AsyncHttp4sServlet[IO](
service = UserSvcServer.start,
servletIo = BlockingServletIo(4096, Blocker.liftExecutorService(Executors.newCachedThreadPool())),
serviceErrorHandler = DefaultServiceErrorHandler
)
正如您在该service属性上看到的,我提供了具有以下实现的 http 服务:
def start[F[_]: ConcurrentEffect: ContextShift: Sync: Timer]: HttpApp[F] =
for {
a <- EnvironmentLoader.db.load[F].map(create_transactor)
b <- EnvironmentLoader.cors.load[F].map(origin)
http = Logger.httpApp(true, true)(CORS(UserRoutes(UserProgram(LiveUserQuery.make(a))).routes, b).orNotFound)
} yield http
该start方法应该返回HttpApp[F],但不幸的是for块返回F[Http[F]]。但是最后F将是一种IO类型。
这是 的定义HttpApp[F]:
type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]
两者EnvironmentLoader.db.load[F].map(create_transactor)和EnvironmentLoader.cors.load[F].map(origin)都在它们的上下文中F,它们加载环境变量。为了加载环境变量,我使用库https://cir.is/。
我知道,不可能Http[F]脱离上下文F。我必须在这里重组代码以使其工作吗?
更新
一种可能的解决方法是:
class UserSvcServlet
extends AsyncHttp4sServlet[IO](
service = UserSvcServer.start[IO].unsafeRunSync(),
servletIo = BlockingServletIo(4096, Blocker.liftExecutorService(Executors.newCachedThreadPool())),
serviceErrorHandler = DefaultServiceErrorHandler
)
它很丑,但它有效。