Is there a recommended pattern for cancellation?
See original GitHub issueWhen calling a HTTP API or doing other long-running tasks, one might need to support cancellation. This could be explicit using a “Cancel” button, or implicit, e.g. cancelling any ongoing requests when signing out of the app.
Is there a recommended pattern for cancellation in Fabulous? Should CancellationTokenSource
s for any unique cancellable request be stored in the model and replaced when cancelled, or are there better ways? (And would that cause issues if serializing/deserializing the whole model, including CancellationTokenSource
s?)
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:36 (1 by maintainers)
Top Results From Across the Web
Recommended patterns for CancellationToken
Know when you've passed the point of no cancellation. Don't cancel if you've already incurred side-effects that your method isn't prepared to ......
Read more >Is there a recommended pattern for cancellation? #380
I have an app that is very API-based, where there is no technical reason why there can't be multiple requests in flight at...
Read more >A Deep Dive into C#'s CancellationToken | by Mitesh Shah
Recommended Patterns for Cancellation Tokens. I wish I knew a lot about cancellation tokens to recommend some patterns of my own. But until...
Read more >How to Create a Cancellation Policy: Templates + Examples
Try these cancellation policy templates, tips, and examples to write a winning cancellation policy for your home service business.
Read more >6 Cancellation Flow Examples To Help Reduce Customer ...
Best collection of cancellation flow examples. Get inspiration from top SaaS brands and reduce churn by implementing churn surveys right ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
That was an interesting article. He makes some points which I am sure are valid on fully implemented actor based systems like Akka running at scale. I also totally agree that there is no point in using an actor if you don’t need to manage state, just use a normal function. I think his definition of cache is a bit different to mine, I just mean some data needed at runtime but not stored on disk, or an in-memory reflection of some on-disk data to make access easier and faster, not a static store.
I will start here by saying that I am a fairly junior programmer, about 5 years pro, and only a year on F#, and mostly self taught, so I am probably a little off the mark on some things here and welcome any input from more knowledgeable people.
I think it is initially important to make a distinction between using actors and the actor model of software design.
At a very basic level, an actor is just a recursive loop with a message queue that runs on its own thread - no more, no less. I really like the fact that F# has a simple, lightweight and stripped down implementation included out-of-the-box, the MailboxProcessor. As it just uses a delegate that runs recursively, you can replace the state on each loop, and because it has an inbox you can post it messages and it will work through them as and when it can.
The actor model isn’t a framework, it is a configuration-based model of computation and interaction, as opposed to a traditional state based turing machine model. Frameworks like Akka build on the concepts by providing tools such as an actor registry / resolution system, distribution across machines, failure handling, loads of stuff, but they aren’t the model themselves any more than Fabulous ‘is’ MVU.
If you are interested in the fundamental concepts and power of the model-proper, there is an essential talk by the guy who invented it, Carl Hewitt (interviewed by Eric Meijer) here: https://www.youtube.com/watch?v=7erJ1DV_Tlo They explain (in an informal way) the essential axioms – that actors can only talk to other actors, and messages can be received at any time but and at most once etc etc. and what this brings to reasoning about interaction. The bit that really struck a chord with me is that it models indeterminacy (as opposed to non-determinacy) in a real way, which you can’t do with direct method calls, and that in turn forces you to consider it in your system design. It makes you think in terms of domain events which can happen in any time in any order. You think about the interaction much more than the state.
There is also a great amount of info here: https://doc.akka.io/docs/akka/current/guide/actors-intro.html
There is obviously a lot of potential to model complex applications using a full, strict system like this, and arguably you would get more out of it the more you embrace it, much like MVU and FP in general.
However, most of this is way more than I need right now for a mobile app and certainly a whole world away from what I am suggesting in the context of this thread.
I think talking about the actor model is a bit like event sourcing – everyone has a different understanding (or lack thereof) of exactly what it is or how you do it or to what extent.
I have taken the same approach here as I did there – try to understand the fundamental concepts, then implement the bits I understand which are useful in a pragmatic way to improve my daily code, rather than try to go full bore into creating a pure event sourced or actor based application because it is the latest thing and making an expensive mistake, or alternatively ignore it altogether and keep on doing things the inefficient way I had always done them.
A little background: I create Xamarin apps at work, previously in C# exclusively. I received the Reactive Patterns w/ Actors book I linked to earlier as a gift, and found it fascinating although a little heavyweight as Akka is a full framework and overkill for my needs and Scala makes my eyes bleed. Most of the book however is just a general pattern reference, it isn’t that specific to the language or framework.
A little while later I found (fell in love with) F# and started using it for the core Xamarin work. I needed to manage some application state, and the mailbox processor was easy to use and worked really well for many things. It allowed me to make use of many of those patterns where appropriate whilst not marrying a large framework, everything I needed was right there in the language.
It also was a revolution when dealing with the database. I no longer need to worry about concurrent writes. I have a single mailbox which manages the write connection. No more locks or anything. My reads happen using separate actors – I currently have one per table as I have a generic implementation that I instantiate with a return message type. This is my own ad-hoc approach which fits my apps, and is a lot better than what I had before (locking a SQLite connection). I never need to worry about massive parallel access, as my apps don’t do that. If they did, I would research an appropriate solution for that scenario.
The one thing I did find on my last project was that without a formal way of connecting the mailboxes, it can be hard to follow the flow of control for anyone unfamiliar with the architecture in question. That is why I have embraced MVU – it gives a rigid backbone for the application which can call into side-processors as necessary, making it easy to navigate and reason about.
It may not be perfect, and it may not be strict MVU or Actor Model or FP or OO or whatever, but I know why I made every decision (and compromise), it works really well and I have basically no external dependencies. It is the best of all the worlds I know of done the best way I know how, which is all any of us can do hey. I am working on a proper project with all of this included right now which I am happy to share if anyone is interested, it will end up on Github eventually.
Ok, so all of that said, I will reiterate that I am just simply talking about using the mailbox processor as a state bucket in this context, the most basic way you could think of. No big computing model or framework to deal with, just a small recursive loop with a stashed thing in it. The most basic way you can maintain state without a mutable field, and arguably simpler to reason about.
How would I implement the cancellation loop using the cmd I posted previously? Something like this:
I have included the types for completeness, it should actually compile if you import the cmd from earlier in the thread.
As previously mentioned, this example is a ‘one request at a time’ set-up where each cancels the last, but you could easily expand it, and adapt it to handle any kind of state.
The important bit is how nice it looks in the update func now, and if you strip all the comments out of the mailbox it is only a few lines. You are completely in control of how you use it, that depends on the mailbox body, and the Cmd is very generic, just like OfAsync but with an extra callback message.
Elmish, not Elm. I have no idea what Elm uses. (Not MailboxProcessor of course, since that’s F# specific). You can read about the reasons for the switch in this PR and the three linked issues: https://github.com/elmish/elmish/pull/160
5 more simple-to-understand lines added to the already simple function-based solution is IMHO not vastly more complex - I’d say it’s still very simple. Also, I’m trying to solve this particular case, not state management in general. As I said, I appreciate that actors/queues/etc. is a very powerful pattern and the right tool for the job in many contexts. 😃
Thanks for the conversation! I’ll make sure to investigate MailboxProcessor a bit more on my own time.