Re: Future cancellation

Hi Ron,

Thanks for engaging and not being put off by my previous message. I
understand it could have come across as rather abrasive. Apologies for
that. More inline.

On Tuesday, April 30, 2013, Ron Buckton wrote:

>   Alex,****
>
> ** **
>
> Thank you for the feedback.  I’ve also added two more gists:****
>
> ** **
>
> 4. Cancellation using CancellationTokenSource: *
> https://gist.github.com/rbuckton/5490373*<https://gist.github.com/rbuckton/5490373>
>

This is interesting. Is there a reason to allow configuration of the
cancelation token? I had thought the value in having a standard mechanism
(and value for "this future was canceled") would be to avoid per-API
contracts of the sort that might be created here.

Also, if it's really necessary but turns out to be rare, we might imagine
Future/Resolver subclass pairs that are pre-configured with different
cancel values instead of configuration. But I don't have experience with
how common cancelation through chains of Futures with different cancelation
roots is.


> ****
>
> 5. Cancellation using CancelableFuture subclass: *
> https://gist.github.com/rbuckton/5490482*<https://gist.github.com/rbuckton/5490482>
> ****
>
>
>
This design is roughly what I'd sketched out for Anne van Kesteren as what
DOM will need to do for XHR as it already vends the cancelation capability
there.

Our designs for this diverged in that I hadn't overridden then/catch to
enable chaining, instead relying on the "cancel" error value in rejection.


>  Each one of these is an attempt to find out exactly what does and
> doesn’t work with various mechanisms for cancellation that have been
> discussed on these lists as well as in various libraries. ****
>
> ** **
>
> In [1] I added the synchronous flag as a way to ensure that the Future
> that is used for cancellation can resolve and have its resolve callbacks
> run in time. It’s not exactly necessary but there are some cases where not
> being able to cancel synchronously could bite a developer:****
>
> ** **
>
> function someAsync(cancelFuture) {****
>
>   return new Future(function (resolver) {****
>
>     var handle = setImmediate(function () { … });****
>
>     cancelFuture.done(function () { clearImmediate(handle); });****
>
>   });****
>
> }****
>
> ** **
>
> var { token, cancel } = createCanceler();****
>
> var f = someAsync(token);****
>
> cancel();****
>
> ** **
>
> Due to asynchronous resolution, even though cancel() is called
> synchronously it will be scheduled **after** the setImmediate call.****
>
> **
>

This honestly feels like a separate side contract about what it means to
cancel some underlying operation, not what it means to get the resolution
value...and it feels like the sort of thing that cancelable futures need to
navigate with regards to the semantics of the underlying operation that
they're representing. Put another way, it's about what resolvers say to
resolvers and when. ISTM that any future subclass should be able to
schedule synchronous resolution for cancel if it wants to. I don't think
that breaks any invariants of the design. The question now is where that
belongs. Punning too strongly on the superclass resolution semantics feels
wrong, but so does carving out brand new API space for synchronous
resolution until we have at least one more use-case for it. For now, we
could simply say that CancelableFuture cancels synchronously and leave that
up to impls to accomodate. Feels dirty, but preserves the ability to
explain it later with a synchronous flag should we find it more broadly
necessary.


> **
>
> [2] was based on a side discussion around cancellation and similarities to
> revocable Proxies.****
>
> ** **
>
> [3] was based on providing a simple means of cancellation, but I agree
> that there is a danger that a Future that is referenced by multiple
> consumers could be canceled by any consumer.****
>
> ** **
>
> [4] is inspired by cooperative cancellation of Tasks in .NET. I’ve used
> this quite often and found it to be a powerful cancellation mechanism. It
> has the advantage of being very explicit about where responsibilities lie
> as part of cancellation and reducing pollution of the Future API, but it
> does add additional complexity around setup. I’m personally in favor of
> this approach, though not so fond of the name of types.  [1] is partially
> based on this approach as well, except that CTS cancels synchronously and
> can automatically reject a Future.****
>
> ** **
>
> [5] is a possible approach (albeit a naïve implementation) of cancellation
> via a subclass. In its current incarnation it suffers from the same issues
> a [1] and [2], but can be mitigated by having it directly call the
> resolver’s resolve algorithm with the synchronous flag set. It also gets
> lost when using Future.any, etc. ****
>
> ** **
>
> My intent currently is not to advocate any of these approaches. Rather;
> I’m trying to catalogue each approach as I’ve come across them specifically
> to gather this kind of feedback.
>

