Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Queued but unstarted work on Dispatcher.sequential should be cancelable #4069

Open
mperucca opened this issue Apr 30, 2024 · 6 comments
Open
Labels

Comments

@mperucca
Copy link

A queued task to a dispatcher cannot be canceled:

import cats.effect.std.Dispatcher
import cats.effect.unsafe.implicits.global
import cats.effect.IO
import scala.concurrent.Await
import scala.concurrent.duration.Duration

val (dispatcher, shutDownDispatcher) = Dispatcher.sequential[IO].allocated.unsafeRunSync()

dispatcher.unsafeToFuture(IO.never)
val cancel = dispatcher.unsafeRunCancelable(IO.unit)
Await.result(cancel(), Duration.Inf) // hangs

Perhaps this is explained somewhere, but it was surprising to me.

@armanbilge
Copy link
Member

* Sequential mode is the simplest of all: all work is executed in-place and cannot be canceled.
* The cancelation action in all cases is simply `unit` because the impure submission will not be
* seen until after the work is completed *anyway*, so there's no point in being fancy.

If you need cancelation, use Dispatcher.parallel

@mperucca
Copy link
Author

mperucca commented Apr 30, 2024

Ah, thanks. I was unknowingly reading the 3.5.3 scaladocs that my IDE had cached instead of the 3.5.4 ones. (Unfortunately Dispatcher.parallel doesn't fit our use case as we're replacing a cancelable actor model. The private Dispatcher.sequentialCancelable actually looks to have the behavior I was expecting though.)

@armanbilge
Copy link
Member

Unfortunately Dispatcher.parallel doesn't fit our use case as we're replacing a cancelable actor model.

I see, can you say more about why it doesn't fit your usecase?

@mperucca
Copy link
Author

mperucca commented Apr 30, 2024

We only want one action happening at a time in the order that Dispatcher.unsafe* is called, but we want any unstarted work to be cancelable. (We're migrating some code that had those semantics.)

@armanbilge
Copy link
Member

We only want one action happening at a time in the order that Dispatcher.unsafe* is called

I see, are you calling Dispatcher.unsafe* from a single thread or multiple threads? which variant of unsafe* are you using?

@armanbilge
Copy link
Member

armanbilge commented May 1, 2024

but we want any unstarted work to be cancelable.

Ohhh I'm sorry I missed this subtlety. Actually I completely agree with you. This should be fixed. Canceling running work is challenging, but unqueued work should definitely be cancelable. I remember complaining about this too 🤔

Edit: aha, I think I raised this issue on Discord.

@armanbilge armanbilge changed the title Dispatcher unable to cancel queued tasks Queued but unstarted work on Dispatcher.sequential should be cancelable May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants