Using Durable Functions, how to return multiple values from an Activity Functions

大憨熊 提交于 2020-07-21 07:21:11

问题


I’m a big Domain Driven Design fan and developer, and am always attempting to map technology/architecture into the world of DDD. Mapping microservices to bounded contexts provides for a natural marriage. At the end of the day, I just want to focus on my business logic and host that in the right environment. Durable Functions looked promising to me, in needing to solve the distributed transaction problem across microservices, Sagas or Process Manager if you will. I have been using NServicebus for years, and love their Saga technology, but would like to leverage Durable Function orchestrations for handling saga logic.   The architecture problem that I am currently having is the following. I have mapped the DDD Application Service to an Activity Function. A Saga would therefore be created simply with an Orchestrator tapping the right set of Activity Functions to run their transactions. Building out a rollback is pretty straightforward as well conceptually, but I am having an implementation problem. As an aside, each Activity Function will delegate to a library that handles all the business logic details, and will then take the list of events returned by the business logic and return that back to the Orchestrator. As far as I have researched, there is no way to return a polymorphic return value from an Activity Function. So if my business logic generates either a UpdateSucceeded or a UpdateFailed event, how would I simply return that from my Activity Function back to the Orchestrator so that the Orchestrator can take corrective action by calling distinct rollback Activity Functions?


回答1:


You can use the new custom serializer support in Durable Functions 2.1.0 to do this. It still needs to be documented but basically it works like this, using Azure Functions dependency injection:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddSingleton<IMessageSerializerSettingsFactory, CustomMessageSerializer>();
    }
}

public class CustomMessageSerializer : IMessageSerializerSettingsFactory
{
    public JsonSerializerSettings CreateJsonSerializerSettings()
    {
        return new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
    }
}

Now if you have classes like these:

public abstract class Thing
{
    public abstract string GetMessage();
}

public class Foo : Thing
{
    public override string GetMessage()
    {
        return "I'm a Foo";
    }
}

public class Bar : Thing
{
    public override string GetMessage()
    {
        return "I'm a Bar";
    }
}

And you have orchestration and activity functions like this:

[FunctionName(nameof(Orchestrator))]
public static async Task<List<string>> Orchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add((await context.CallActivityAsync<Thing>(nameof(GetThing), true)).GetMessage());
    outputs.Add((await context.CallActivityAsync<Thing>(nameof(GetThing), false)).GetMessage());

    // [ "I'm a Foo", "I'm a Bar" ]
    return outputs;
}

[FunctionName(nameof(GetThing))]
public static Thing GetThing([ActivityTrigger] bool isFoo, ILogger log)
    => isFoo ? (Thing)new Foo() : (Thing)new Bar();

The above custom serializer applies to everything serialized by the Durable Functions extension. You can create a more complicated serializer if you want more control.




回答2:


While you may not be able to return a polymorphic result from an Activity, have you considered returning a serialized value that can be deserialized by the Orchestrator and handled accordingly. It's not ideal, but would give you the ability to accomplish the same task.




回答3:


Sure, adding serialization code before and after call would work, but sub optimal. The activity function signature would lose its type specificity. Workable, but not very elegant.



来源:https://stackoverflow.com/questions/60231879/using-durable-functions-how-to-return-multiple-values-from-an-activity-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!