question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Discussion on async/cancellation and exceptions

See original GitHub issue

@TIHan and I have been discussing using FSharp.Data.Adaptive in future work on making parts of the F# compiler and FSharp.Compiler.Service more incremental.

We’ve some questions about async, cancellation and exceptions.

As context, in our current incremental model the operations to evaluate final nodes in the dependency graph are always cancellable. In the language of FSharp.Data.Adaptive I believe this means as follows. Consider these operations:

ASet.map: ('T -> 'U) -> aset<'T> -> aset<'T>
Aset.contains: aval<'T> -> aset<'T> -> aval<'T>
Aset.elements: aset<'T> -> aval<Set<'T>>
Aval.force: aval<'T> -> 'T

In these cases, the 'T -> 'U functions are not cancellable and might throw exceptions. My understanding is that

  1. if any such function throws an exception then FSharp.Data.Adaptive never “saves” the exception as a result, it is just always propagated all the way up to the routine that requested the result.

  2. some parts of the dependency graph calculation may have been committed, and this is done in an atomic way (there is a related question about concurrent update requests)

  3. there is no special treatment if OperationCancelledException is thrown, and so throwing that exception is a valid way to represent cancellation.

  4. however there is no cancellation token propagated, so these functions have to capture an exterior cancellation token.

Now one could imagine a variation on FSharp.Data.Adaptive that either

  1. propagates a cancellation token

  2. uses a computation expression like cancellable { ... } to represent synchronous cancellable code

  3. uses an existing computation like async { ... } that has cancellation built in (but is richer, as it represents asynchronous code)

Which would lead to signatures like this (option 1)

ASet.mapCancellable: (CancellationToken -> 'T -> 'U) -> aset<'T> -> aset<'T>
Aval.force: aval<'T> * ?cancellationToken: CancellationToken -> 'T

or this (option 2)

ASet.mapCancellable: ('T -> Cancellable<'U>) -> aset<'T> -> aset<'T>
Aval.force: aval<'T> -> Cancellable<'T>
Cancellable.run: Cancellable<'T> * ?cancellationToken: CancellationToken -> 'T

or this (option 3)

ASet.mapAsync: ('T -> Async<'U>) -> aset<'T> -> aset<'T>
Aval.force: aval<'T> -> Async<'T>

or this (combo of option 2 and 3 for tasks)

ASet.mapAsync: (CancellationToken -> 'T -> Task<'U>) -> aset<'T> -> aset<'T>
Aval.force: aval<'T> * ?cancellationToken: CancellationToken -> Task<'T>

I’m curious about your thinking about this. Obviously complicates things.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:10

github_iconTop GitHub Comments

1reaction
krauthaufencommented, Apr 29, 2021

FYI @dsyme

It may also be interesting to give more samples/demos with database and file system connections into this system, e.g. a sea of adaptives adapting to changes on disk. And in general more systems programming samples. Every time I build a project/file-watcher tool like fsdocs I think it should be using adaptive…

I just implemented AdaptiveFile and AdaptiveDirectory and a little example using them HERE

Hope that helps with future directory-watchers 😁 Cheers

0reactions
krauthaufencommented, May 4, 2021

Cool 👍

Actually I didn’t check nested deletions, so i guess that means it will have the locking problem. Semantically the nested removal should work fine via ASet.collect

We should certainly look into the locking things…

Read more comments on GitHub >

github_iconTop Results From Across the Web

Async Tasks, Cancellation, and Exceptions
and the TaskCanceledException. A task abstracts a single task/job that executes asynchronously, eg the code that runs in response to the event.
Read more >
AsyncSequences and cooperative task cancellation
In this thread I would like to discuss the cooperative task cancellation in context of AsyncSequence conforming types.
Read more >
Rust Async, Cancellation and transactions question
Async cancellation can be influenced by an external actor potentially maliciously on requests, which for me puts it in a different risk bucket....
Read more >
Tracking the source of cancellation in tasks - Python discussion
asyncio's cancellation is a special case here: the cancellation error is often “injected” by something outside of the current task's stack, and ...
Read more >
A Deep Dive into C#'s CancellationToken | by Mitesh Shah
We have an object that creates one or more long running asynchronous operations. This object will pass this token to all of these...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found