Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Oct 20 19:05
    DuncanHills edited #1278
  • Oct 20 19:05
    DuncanHills edited #1278
  • Oct 20 16:48
    DuncanHills opened #1278
  • Oct 20 11:25
    codecov-io commented #1277
  • Oct 20 11:17
    scala-steward opened #1277
  • Oct 19 23:27
    codecov-io commented #1276
  • Oct 19 23:16
    scala-steward closed #1272
  • Oct 19 23:16
    scala-steward opened #1276
  • Oct 16 20:49
    scala-steward opened #1275
  • Oct 14 08:45
    benjumanji synchronize #1274
  • Oct 14 08:45
    benjumanji edited #1274
  • Oct 14 08:45
    benjumanji opened #1274
  • Oct 06 20:54
    scala-steward opened #1273
  • Oct 05 01:24
    codecov-commenter commented #1272
  • Oct 05 01:15
    scala-steward opened #1272
  • Oct 01 12:54
    Bernold1 commented #347
  • Oct 01 12:30
    rpless commented #347
  • Oct 01 08:41
    Bernold1 commented #347
  • Sep 30 07:04
    keyno63 commented #1250
  • Sep 29 20:57
    codecov-commenter commented #1271
Jan Bessai
@JanBessai
also if people try to read templates from disk, the same problem would pop up
e.g. get(path[Int]::paths[String]).flatMap(userId::paths => fromInputStream(getFileResource(Paths.get(paths:_*)).map(renderTemplate(_, userId)))))
Jan Bessai
@JanBessai
it would probably help to change the FromInputStream endpoint to be an Endpoint[F, Resource[F, InputStream] => Buf] by binding its resource in a lambda in apply instead of the constructor
the old version could still be restored by something likeoldVersion(resource: Resource[F, InputStream]) = newVersion.map(f => f resource)
Ryan Plessner
@rpless
hrm ok. fromInputStream is probably not want you want then. you might want to try using a Mapper. maybe something roughly like:

  get(path[Int] :: paths[String])({ (userId: Int, paths: Seq[Strings]) => 
    getFileResource(Paths.get(paths:_*))
      .map(renderTemplate(_, userId))
      .use(template => Ok(template))
  })
Jan Bessai
@JanBessai
hmm... that works if the resource lifetime is tied to a single request
in my case, the resource is available while the endpoint module is alive
Jan Bessai
@JanBessai
ah I guess the correct way to do this is to expose the endpoint module itself as a resource, and later use it in the IO operation which starts the http server
Jan Bessai
@JanBessai
also, there is some issue with the documentation how to use AsyncStream, the api changed and it now has to be .toAsyncStraeam on the reader instead of AsyncStream.fromReader
Jan Bessai
@JanBessai
Seems AsyncReader finagle/finch#1070 and iteratee is the way to go. The documentation needs an according update!
thanks for the help! :)
iteratee gave me empty files and I found the documentation too sparse to work with, so I ended up using the future returned by Reader.fromStream(...).read()
Dermot Haughey
@hderms
anyone know if there is something stopping us from moving to circe 12.x
Octav Zaharia
@octavz

hi, this code:

      Bootstrap .serve[Application.Json](helloWorld :+: combos(env))

causes:

 no type parameters for method apply: (e: io.finch.Endpoint[FF,E])
io.finch.Bootstrap[FF,io.finch.Endpoint[FF,E] :: io.finch.Endpoint[zio.Task,String] :: shapeless.HNil,io.finch.Application.Json :: io.finch.Text.Plain :: shapeless.HNil] 
in class Serve exist so that it can be applied to arguments (io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+:  models.CombosDTO :+: shapeless.CNil])
[error]       --- because ---
[error]      argument expression's type is not compatible with formal parameter type;
[error]       found   : io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+: models.CombosDTO :+: shapeless.CNil]
[error]       required: io.finch.Endpoint[?FF,?E]
[error]
[error]      L77:             .serve[Application.Json](helloWorld :+: combos(env))
[error]                             ^
[error] [E2] Main.scala
[error]      type mismatch;
[error]       found   : io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+: models.CombosDTO :+: shapeless.CNil]
[error]       required: io.finch.Endpoint[FF,E]
[error]      L77:             .serve[Application.Json](helloWorld :+: combos(env))

while:

Bootstrap
  .serve[Application.Json](combos(env))
  .serve[Application.Json](helloWorld)

will compile just fine, obviously some type inference doesn't work...

is :+: usable in my case ? am i doing something wrong ?
Both functions will return Endpoint[zio.Task, X]
Octav Zaharia
@octavz
same code compiles fine if i use cats.effect.IO instead of zio.Task
Sergey Kolbasov
@sergeykolbasov
it looks weird indeed
is type for helloWorld and combos set explicitly?
Thomas Santana
@nebulorum

I've been building in finch for a couple of week and using the Cookbook and user guide as much as possible. I really liked the idea of composing Endpoints. So I attempted to build one with mapOutputAsync and twitter.util.Futures.

def checkToken: com.twitter.util.Future[TokenInfo]  = ???
val authenticated: Endpoint[IO, TokenInfo] = header(Fields.Authorization).mapOutputAsync {
     checkToken(header).map(Ok)
}

This does not work since of header unlike get there are not Mapper for the future. I found a way via twitter Future to scala Future (form the cookbook with IO.pure, and IO.fromFuture). But I wonder if there is a way to do this without this step. I also tried to use io.catbirds.util but could not find a good way. Ony one have a better solution?

Sergey Kolbasov
@sergeykolbasov
Shortly, you need a conversion to IO anyway, but there is indeed a way to skip intermediate hop through Scala Future
Thomas Santana
@nebulorum
Shouldn't this conversion be applied on the other EndpointModules?
Thomas Santana
@nebulorum
This worked for me: def toIO[A](f: TFuture[A]): IO[A] = ToAsync.twFutureToAsync[IO].apply(f). However I feeling this is not the correct use. Is there a cleaner way?
Sergey Kolbasov
@sergeykolbasov
Yep, make checkToken returning you IO :)
I'd suggest to fallback to Future (if it's really required) somewhere on the very edge of the application where the actual I/O happens
Thomas Santana
@nebulorum
Sergey I get your suggestion of limiting the use of Future. From the looks of all Cat Effect/IO discussions Future is not the correct abstraction. But since Finch run on top of Finagle, doesn't it make sense to leverage the capabilities? Is there a more Effect way of using Finagle?
Sergey Kolbasov
@sergeykolbasov

@nebulorum there is no simple answer here, especially on "correctness" of abstraction.

Personally I'd prefer to use F[_] inside the application instead of fixing on a specific monad, would it be Future, IO or Task.

Speaking of Twitter Future, the only "killer feature" comparing to cats.effect.IO is LocalContext that is somewhat similar to Java's ThreadLocal and might be quite handy to use. I.e. monix Task provides similar capabilities.

We use ReaderT[IO, RequestEnv, *] monad instead to have the same set of capabilities but also keep referential transparency.

If you keep Future outside of your application logic, there is no difference from your app perspective on what happens outside
Octav Zaharia
@octavz

it looks weird indeed
is type for helloWorld and combos set explicitly?

@sergeykolbasov i was missing addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.1.2")

Thijs Broersen
@ThijsBroersen
When an exception is throw within one of the encoders the service returns a 500 and no error is logged. Is there any way I can add a specific exception handler to a service or part of a service, e.g. .serve[Application.Json](api).onErrorHandleWith(myhandler) ?
Ryan Plessner
@rpless
@ThijsBroersen you can use api.handle() in that case. Although I thought encoding errors also go through the Encoder for Exception which is usually what I've used for handling that
Dermot Haughey
@hderms
we were figuring we'd be able to do something lke
withAuth :: someOtherEndpoint
withAuth being like Endpoint[User
but predictably there is no JSON encoder for User so this doesn't work
Dermot Haughey
@hderms
it seems like this form of composition just won't work for us which makes it hard for us to understand how we could blanketly add auth to a collection of endpoiints
from one perspective we could make sure User has a JSON codec and then perhaps it would work but it seems kind of hacky
Dermot Haughey
@hderms
I got it to work with an Endpoint[HNil] which isn't ideal but will more or less work for us
definitely was a bit confusing
Stefan Dietiker
@d-s-d
@hderms Why would you need an Encoder for User?
Dermot Haughey
@hderms
Alfredo Torre
@sentenza
Hey guys. I need some help here. I've just started using Finch and I was looking for a tutorial or some docs/examples on how to create a sort of "route decorator". I want to create a set of authenticated routes verifying JWT tokens produced by Auth0, but in order to do that I should execute a monadic flow (within cats.IO I guess) and check whether return a 401 or not at the end of the world.
Alfredo Torre
@sentenza
for instance in Play you can use the action composition to execute a check before executing the actual action like a sort of action decorator https://www.playframework.com/documentation/2.7.x/ScalaActionsComposition#Custom-action-builders
Ryan Plessner
@rpless
@sentenza are you using the old finch artifacts or the new finchx artifacts that make use cats effect? If you are using the ones with cats effect you can do something like this https://github.com/finagle/finch/blob/master/examples/src/main/scala/io/finch/middleware/Main.scala#L32
and only apply it to a subset of your endpoints
Frederick Cai
@zhenwenc
Hello, is there any good docs around for finchx? It's kinda confusing while reading the finch docs but using finchx :joy_cat:
Alfredo Torre
@sentenza

@sentenza are you using the old finch artifacts or the new finchx artifacts that make use cats effect? If you are using the ones with cats effect you can do something like this https://github.com/finagle/finch/blob/master/examples/src/main/scala/io/finch/middleware/Main.scala#L32

I'm using the new ones (finchx) so I guess that will solve my problem, but now I'm wondering how exactly I should take advantage of that middleware in my endpoints.

val auth: Endpoint.Compiled[IO] => Endpoint.Compiled[IO]  // where should I put the auth middleware?

val authFilter = Function.chain(Seq(auth))
val compiled = filters(Bootstrap.serve[Text.Plain](myEndpoint).compile)
// Endpoint.toService(compiled) ??

Is there any way to directly apply the authFilter on my endpoints?

Sergey Kolbasov
@sergeykolbasov
authFilter is just a function from Endpoint.Compiled to Endpoint.Compiled