Four years ago I’d written a post “How to hibernate async methods (how to serialize a task)“. I decided to dig it up and improve it. Here’s what I can now write with it:
// This kicks off the async method. But it allows the async method to
// serialize its state to disk.
// This serializes a snapshot of the async method’s current state to disk.
// It also serializes the async caller who is awaiting it, and so on
// all the way up the async callstack (up to "RunWithCheckpointing")
throw new Checkpoint.Defer(Timespan.FromHours(1));
// I can abort my current method now. A worker will resume
// it in time, once a condition is met (in this case a delay for one hour)
Task t = Checkpoint.ResumeFrom("a.json");
// You can transfer that serialized state across the wire to another machine,
// who can deserialize it to resume work exactly where it left off.
// The task "t" here stands for the top-level AlphaAsync().
My idea is to enable a kind of “async workflow” — I’d like to write my long-running processes as async methods, using for loops/while loops and exceptions and recursive functions and all that – things where the current execution state is actually a pretty complicated thing to serialize manually, and where I need all the assistance I can get. The “Checkpoint” class provides that assistance.
Where might it be useful? …
- You could kick off a long-running method on Azure, which saves its state periodically. If the Azure VM goes down then another VM can just pick up where it left off.
- You could write an interactive website which prompts the user to click a button, then saves its state to disk and releases all resources. When the user clicks the button on their website, that incoming HTTP message causes the state to be picked up from where it left off.
- You could write a mobile agent, which can migrate to another machine to be near to some local resources to do the rest of its work.
I don’t know if this idea has legs! It might be completely crazy. It might be that serializing state is too difficult to do reliably.
Source code is here: https://github.com/ljw1004/blog/tree/master/Async/AsyncWorkflow
Please let me know if you have thoughts on this – feasibility, directions, improvements etc. Next time I revisit this topic, I plan to make the code more robust – make it deal with VB, with ConfigureAwait(), with Task.WhenAll and Task.WhenAny, and most importantly make it uses EntityFramework to serialize the current state of async methods in the async callstack. Once that’s done I’ll package it up as a NuGet library.