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

add: capability inside a CAF function to do work exempt from cancellation-signal #31

Open
getify opened this issue Oct 9, 2024 · 0 comments
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested

Comments

@getify
Copy link
Owner

getify commented Oct 9, 2024

This might seem quite contrary to CAF's design philosophy, which is that all async work should be cancelable. But, some async work is dependent on users, like prompting them for interactions -- even ones that go through browser prompts outside the control of the main UI thread -- which may not make sense to try to make dependent on cancellation signals (especially timeout based ones).

Here's one example use-case I've run into a few times now:

var whatever = CAF(function*whatever(signal){
   var res = yield fetch("https://some.tld/api",{ signal });
   var json = yield res.json();
   renderResult(json);

   // all done with the cancelable bits now, but some
   // non-timeout-cancelable work left to do
   yield showInfoNotice("Info updated");
});

// elsewhere:
await whatever(CAF.timeout(10_000,"took too long");

In this case, if the showInfoNotice() holds the whatever() task open indefinitely (waiting on user interaction, etc), it might cause the timeout signal to abort.

From an original design perspective, it'd be preferable if that non-timeout-cancelable work was split out into a separate non-CAF task. But whatever() can't invoke such a step, it would have to communicate that in some way back to the caller, perhaps returning a thunk the caller must detect and invoke.


The spirit of this is, sort of like a finally clause that runs after the CAF function has finished, and thus runs outside the purview of the cancellation signal.

I don't think I can actually detect a finally being used, so I don't think that works as an implementation option. But one way to do what I'm suggesting here might look like:

CAF(function*(signal){
   // main work, subject to signal cancellation

   CAF.finally(() => {
      // do some post-cancellation-signal work
   });
});

This has various pros/cons that need to be considered.

An alternative approach is to allow a signal to be "released" from inside the CAF function:

CAF(function*(signal){
   // main work, subject to signal cancellation

   // release this signal from CAF control for the rest
   // of this function
   signal.release();

   // do some post-cancellation-signal work
});

I kind of like this approach better, but it also has its own downsides.

There might be other approaches I haven't thought of yet. Want this to simmer for a bit, see if anyone else has thoughts.

@getify getify added enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers question Further information is requested labels Oct 9, 2024
@getify getify self-assigned this Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant