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

Provide an API to invoke a callback on job cancellation #4117

Open
dkhalanskyjb opened this issue Apr 29, 2024 · 0 comments
Open

Provide an API to invoke a callback on job cancellation #4117

dkhalanskyjb opened this issue Apr 29, 2024 · 0 comments

Comments

@dkhalanskyjb
Copy link
Contributor

Use case

runInterruptible allows one to run blocking Java code and interrupt it when the coroutine it's running in gets cancelled. Internally, this is implemented by reacting to notifications about the job entering the cancelling state.

There is no public API to subscribe to these notifications, but this pattern is occasionally useful outside of runInterruptible.

In general, the use case is to do the same thing as runInterruptible, but for the general problem of stopping some computations when cancellation requests arrive.

Shape of the API

Unclear. Maybe nothing should be added and we just need to document this use case better.

Workarounds

It's possible to get this functionality today, without any special API.

  1. We already have Job.invokeOnCompletion(onCancelling = true) { /* callback */ }, but this is internal API.
launch {
  process.run()
}.invokeOnCompletion(onCancelling = true) {
  process.stop()
}

This seems to be the most straightforward option, but using non-stable API is unacceptable in many scenarios.

  1. One can also write this using a low-level API:
suspendCancellableCoroutine { cont ->
  cont.invokeOnCancellation {
    process.stop()
  }
  process.run()
  cont.resumeWith(Result.success(Unit))
}

It looks non-idiomatic, but it should work.

  1. It's possible to spawn another child for the sole purpose of sending asynchronous cancellation notifications.
launch {
  launch { awaitCancellation() }.invokeOnCompletion {
    process.stop()
  }
  process.run()
}

Note 1: this won't work in a single-threaded dispatcher.
Note 2: the only way for this coroutine to properly complete is to cancel. Otherwise, awaitCancellation will be stuck forever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant