Cats-effect: Incorporate linebacker

Created on 14 Jul 2018  路  21Comments  路  Source: typelevel/cats-effect

I'd love for linebacker to be incorporated directly in to cats-effect. We've discussed doing so in Gitter but I didn't see an issue for it.

We could incorporate the current version in cats-effect 1.0 and then an adjusted version in 2.0 that accounts for changes in model (e.g., RTS or whatever else ends up changing).

https://github.com/ChristopherDavenport/linebacker
https://github.com/functional-streams-for-scala/fs2/pull/1167

Most helpful comment

@alexandru When you're back from vacation, let's discuss this in more detail. I'd really like to see this integrated in to 1.0, as the ad-hoc solutions in FS2 aren't ideal. If we don't think this is a fit for cats-effect, we could merge the FS2 PR that adds linebacker as a dependency, but there's nothing about linebacker that's unique to streaming, which indicates that this should probably be baked in to cats-effect.

All 21 comments

On first glance seems interesting, but I have to give it a proper review once I鈥檓 back from my holiday.

I think even when some parts won't fit now in cats effects properly we shall invest resources in merging this into effects before 1.0. It is important part that is now missing in effects, and users tend to do things manually, often erroneously.

@alexandru When you're back from vacation, let's discuss this in more detail. I'd really like to see this integrated in to 1.0, as the ad-hoc solutions in FS2 aren't ideal. If we don't think this is a fit for cats-effect, we could merge the FS2 PR that adds linebacker as a dependency, but there's nothing about linebacker that's unique to streaming, which indicates that this should probably be baked in to cats-effect.

Hey, yes we can talk.

I'm planning to play a bit with it tonight.

Hey, so there is some code in linebacker and I was wondering if we could maybe incorporate it as a sub-project, you pick the name. The litmus test for me is that thread pools are not relevant for JavaScript.

Would that work?

I think so - I hadn't considered the JavaScript point. Only potential problem with a subproject is making sure the integration with Timer and App work nicely. As @wedens alluded to this week, offering both Timer[F] and linebacker is confusing and there are no guidelines on how to put all the pieces together. Hence we might need to include the linebacker functionality directly in the main jar but only in the JVM artifact. I agree that we shouldn't make the JavaScript experience worse though.

Timer isn't about thread pools or multi-threading, it never was. Of course Timer#shift, like IO.shift before it, can be used for continuing execution on a different thread-pool, however in truth this behavior is very IO-specific. Because with Monix's Task for example, because the run-loop has its own internal "Scheduler", you do not get a guarantee that the continuation will run on the indicated thread-pool.

You can think of shift as yielding control back to the run-loop (e.g. setTimeout or setImmediate), being there for fairness reasons, but it's not for selecting a thread pool and in truth that piece of functionality only works for cats.effect.IO.

And to drive this point home, consider that with Monix:

  1. Timer[Task] is available without having an ExecutionContext in scope
  2. Task.shift does not take an ExecutionContext parameter (it has an overload, but you have to pass it explicitly, otherwise it works with no params)

Not sure what the conversation with @wedens was, but I don't think we can integrate something like Linebacker into IOApp, or anywhere else.

If it's an add-on that users can use on top of the JVM, that's totally fine by me, but in cats-effect (the core) it's a leaky abstraction.

Timer isn't about thread pools or multi-threading, it never was.

I don't think this is clear at all. There's Async.shift and Timer.shift -- of course folks will conflate these together. For instance, in fs2 right now, we use this pattern to handle blocking calls:

val blockingTask: F[Whatever] = ...
F.bracket(Async.shift(blockingExecutionContext))(_ => blockingTask)(_ => timer.shift)

I don't think we can integrate something like Linebacker into IOApp, or anywhere else.

I'm not convinced of this. The point in incorporating this in to cats-effect is to provide an out of the box solution for dealing with blocking calls.

Why does FS2 handle blocking calls?

Java interop for working with things like blocking input streams (in the io module, which is jvm only). Search this file for blockingExecutionContext: https://github.com/functional-streams-for-scala/fs2/blob/fb74ea0bd6438fb63092a3dad6db6b4fdb9ce752/io/src/main/scala/fs2/io/io.scala#L5

Another use case from Doobie is handling things like F.delay(blockingJdbcCall).

Doobie PR - https://github.com/tpolecat/doobie/pull/759

Which fixes a common problem people have since JDBC is blocking

I think the problem is that we want to shift execution temporarily to "blocking" EC, and then guarantee it will return to "normal" EC if it completes or fails. Why we just cannot have this on Instances that do have shift already?
Something like shiftOn(blockingEc)(f: F[A]): F[A] ?

Just to be clear I think it is in fact completely same problem like we do now with Timer#sleep except for sleep we are using special scheduled EC

That might be a good idea, not really sure. One thing I don't like is that we are going to expose again ExecutionContext.

Where are we going to put shiftOn? On Timer?

Actually, the only place where shiftOn can go is on Timer. Because only Timer knows where to shift back.

I am fine to put it on timer, not sure if it shall be name shiftOn, shiftBack, evalOn or whatever :-)

In Monix it is called executeOn and has the semantics you want.

@ChristopherDavenport what do you way?

So trait Linebacker has mostly the same semantics as @pchlupacek suggestion, but a shiftOn as proposed has a smaller API surface so to speak.

Would you like to work on it?

I will take this, my pleasure. 馃槃

Is this still relevant now that ContextShift exists?

Nope, it is still useful as it makes it much easier to use, but the baseline behavior is now available here.

Was this page helpful?
0 / 5 - 0 ratings