Hi @Igosuki I experimented with it once, don't remember the way but it's possible for certain
But to clarify, what do you mean exaclty by upon Finagle server termination
? Because usually you shut it down all together with the whole application, and Http.serve
returns forever-running Twitter Future
libraryDependencies ++= Seq(
"com.github.finagle" %% "finchx-circe" % "0.31.0",
"com.github.finagle" %% "finchx-generic" % "0.31.0"
)
F
and dependency injection in class constructor
IO[Output[Something]]
into a Future
by calling unsafeToFuture
. Since I had already and IO[...], I suppose this call to unsafeToFuture
is not necessary, if not undesirable. val productsQuery: Endpoint[IO, ProductListResponse] =
post( "products" :: jsonBody[SimpleRequest] ) { req: SimpleRequest =>
val origin = "austria"
val products: IO[Output[ProductListResponse]] =
productCache
.flatMap { cache => cache.ref.get(origin) }
.map { r => Ok(ProductListResponse(ctx.api.version, None, r.get.contents)) }
products.unsafeToFuture
} handle {
case e: IllegalArgumentException => handleProductList.BadRequest(e)
case e: Exception => handleProductList.InternalServerError(e)
}
Future
is required.[error] /home/rgomes/workspace/guided-repair-api/service/src/main/scala/Endpoints.scala:143:17: type mismatch;
[error] found : cats.effect.IO[io.finch.Output[api.model.ProductListResponse]]
[error] required: scala.concurrent.Future[?]
[error] products //XXX .unsafeToFuture //FIXME: investigate if there's a way to avoid this call
// These are magic imports which must survive IntelliJ attempts to "help us".
// @formatter: off
import cats.effect._
import cats.implicits._
import cats.syntax.apply._
import io.circe.generic.auto._
import io.finch._
import io.finch.circe._
// @formatter: on
MyApp
object into the Request
when the request is authorized.auth
filter only blocks not authorized requests, but does not pass MyApp
to compiled(req)
.trait Filters extends Whiteboard with StrictLogging {
import io.finch._
import cats.effect.IO
import cats.implicits._
import com.twitter.finagle.http.Status
import com.twitter.finagle.http.Response
def authorized(authorization: Option[String]): IO[MyApp] = tokenValidation.authorized(authorization)
val auth: Endpoint.Compiled[IO] => Endpoint.Compiled[IO] =
compiled => {
Endpoint.Compiled[IO] { req =>
authorized(req.authorization)
.redeemWith(
_ => (Trace.empty -> Right(Response(Status.Unauthorized))).pure[IO],
//FIXME: should pass MyApp object into the request
// See examples 2 and 3 of: https://finagle.github.io/finch/cookbook.html#defining-custom-endpoints
myapp => IO(println(myapp)) *> compiled(req))
}
}
...
}
@frgomes quick and dirty way would be to use Request#ctx
: https://twitter.github.io/finatra/user-guide/http/filters.html#using-c-t-finagle-http-request-ctx or Context
from Finagle that is roughly the same as ThreadLocal (but actually request local)
IMO, proper "functional" way would be to use a different monad instead and have an auth that would have a similar signature:
val auth: Endpoint.Compiled[ReaderT[IO, MyApp, *]] => Endpoint.Compiled[IO]
The idea here is to have underlying endpoints with effect ReaderT[IO, MyApp, *]
that runs inside of Endpoint.Compiled[IO]
where you have an access to request and can build the instance of MyApp
ReaderT
as your effect monad allows you to access environment MyApp
whenever you feel like it
interop-cats
library which supposedly gives instances of various cats effect typeclasses for ZIO
@hderms : Without willing to promote a flame war... but I've ditched IntelliJ from my workflow. To be honest, I always used IntelliJ just as a very clever text editor, using SBT and other external tools for compiling, testing, etc. So, if I there's another very clever text editor around (and there is!) I would not feel very much difference, really.
I'm using Emacs with scala-metals. The later employs LSP (Language Server Protocol) in order to talk to the Scala compiler.
This is the link for scala-metals. You will find configurations for several text editors and build tools there:
https://scalameta.org/metals/