Managing Durable Functions Orchestration History
I had the privilege of speaking about Durable Functions at the Developer South Coast user group a week ago, and I took the opportunity to update my Durable Functions e-Commerce sample app to take advantage of some new features that have recently been added to Durable Functions.
Orchestrator History
One of the great things about Durable Functions is that the history of each orchestration is stored using an "event sourcing" technique, meaning that it is possible to get a very detailed log of exactly what happened.
In particular you can discover what the input and output data of the orchestrator was, as well as the input and output data of every single activity function or sub-orchestrator that was called along the way. You can access the status of an orchestrator by calling the Get Instance Status API or using DurableOrchestrationClient.GetStatusAsync.
All this information is brilliant for both troubleshooting and auditing purposes. But it does also raise a few questions.
First, if I'm a heavy user of Durable Functions, will my Task Hub fill up with vast amounts of historical data that I no longer need or want?
Second, how can I search back through history to find any failed orchestrations, or orchestrations that are still running but should have terminated by now?
Enumerating Orchestrations
The recent Durable Functions 1.7.0 release includes features that help with both those tasks. It builds on the existing get all instances API, and adds paging capabilities, which would be essential if a large number of historical orchestrations were present.
In my Durable Functions e-Commerce sample app, I have a web-page that uses the get all instances API to show all orchestrations started in the last two hours (which works well for my talks, as I only want to show orchestrations I create during the talk). I do this with DurableOrchestration.GetStatusAsync passing in the start time, and all the orchestration statuses I'm interested in (which is all of them - this method could probably do with a simpler way of expressing that).
var statuses = await client.GetStatusAsync(DateTime.Today.AddHours(-2.0), null,
Enum.GetValues(typeof(OrchestrationRuntimeStatus)).Cast<OrchestrationRuntimeStatus>()
);
Purging Orchestration History
There are several reasons why you might want to purge orchestration history. Maybe you have a strict data retention policy where you don't want to store data older than a certain age. Or maybe you just don't like the idea of your Task Hub filling up with millions of old orchestration history records that you no longer have any use for.
With Durable Functions 1.7, history can easily be purged using the new Purge Instance History API, which allows you to delete either all history for a specific orchestration, or all orchestrations that ended after a specific time. Obviously, you should take care not to purge the history of in-progress orchestrations, or you will get errors when that orchestration attempts to progress to the next step.
In my Durable Functions e-Commerce sample app, I use DurableOrchestrationClient.PurgeInstanceHistoryAsync to allow individual orchestrations to be deleted from my order management page. It's great for when I do a quick practice run before I give the talk and want to hide the resulting history from the UI.
await client.PurgeInstanceHistoryAsync(order.OrchestrationId);
Summary
It's great to see that Durable Functions continues to improve. There are loads more new features I've not mentioned, so do check out the release notes for a full run-down of what's new.
But I'm particularly pleased with these new orchestration history managing APIs. I specifically asked for them and so it's great to see the open source community jump on this and implement my suggestions. These APIs were the one missing feature that I had been waiting for before feeling ready to introduce Durable Functions into one of the products I work on, so many thanks to @gled4er, @k-miyake, @TsuyoshiUshio and everyone else who helped bring these improvements to Durable Functions.