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
@coltfred yes, sleep will yield when waking up (it has to or it would run your action on the scheduler rather than the proper pool)
the fact that you explicitly need a ContextShift will disappear in ce3 though (it's a bit of an implementation leak)
Colt Frederickson
@coltfred
So the reason I don't need fibers in my implementation is because background puts the entire implementation on another thread (is fiber a better word here?)? Also, Daniel inadvertently (I think) switched f and sleep so it's not quite the same? Just checking my understanding.
Fabio Labella
@SystemFw
fiber is a better word
background is just a different combinator that uses Resource to manage start (i.e. a Fiber)
on the jvm this is also likely to mean a different thread, but this is a detail that you shouldn't need to know about
Christopher Davenport
@ChristopherDavenport
They may or may not be on a new "thread" since technically it may never start right. Its just submitted, and might not even start on a synchronous thread pool?
Fabio Labella
@SystemFw
well, actually you have two usages of start
the latter usage is what background abstracts for you
the first usage is not strictly needed because you start and then immediately join
so basically all you are doing is introducing an async boundary, like you would with IO.shift
but you don't need to do that as sleep already does it under the hood
you also don't really need handleErrorWith there

Also, Daniel inadvertently (I think) switched f and sleep so it's not quite the same? J

yeah I think so

@coltfred does that make sense or did I rush it?
Fabio Labella
@SystemFw

Its just submitted, and might not even start on a synchronous thread pool?

I mean, this is always true, but it's not something you generally think about. In most cases there is no need to think about Threads at all, just fibers

Daniel Spiewak
@djspiewak
it's also always worth remember than Threads themselves are a bit more like fibers than you might think
they have very similar semantics, just managed by the kernel atop the processors
Colt Frederickson
@coltfred
If the F dies due to an exception, isn't the handleErrorWith needed to allow the >> to continue?
scala> (IO.raiseError(new Exception()) >> IO(println("foo"))).unsafeRunSync()
java.lang.Exception
  ... 11 elided
@SystemFw Ya, I think I've got it.
Fabio Labella
@SystemFw
@coltfred ah sorry my bad, I overlooked that you have an arbitrary f when I wrote that
although in your specific case it's easier to do f.attempt <* and no handleError at the end
since you essentially want to swallow your error
Colt Frederickson
@coltfred
Fair enough. background gives you an F[A] as the resource, which in the example is just thrown away. I was conducting a thought experiment where startUpdate would actually create the Ref and return it, but then I ended up with Resource[IO, IO[Ref[IO,A]]] so I need to flatMap on the value which I've gotten as the resource (which seems weird). Are there some examples where the value coming out of the IO that's being run by background is actually used?
  //Update r every duration by running f.
  def startUpdate[A](f: IO[A], duration: FiniteDuration): IO[Ref[IO, A]] = {
    def loop(r: Ref[IO, A]): IO[Unit] = {
      for {
        _        <- IO.sleep(duration)
        newValue <- f
        _        <- r.set(newValue)
      } yield ()
    }.attempt >> loop(r)
    for {
      initial <- f
      ref     <- Ref.of[IO, A](initial)
      _       <- loop(ref)
    } yield ref
  }
I guess in this case I've actually mixed things I want done once with things I want to background...
That's probably why it feels weird.
Fabio Labella
@SystemFw
I would expect the IO running in backgrond to be loop yeah, so no value from there
you are writing the equivalent of fs2.hold basically
Colt Frederickson
@coltfred
I have access to fs2 in this project... I'm a fs2 neophyte.
Fabio Labella
@SystemFw
I think experimenting the way you're doing it is valuable btw, so don't use fs2 just because I said so

although

Stream.repeatEval(f).metered(duration).hold(initial).compile.resource

should do the whole thing for you

it will be Resource[F, Signal[F, A]] rather then Ref, but they both have .get: F[A]
Colt Frederickson
@coltfred
Sure.
Why does background give you F[A] for the value in the resource? I don't understand where or when that would be useful.
Fabio Labella
@SystemFw
it's only useful if you eventually want to join on the fiber
background basically means "spawns this fiber, but keep track of canceling if I get canceled for me"
the F[A] that it returns you if the join on the fiber you have spawned
in this case you don't want that, since you are getting the results through the Ref instead (a pretty common pattern, which is why fs2 has hold)
Colt Frederickson
@coltfred
It doesn't give you a fiber though, it gives you an IO
Fabio Labella
@SystemFw
so does join
Colt Frederickson
@coltfred
oh.
Fabio Labella
@SystemFw
there's no need to give you a full Fiber, since cancelling is taken take for you by the Resource
trait Fiber[F[_], A] {
  def join: F[A] // wait for this fiber to complete, give me result
  def cancel: F[Unit] // cancel and wait for the fiber to finalise
}

def start(fa: F[A]): F[Fiber[F, A]] // start a fiber with `fa`, and give a handle to wait for it or cancel it
as a refresher
whenever you use start directly, you risk leaking a fiber (and the process you have spawned within it
since you can do start >> doSomething or start.flatMap { doSomething with fiber
but if get canceled externally (e.g. by a call to timeout), the fiber you have spawned would just keep going in the background
Daniel Spiewak
@djspiewak
you should basically think of Fiber as being very similar to a network socket