Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Oct 16 05:36
    codecov-io commented #1174
  • Oct 16 05:26
    scala-steward opened #1174
  • Oct 14 15:52
    codecov-io commented #1173
  • Oct 14 15:42
    scala-steward opened #1173
  • Oct 12 10:39
    iEAmi commented #1172
  • Oct 11 18:56
    sergeykolbasov commented #1172
  • Oct 11 10:03
    iEAmi opened #1172
  • Oct 09 23:26
    codecov-io commented #1171
  • Oct 09 23:16
    scala-steward opened #1171
  • Oct 07 22:49
    vkostyukov commented #1169
  • Oct 07 22:46

    vkostyukov on master

    Use HTTPS for more resolvers L… Merge pull request #1170 from j… (compare)

  • Oct 07 22:46
    vkostyukov closed #1170
  • Oct 07 22:45
    vkostyukov commented #1170
  • Oct 07 21:54
    codecov-io commented #1170
  • Oct 07 21:43
    joroKr21 opened #1170
  • Oct 07 21:30
    joroKr21 commented #1169
  • Oct 07 21:25
    joroKr21 opened #1169
  • Oct 04 12:53
    dkulichkin commented #1161
  • Oct 04 12:51
    dkulichkin commented #1161
  • Oct 04 12:50
    dkulichkin commented #1161
Jan Bessai
@JanBessai
the user guide mentions an endpoint instance strings which matches any (nested) path an returns a sequence of its components as strings. I tried to grep the current master branch for it, and cannot find it anywhere but in the documentation. I remember an older example using it. Where did strings go?
Jan Bessai
@JanBessai
ah found it.. it is paths[String] since 0.16
Jan Bessai
@JanBessai
is there an example where static content is served based on a requested file name?
fromInputStream is nice, but passing a requested file name would require Endpoints to be monadic: get(paths[String]).flatMap(paths => fromInputStream(getFileResource(Paths.get(paths:_*))))
Ryan Plessner
@rpless
yeah seems like that doc for strings is outdated.
for serving files its not really recommended. I'm pretty sure all those endpoints block at certain points. see: https://github.com/finagle/finch/blob/21b143b44c8959b360b772cf8065560c82111a60/core/src/main/scala/io/finch/Endpoint.scala#L659-L661
Jan Bessai
@JanBessai
@rpless I'm implementing an application which manipulates and hosts a git. the git is a temporary resource and spinning up a second server would be a deployment nightmare
also if people try to read templates from disk, the same problem would pop up
Jan Bessai
@JanBessai
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
@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