Repository navigation
Bracket for Task/Coeval, Task.cancelable and Task.onCancelRaiseError - #561
Conversation
| * as input the resource that needs that needs release, along with | ||
| * the result of `use` (cancellation, error or successful result) | ||
| */ | 8000||
| final def bracketE[B](use: A => Task[B])(release: (A, Either[Option[Throwable], B]) => Task[Unit]): Task[B] = |
There was a problem hiding this comment.
Just to be 100% clear, Either[Option[Throwable], B] here means, that
Left(None) is cancelled,
Left(Some(ex)) is an error, and
Right(b) is success, correct? :)
There was a problem hiding this comment.
Yes. I'm also waiting on that ADT defined in cats-effect, for whenever it will happen, to introduce another overload.
| * | ||
| * For those cases you might want to do synchronization (e.g. usage of | ||
| * locks and semaphores) and you might want to use [[bracketE]], the | ||
| * version that allows you to differentiate between nuormal termination |
| * if (n > 0) | ||
| * loop(n - 1, b, a + b) | ||
| * else | ||
| * a |
There was a problem hiding this comment.
Shouldn't it be Task.now(a)?
| * {{{ | ||
| * Task(println("Hello ...")) | ||
| * .cancelable | ||
| * .flatMap(_ => println("World!")) |
There was a problem hiding this comment.
I think println needs to be wrapped in Task
| * {{{ | ||
| * import java.util.concurrent.CancellationException | ||
| * | ||
| * val tenSecs = Task.sleep(10.seconds).onCancelRaiseError |
There was a problem hiding this comment.
Forgotten parameter for onCancelRaiseError
| acquire.flatMap { a => | ||
| val next = try use(a) catch { case NonFatal(e) => Task.raiseError(e) } | ||
| next.onCancelRaiseError(isCancel).transformWith[B]( | ||
| b => release(a, Right(b)).map(_ => b), |
There was a problem hiding this comment.
So as I understand that correctly, if release throws or return a failed task, it will shadow the exception from use. Maybe it should use reportFailure from current scheduler instead?
|
My last comment got hidden, but it kinda was important: what happens if both |
Codecov Report
@@ Coverage Diff @@
## master #561 +/- ##
=========================================
+ Coverage 90.53% 90.6% +0.06%
=========================================
Files 367 369 +2
Lines 9742 9782 +40
Branches 1838 1841 +3
=========================================
+ Hits 8820 8863 +43
+ Misses 922 919 -3 |
|
@oleg-py that's a very good point. I added a detailed reply here: typelevel/cats-effect#113 (comment) Currently the behavior, if both
I'll modify the behavior to be consistent with the one in Haskell, that I just tested:
|
|
@oleg-py I have implemented the changes. |
|
@oleg-py given your involvement in So what say you? Does it look good after the latest changes? UPDATE: corrected the username |
|
@alexandru looks great 👍 |
|
wow! This is awesome! |
|
|
Introducing:
task.cancelablefor activating the auto-cancelable run-loop for a certain tasktask.onCancelRaiseErrorfor throwing an error in case the source task gets cancelled, in a thread-safe waytask.bracketandtask.bracketEfor resource handlingBracket
The
bracketoperation would be the equivalent oftry {} finally {}in many mainstream languages.For both
TaskandCoevalit comes in two flavors. One would be the simple version:And
bracketEwhich allows distinguishing between successful termination, termination in error or, in the case ofTask, cancellation:Also see the discussion at: typelevel/cats-effect#113
task.onCancelRaiseError
In Monix normally tasks are non-terminating on cancellation. This method transforms a task into one that terminates with error on completion:
task.cancelable
This is the opposite of
uncancelable, activating "auto-cancelable flatMap chains" for the given task on evaluation. Consider this loop that calculates the n-th Fibonacci number:By specifying
cancelableon the loop, we are ensuring that the internal cancellation flag is checked on asynchronous boundaries, automatically interrupting the evaluation if needed.