Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 05 2019 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 2019 21:17
    codecov-io commented #484
  • Jan 31 2019 21:08
    scala-steward opened #484
  • Jan 31 2019 18:19
    andywhite37 commented #189
  • Jan 31 2019 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 2019 00:01
    codecov-io commented #483
  • Jan 29 2019 23:51
    deniszjukow opened #483
  • Jan 29 2019 23:37
  • Jan 29 2019 23:22
  • Jan 29 2019 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 2019 18:01
    jdegoes commented #480
  • Jan 29 2019 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 2019 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 2019 07:12
    alexandru commented #480
  • Jan 28 2019 05:45
    codecov-io commented #482
  • Jan 28 2019 05:35
    daron666 opened #482
  • Jan 27 2019 13:56
    codecov-io commented #481
  • Jan 27 2019 13:46
    lrodero opened #481
  • Jan 27 2019 05:47
    codecov-io commented #460
  • Jan 27 2019 05:37
    codecov-io commented #460
Fabio Labella
@SystemFw
it applies to cached thread pool philosophically. I think in practice only global does something with it
Gavin Bisesi
@Daenyth
The ExecutionContext implementation needs to be explicitly aware of it
Fabio Labella
@SystemFw
for cats-effect itself, the philosophy is slightly different though
and it's about separating blocking and non-blocking code
Blocker uses a CachedThreadPool
ContextShift uses (as of recently) a FixedThreadPool
blocking is mostly about trying to make sure blocking code stays out of the way of non-blocking one, under the assumption that they share the same thread pool. Cats-effect tries to avoid them sharing the same thread pool to begin with (hence Blocker vs ContextShift)
Julien Truffaut
@julien-truffaut
ok so if you discard the global execution context, scala.concurrent.blocking is generally not useful
yes it makes more sense
to separate thread pools
Fabio Labella
@SystemFw
it makes more sense once you have the tools and an ecosystem that's based on non-blocking code
basically everything kinda builds on top of each other
Julien Truffaut
@julien-truffaut
I guess the standard library pushes you to have a single implicit thread pool
with implicit ec: ExecutionContext
Fabio Labella
@SystemFw
yeah
global is a good default choice for that philosophy
Julien Truffaut
@julien-truffaut
thanks a lot Fabio
Fabio Labella
@SystemFw
no problem :)
Julien Truffaut
@julien-truffaut
I heard several people to recommend to have 3 threads pools, one for blocking, one for work and one for dispatch: https://impurepics.com/posts/2018-04-21-thread-pools-basics.html
Blocker provides the blocking pool
What's the recommended pattern to use disptach / work pool with cats-effect?
e.g. IOApp provides a ContextShift[IO], does it shift from dispatch to work pool?
Fabio Labella
@SystemFw
@julien-truffaut the dispatch is Timer, and already shifts to ContextShift, for work
it's rare that you need a separate dispatch pool that isn't timer
Julien Truffaut
@julien-truffaut
how do you shift with a Timer? as far as I can see, they are only two methods:
trait Timer[F[_]] {
  def clock: Clock[F]
  def sleep(duration: FiniteDuration): F[Unit]
}
I guess I am confused because I imagine an event dispatcher as something that receives incoming requests like a REST call or kafka message and dispatch it to something that does the processing
Fabio Labella
@SystemFw
right, I wouldn't classify that as a dispatcher, in the sense of the pool gist
I classify that as "work"
in the case of kafka, blocking as well :P
same for Rest
for me a dispatcher is "processes a sleep" , or maybe a UI event
think about something that generally works with one thread at super high priority
maybe an async http call also fits there, but I dont' think that's actually done this way in cats-effect land
anyway, the source of that advice here I think is ultimately @djspiewak , so let's see what he thinks :)
Julien Truffaut
@julien-truffaut
would it apply to any Async? I mean the dispatcher would be in charge of continuing the IO when the call back is called?
Fabio Labella
@SystemFw
imho, no. Continuing the IO is pretty much the definition of "work". I think in the original gist the dispatcher would be something that just calls the callback in response to an event
but do note that handling of shifting for Async in current cats-effect IO is not optimal, it will be improved in 2.0
Julien Truffaut
@julien-truffaut
yeah sorry I think that's what I meant, the dispatcher would be waiting for the event
do you know an issue or blog I could read about the design of cat-effect 2.0?
so if I understand correctly, with cats-effect 1.x we have:
  • a pool for blocking actions: Blocker
  • a pool for sleeping: Timer
  • a working pool: ContextShift
Fabio Labella
@SystemFw
yeah, Timer is a good example. It waits for a "time elapsed" event, and calls the callback on an Async, and shifts it to ContextShift
sorry, wrong version, I mean 3.0
2.0 just got out, mostly for the bincompat problem with scalacheck
Julien Truffaut
@julien-truffaut
yep same for cats-core
Fabio Labella
@SystemFw

do you know an issue or blog I could read about the design of cat-effect 3.0?

no because it still isn't really that formed

there are some discussions in various issues, but I wouldn't really take any of it for granted at all
but hopefully we will manage to agree on a draft for discussion soon
Julien Truffaut
@julien-truffaut
cool thanks again!
Julien Truffaut
@julien-truffaut
sorry for all the questions recently ... I am in the process of refactoring an App to IOApp and I am not sure I am doing it right. My current App reads configs, initialise some services, rest server and start some background processes. I started to refactor all the initialise/shutdown into Resources. Now I have something like this:
(for {
    resource1  <- ...
    resource2  <- ...
    congfig    <- Resource.liftF( // read config )
    resource3  <- f(config)
    httpSrever <- g(config)
} yield (congfig, resource2, resource3)).use{
    case (congfig, resource2, resource3) =>

  val service1 = ...(config, ...)
  val service2 = ...(config, ...)

  val backgroundProcess1 = service1.doSmething
  val backgroundProcess2 = service2.doSmething

  (backgroundProcess1, backgroundProcess2).parTupled
}.as(ExitCode.Success)