Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • 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
Jakub Kozłowski
@paul-snively don't we all?
Fabio Labella
look at the docs from Control.Exception. It's in the context of cancelable/uncancelable regions (same idea)
From the doc, I did not get it.
Jens Halm
@bifunctor It deals with the scenarios where you want to safely group the effect-full acquisition and release of a resource (e.g. an InputStream) into a single type. It reduces the amount of plumbing and the opportunity for errors in the code that uses the resource (e.g. you cannot forget to close the stream). The tutorial section about Resource is a bit more detailed (and also compares Resource with Bracket): https://typelevel.org/cats-effect/tutorial/tutorial.html#acquiring-and-releasing-resources
Paul Snively
You could say it’s an effectful, referentially transparent version of try/catch/finally.
Basically, a “resource” is something that must be acquired (like a socket connection), used (effectfully), and released whether used successfully or unsuccessfully.
Jakub Kozłowski
@bifunctor if you like this kind of thing, I made a vid about Resource (and Bracket, if you want to understand how Resource works with multiple effect types): https://www.youtube.com/watch?v=m9cu4xUvrUs
Rafał Sumisławski
The docs of Blocker say that it shouldn't be passed implicitly (https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/Blocker.scala#L31). What is the reason behind this recommendation? I used to pass it implicitly and haven't seen any obvious drawbacks so far.
Daniel Spiewak
@RafalSumislawski Just general best-practices with implicits. Basically, implicit values should never hold state. The implications of this are pretty profound and far-reaching, and a lot of it comes from experience in violating this rule (and paying the price later). An analogous "best practice" is that you should never do something like implicit def strToInt(s: String): Int = .... You certainly can do this, and it'll work sometimes, but you would reject any PR that introduced something like that, wouldn't you? Same thing with implicit Blocker.
That was maybe too abstract. :-) It's hard to point to concrete examples of where implicit Blocker will bite you. I guess the best thing to look at is the frustrations that people often have around implicit ExecutionContexts in the Future ecosystem.
Blocker is similar
Daniel Karch
@SystemFw I attended your talk at Scala World and you mentioned that the toy IO that you built there is not stack-safe. I have started playing around with the code from the slides and filled in the blanks ... and I'm having a hard time getting the stack to overflow. ^^
In what way isn't the IO from http://systemfw.org/Scala-World-2019/ stack-safe? Aren't Pure/FlatMap + the run loop essentially a trampoline?
Rafał Sumisławski
@djspiewak the most common issue I've seen with ExecutionContext is that a typical application needs more than one ec, this leaves a lot room for "accidentally passed the wrong one" errors. Typically an application needs just one Blocker wrapping an unlimited cachedThreadPool. A cached thread pool indeed has a state, but it's the kind of state that can't be observed. Compared to blocker, I see more risk in passing around implicit CountextShift, which typically boxes a limited thread pool, and through that limit the state (number of running tasks) of the thread pool can be observed (delayed execution) by a user of the context shift.
I'd agree the warning generalizes to ContextShift.
That is, as @djspiewak said, "Basically, implicit values should never hold state."
Rafał Sumisławski
@paul-snively-exa and what do you think about the inability to observe the state of a Blocker backed by a cachedThreadPool? I used to view it as a technical/JVM detail of execution, one that just like allocations, stack size limit etc, doesn't need special handling.
Paul Snively
My sense is I don’t want anything unbounded passed implicitly.
In this case, the reality is, you don’t have an unbounded number of cores.
(Cue @djspiewak: "'Unbounded' is just another word for 'DOS attack.'")
Rafał Sumisławski
I expect the threads of blocker to spend most of the time blocked, not on the cores, but I see what you mean. The risk of the pool growing infinitly is a problem indeed.
At some point, when developing services at scale, I think you get radicalized about managing scarce resources explicitly.
Rafał Sumisławski
Then maybe the recommended practice should be to use thread pools of limited size under the Blocker? I feel like the API and the docs kind of encourage the unlimited cachedThreadPool approach.
I think so too, but that's why, I think, the "don't use it implicitly" warning is there.
That is, I'd add the warning to ContextShift rather than removing it from Blocker.
Rafał Sumisławski
I get it.
tl;dr threads are a scarce resource.
But meh. I take your point, too, about expecting most of them to be blocked rather than actually consuming a core. That's not indefensible, any more than expecting not to OOM, acting as if memory were unbounded, is.
It's all trade-offs.
Fabio Labella
I think you can apply the "implicit call site" strategy to this problem
(re: implicit Blocker)
same that applies to stateful tagless algebras
basically the idea is that passing things implicitly does not really cause issues, it's implicit instances that can be troublesome (because you can pick up the wrong one by accident)
but if you pass something implicitly, but only make the correspondent instance implicit close to the call site, then it's ok
  • the language isn't great for this syntax wise, so you have some unwieldy bits, which are normally limited to main however
  • it's not a clear cut rule, so if your team disagrees, just passing things explicitly works better
