Kotlinx.coroutines: Deprecate and remove Job.cancel(cause)

Created on 7 Aug 2018  路  5Comments  路  Source: Kotlin/kotlinx.coroutines

Job.cancel(any exception) is a cumbersome API:

  • It has unclear semantics (especially after #333 fix, when cancel(cause) can return true more than once for the sake of exception handling)
  • It shares a given exception between multiple coroutines which can mutate it
  • It doesn't provide any significant value from the user-facing API standpoint, because cancel can return false, forcing a user to handle an exception on the callsite anyway

As for implementation, it complicates Job exception handling a lot and has a lot of maintenance burden as opposed to Job.cancel() or Job.cancel(message: String)

We can remove cancel(cause) from public API and move it to attachChild machinery (e.g. by introducing ParentHandle instead of DisposableHandle).
It should make parent-child communication (-> cancellation and exception handling) much simpler and open a door for state machine optimizations.

If someone has a use-case which cannot be reasonably implemented without cancellation with a custom exception, let's discuss it here.

breaking change enhancement help wanted

Most helpful comment

After discussion with @LouisCAD I've found at least one use-case which is hard to workaround: external callback-based API working as parent/owner of the job.

An example may be found here.
In this example, CameraDevice (CameraDevice.StateCallback) actually owns the job and cancels it any (asynchronous) error occurred with that error. And it's essential for a user to get this error on completion.await(), otherwise troubleshooting may be cumbersome.

Workaround without cancel(cause) requires to create one more Deferred and pass it as parent of the completion, but it makes code less readable

All 5 comments

After discussion with @LouisCAD I've found at least one use-case which is hard to workaround: external callback-based API working as parent/owner of the job.

An example may be found here.
In this example, CameraDevice (CameraDevice.StateCallback) actually owns the job and cancels it any (asynchronous) error occurred with that error. And it's essential for a user to get this error on completion.await(), otherwise troubleshooting may be cumbersome.

Workaround without cancel(cause) requires to create one more Deferred and pass it as parent of the completion, but it makes code less readable

It's worth noting that the use case shown above uses cancel(cause) on a Deferred (which is a subtype of Job).

cancel(cause) could be moved from Job to Deferred, which would imply that cancelling a Job from the outside with a custom Throwable/Exception would no longer be possible.

That may be a good thing since doing so with a Throwable which is not a subclass of CancellationExcepion causes a crash that can only be avoided with a custom coroutine exception handler.

If anyone uses job.cancel(cause) on a type that is not a Deferred, please comment and explain your use case (and link any open source lines or gist).

@LouisCAD Keep in mind the idea spelled out in #220 (abolish difference between cancelled and failed job). We have CompletableDeferred.completeWithException(cause). It does not look like we would need cancel(cause) there.

@elizarov I have read the issue you linked thoroughly, and I agree on merging the failed state into the cancelled state, makes it easier to reason about.

However, you are talking about replacing CompletableDeferred.completeExceptionally(cause) by cancel(cause). I think this is great thing as it caused a bit of confusion to me when I used CompletableDeferred not so long ago, but this can't be done if cancel(cause) is removed from Job and not added back to Deferred, am I right? What are the plans for this?

BTW, I think all these changes should appear in the same release to allow "one shot" migration.

@elizarov note that completion is deferred returned by async call, it's not a CompletableDeferred instance and has no completeWithException.

IMO having complete* family on Deferred is a bad idea as we have seen in CompletableFuture API

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elizarov picture elizarov  路  116Comments

elizarov picture elizarov  路  63Comments

elizarov picture elizarov  路  40Comments

elizarov picture elizarov  路  62Comments

NikolayMetchev picture NikolayMetchev  路  46Comments