Azure App Service Team Blog

How the App Service team functions

Durable Functions and Bindings Extensibility Preview Announcement

We’re excited to announce two new preview features in Azure Functions:

  • Durable Functions: A framework that makes it easy to orchestrate multiple functions and manage state for your serverless apps.
  • Binding extensibility: A capability that allows you to create your own reusable serverless components that can be used from any supported language.

Durable Functions

In serverless functions, as with many application frameworks, it’s commonly recommended to write your code to be stateless, and this is the best practice. What is often not discussed in detail, though, is how one should manage that state. For trivial scenarios like just standard user data, databases are an obvious option, or for messaging between applications, a queue service is sufficient. However, what if your application has need for a more complex, stateful orchestration of multiple components? Without better tools, you’re left to figure out the right way to combine those pieces. This is the problem that the Durable Functions feature seeks to solve; letting developers abstract away the management of state for complex, stateful orchestration. Today, we’re happy to announce that Durable Functions is now in preview.

Durable Functions builds on the Durable Task Framework, which was designed to allow developers to write code based orchestrations using async/await pattern in C#. This enabled the following:

  • Expression of tasks in simple C# code
  • Automatic persistence and check-pointing of program state
  • Versioning of orchestrations and activities
  • Async timers, orchestration composition

With Durable Functions, we let you write orchestrators and activities as Functions. Orchestrators can call Activity Functions, other sub-orchestrations, and wait for an external event. Combined, this functionality allows a lot of complex patterns to be expressed via code. For instance, the code below will fan out and call various Activity Functions, wait for them all to complete, and then allow you to sum the results (fan in). This pattern was possible before but involved a lot more setup and management code that was unrelated to the business logic.


#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"

public static async Task<long> Run(DurableOrchestrationContext backupContext)
{
    string rootDirectory = backupContext.GetInput<string>();
    if (string.IsNullOrEmpty(rootDirectory))
    {
        rootDirectory = Environment.CurrentDirectory;
    }

    string[] files = await backupContext.CallFunctionAsync<string[]>(
        "E2_GetFileList",
        rootDirectory);

    var tasks = new Task<long>[files.Length];
    for (int i = 0; i < files.Length; i++)
    {
            tasks[i] = backupContext.CallFunctionAsync<long>(
            "E2_CopyFileToBlob",
            files[i]);
    }

    await Task.WhenAll(tasks);

    long totalBytes = tasks.Sum(t => t.Result);
    return totalBytes;
}

In the above code, you can see the first set of bold code fanning out and calling many Functions, and then the later bold line waiting for them all to complete.

What’s happened since alpha?

Since we initially released the alpha preview we’ve seen lots of great community interest and folks experimenting with Durable Functions. In addition to all that feedback, we’ve also been working on a few important enhancements. You can see all the work highlighted on the GitHub repo for Durable Functions extension. Here are some highlights:

Roadmap

In the coming months, we’ll be working towards a GA of the current functionality and investigate the following enhancements:

  • Support for other languages
  • Improved monitoring and management of orchestrations
  • Improve the underlying messaging/data layer to improve the maximum throughput
  • Dynamic repartitioning of orchestrations

Binding extensibility: goodbye SDKs, hello bindings

Developers are building increasingly complex serverless applications and need better mechanisms for code reuse. Triggers and bindings allow developers to focus on their code and let Azure Functions handle all the logistics of connecting to other services, in a way “reusing” the glue code that we have already written for you. We are now providing a mechanism using which you can author your own custom bindings for Azure Functions, providing more avenues for reuse.  This mechanism (binding extensibility) is a feature of the 2.0 Functions runtime. In fact, Durable Functions is authored as a custom binding for Azure Functions.

Bindings allow you to create reusable serverless components that can be used from any supported language. If you host a developer service, bindings will make it easy for Functions developers to use your product. Developers can also create reusable packages and host them in a central repository, just like a library or SDK.

Binding extensibility allows you to provide a declarative interface for an SDK. For instance, we have a sample Slack output binding that sends a slack message when a customer uses a [Slack] attribute (or the equivalent in function.json):

C#

using System.Net;
using System.Net.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using SampleExtension;

namespace SampleFunctionApp
{
    public static class HttpTriggerSlack
    {
        [FunctionName("HttpTriggerSlack")]
        public static string Run(
            [HttpTrigger] SlackMessage message, 
            [Slack(WebHookUrl = "SlackWebHook")] out SlackMessage slackMessage,
            TraceWriter log)
        {
            slackMessage = message;

            return "Ok";
        }
    }
}

JavaScript

module.exports = function (context, req) {
    context.log('JS HTTP function processed a request: ' + req.body.text);

    context.bindings.slackMessage = req.body;
    context.done();
};

Creating a custom binding

Currently, extensions can only be authored in C# but can be consumed from any supported language. To get started, please check out the sample WebJobsExtensionSamples, which has a detailed readme on how to get started. There is also a Slack output binding sample.

Reference documentation is available on our wiki: Creating custom input and output bindings.

Custom triggers

For custom triggers, we plan to offer integration with Azure Event Grid. Stay tuned for more details on this.

Next steps

Please try out Durable Functions and binding extensibility and provide feedback on the experience. We encourage you to try these features in all kinds of interesting ways and help us make them work even better when we GA. As always, we look forward to hearing from you through our Forums, StackOverFlow, or Uservoice.