Fabio Labella

@danielkarch hey,

Aren't Pure/FlatMap + the run loop essentially a trampoline?

well, you need to introduce an async boundary (or more), and then the execution context essentially acts as a trampoline (which is why Future is stack safe, it submits all the time). However having a fully async boundary (i.e. an ExecutionContext submission) is heavyweight, you can build a lighter weight one (this is trampolineEc in cats-effect).
The thing with stack-safety is that there are some corner cases (you will see comments in the cats-effect codebase like "we need to insert another async boundary here for stack-safety")

Rafał Sumisławski
My team ins currently on the implicit side. Before there was Blocker in cats-effect we used to create our own wrappers around diffrent ExecutionContext, to be able to pass them around implicitly without the risk of using the wrong implicit instance.
Fabio Labella
you (@danielkarch) can look at various tests for stack-safety in cats-effect for these various corners
also, you will notice that in my code there is a comment saying "no double execution check" on Async, so my async there is not idempotent (which it has to be)
all that being said, I'm planning to expand on that IO for blog post series and/or a playground for the new cancelation semantics (unfortunately the optimisations in cats-effect proper make the code quite convoluted and hard to experiment with, at least for me)
Rafał Sumisławski
@djspiewak @paul-snively @SystemFw thanks sharing your opinions on the topic of implicit Blockers :+1:
Daniel Karch
@SystemFw thank you, I will look at the tests.
Nik Gushchin

Hello guys!)
I’ve started exploring world of FP recently, and now I’m trying tu build my first http-service with http4s.
And I get these debug messages in my console (on every request that consul does):

Request headers: Headers(Host: docker.for.mac.localhost:7000, User-Agent: Consul Health Check, Accept: text/plain, text/*, */*, Accept-Encoding: gzip, Connection: close)
[21:31:24.850] [scala-execution-context-global-40               ] DEBUG - closeConnection()
[21:31:24.850] [scala-execution-context-global-40               ] DEBUG - Shutting down HttpPipeline
[21:31:24.850] [scala-execution-context-global-40               ] DEBUG - Canceled request
[21:31:24.850] [scala-execution-context-global-40               ] DEBUG - Shutting down.
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Shutting down HttpPipeline
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Canceled request
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Shutting down.
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Shutting down idle timeout stage
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Shutting down.
[21:31:24.851] [scala-execution-context-global-40               ] DEBUG - Shutting down.
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Stage NIO1HeadStage sending inbound command: Disconnected
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Shutting down idle timeout stage
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Shutting down.
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Stage IdleTimeoutStage sending inbound command: Disconnected
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Shutting down HttpPipeline
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Canceled request
[21:31:24.851] [blaze-selector-7                                ] DEBUG - Shutting down.

My code looks like:

 def apply[F[_]: Sync: Async](port: Int)(
    implicit cs: ConcurrentEffect[F],
    timer: Timer[F],
  ): F[Http4sPrometheusExporter] = {

    for {
      prometheusService <- Http4sPrometheusService.build[F]
      httpApp = Router[F]("/" -> prometheusService.routes).orNotFound
      server <- BlazeServerBuilder[F]
        .bindHttp(port, "")
        .use(_ => Async[F].never[Unit])
    } yield new Http4sPrometheusExporter()

Is it ok? Or I’m duing something wrong?
Appreciate any help :)

BTW api-endpoint seems to be working properly
Rafał Sumisławski
@Dr-Nikson https://gitter.im/http4s/http4s would be a better place to ask this question.
Nik Gushchin
@RafalSumislawski ok, thanks)
Hi, what if I want to learn how to use the ConcurrentEffect type class? I'm not sure how it relates with IO.