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
CancelableFuture #1655
CancelableFuture #1655
Conversation
Seeing that that this is an impure construct meant mainly for interop with Future-based programs, it appears that |
I'm also wondering about |
My initial idea was Since we return the |
You can access the runtime at any point using |
In order to run the About |
final def toFutureWith(f: E => Throwable): UIO[CancelableFuture[E, A]] =
ZIO.runtime[Any].flatMap { runtime =>
// construct CancelableFuture here, using the runtime
} |
|
core-tests/shared/src/test/scala/zio/CancelableFutureSpec.scala
Outdated
Show resolved
Hide resolved
core/shared/src/main/scala-2.11/zio/FutureTransformCompat.scala
Outdated
Show resolved
Hide resolved
|
||
object CancelableFutureSpec | ||
extends ZIOBaseSpec( | ||
suite("CancelableFutureSpec")( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the new ZIO Test!
@iravid I’ve understood now – it didn’t occur to me to refer to the |
Is there anything I can do to help with this? |
It will be ready soon. I am at the hackathon and will wrap it up tomorrow |
@fsvehla I'm jealous - wish I could be there! |
22409ef
to
3d30fe7
Compare
addressed all comments. |
|
||
package zio | ||
|
||
trait Cancelable[+E, +A] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only used in Cancelable
, right? In that case, I'd inline it completely so we can delete the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jdegoes You were actually correct, there is java.util.Cancelable
def cancel(mayInterruptIfRunning: Boolean): Boolean
def isCancelled(): Boolean
def isDone(): Boolean
Let’s use that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That JCP was never accepted,
Inlined. |
extends Future[A] | ||
with FutureTransformCompat[A] { | ||
|
||
def cancel: Exit[E, A] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could return another Future
instead of blocking the current thread?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no strong opinion here, but see
#1655 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if we go back to the original use case:
We've started introducing zio at the edges of our system. This results in having multiple
unsafeRunToFutures
running in different actors. I'm looking for advice on terminating these from outside of zio (e.g. when the parent actor is shutting down).
I'm fairly sure introducing a potentially never-ending blocking operation inside an akka actor is a big no-no. Note that Future
/scala.Promise
is also impure and it's already running the moment it's returned, so it's no less ergonomic to use it in impure code. In fact, I'd expect that most users will not care about the Exit
return AND might not want to wait until the fiber is interrupted, in which case the default run-and-forget
behavior of cancel
without Await
is preferrable.
Note that there would be no way for a user to achieve run-and-forget
without blocking a thread if we commit to a synchronous API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍, Kai. My initial idea was to return an UIO[Exit[E, A]]
, because the runtime would have been around anyway at the call site where the CancelableFuture
is created. Returning a Future
sounds like a good compromise
import scala.concurrent.duration.Duration | ||
import scala.util.Try | ||
|
||
private[zio] abstract class CancelableFuture[+E, +A](val future: Future[A]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to make it public so that users can use the additional cancellation ability!
Addressed comments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
new CancelableFuture[E, A](p.future) { | ||
def cancel: Future[Exit[E, A]] = runtime.unsafeRunToFuture(interrupt) | ||
} | ||
} <* self.await | ||
.flatMap[Any, Nothing, p.type](_.foldM[Any, Nothing, p.type](failure, success)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if type annotations could be avoided if concurrent.Promise[A]
is used in success/failure
returns instead of p.type
@fsvehla Thank you for all your work on this feature, and congratulations on your first ZIO contribution! |
ZIO team - thanks for addressing this! |
* Introduce CancelableFuture * Fix race in CancelableFutureSpec * Impure cancel * Inline Cancelable * Make CancelableFuture public * cancel returns a Future * Format * Fix mdoc
Closes #1627
Delegates calls to a
Future
that it wraps. I’ve found a lightweight way to support Scala 2.11 as well.