Much appreciated. I've fretted for some time that I've under-researched the
cancellation aspects of the design (whereas I don't have any such qualms
about the rest of it).


>
> Sent from Windows Mail
>
>  *From:* Alex Russell
> *Sent:* Tuesday, April 30, 2013 2:54 AM
> *To:* Ron Buckton
> *Cc:* es-discuss, public-script-coord@w3.org <javascript:_e({}, 'cvml',
> 'public-script-coord@w3.org');>, Tab Atkins Jr.
>
> These are horribly confused -- and likely foot-gun -- designs.
>
>  First, synchronous resolution needs some justification. I don't
> understand why you've added it in the first design. The question of "does
> the Resolver know it is resolved?" is entirely independent of the
> visibility of that resolution to the outside world. I don't think this flag
> even makes sense.
>
>  In terms of blessing one or another static method for generating the
> cancellable tuple (as you do in your first two designs), why does it have
> to be in the design at this point? The current design in DOM provides a
> small contract to keep us from fighting over how to distinguish
> cancellation from other error values (the side-contract everyone would need
> to re-create at great expense), but purposefully avoids doing this for the
> sake of simplicitly. I don't get why you're trying to expand this contract
> in the core spec. Just subclass. Should it become so common, we can revisit
> this later.
>
>  Lastly, your final design is irretrievably broken in a way the first two
> aren't: it vends to anyone who has a handle to the Future the capability to
> reject it.
>
>  The DOM design has studiously avoided this class of fatal design errors
> so far. It's the key reason why Resolvers and Futures are separate objects.
> No such design will fly in this group.
>
>  Regards
>
> On Tuesday, April 30, 2013, Ron Buckton wrote:
>
>  I’ve created separate gists for three different ways that I am currently
> investigating as a means to support the cancellation of a Future. These can
> be found here:****
>
> ** **
>
> **1.       **Cancellation using Future:
> https://gist.github.com/rbuckton/5486149****
>
> **2.       **Cancellation using Future.cancelable:
> https://gist.github.com/rbuckton/5484591****
>
> **3.       **Cancellation using Future#cancel:
> https://gist.github.com/rbuckton/5484478****
>
> ** **
>
> Each has a list of some of the benefits and issues I’ve seen while
> experimenting with each approach, as well as possible changes to the
> various APIs or algorithms for Future to make each happen.****
>
> ** **
>
> In general, cancellation of a Future can be beneficial in a number of
> cases.  One example is the case where you are requesting a resource from a
> remote server using XHR. If the request was being made to fetch a page of
> data, and the user opted to move to the next page before the current page
> completed loading, it no longer becomes necessary to continue fetching the
> remote resource. In addition, it is no longer necessary to handle any
> additional computation or transformation logic that would have resulted
> from the successful completion of the fetch operation. Having the ability
> to cancel the request allows an application to quickly release resources
> that it no longer needs.****
>
> ** **
>
> It is also useful to be able to handle the cancelation of a long running
> task that might be executing in a Worker. In this case, cleanup logic that
> is part of cancelation would request the worker to close, ending the
> current operation and releasing resources.****
>
> ** **
>
> Both of the above examples are indicative of cancelling the root of an
> operation, but there are also circumstances where you might want to cancel
> a chained Future and any Future chained from it, without canceling the
> root. In the previous example regarding paged data, I might wish to allow
> the fetch operation to complete so that I could cache the data for quick
> retrieval, but would only want to cancel any possible UI updates that might
> occur in a chained Future.****
>
> ** **
>
> I’m interested to hear what others thin
>
>

Received on Wednesday, 1 May 2013 09:43:29 UTC