使用持久函数,如何从活动函数返回多个值

时间:2020-02-14 18:40:10

标签: domain-driven-design azure-durable-functions

我是“领域驱动设计”的忠实拥护者和开发人员,并且一直试图将技术/体系结构映射到DDD领域。将微服务映射到有限的上下文提供了自然的结合。归根结底,我只想专注于业务逻辑并将其托管在正确的环境中。持久功能对我来说很有希望,因为如果需要的话,它需要解决跨微服务,Sagas或Process Manager的分布式事务问题。我已经使用NServicebus多年了,并且喜欢他们的Saga技术,但是想利用Durable Function业务流程来处理Saga逻辑。 我当前遇到的体系结构问题如下。我已将DDD应用程序服务映射到活动功能。因此,只需使用协调器点击正确的一组活动功能来运行其交易即可创建传奇。从概念上讲,建立回滚也是非常简单的,但是我遇到了实现问题。顺便说一句,每个活动功能都将委派给一个处理所有业务逻辑详细信息的库,然后将获取业务逻辑返回的事件列表,并将其返回给Orchestrator。据我研究,还没有办法从活动函数返回多态返回值。因此,如果我的业务逻辑生成了UpdateSucceeded或UpdateFailed事件,我该如何简单地将其从我的Activity函数返回给Orchestrator,以便Orchestrator通过调用不同的回滚Activity Function来采取纠正措施?

3 个答案:

答案 0 :(得分:4)

您可以使用持久功能2.1.0中新的自定义序列化程序支持来执行此操作。仍然需要记录下来,但是基本上可以使用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 };
    }
}

现在,如果您有类似的课程:

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";
    }
}

您具有如下的编排和活动功能:

[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();

上面的自定义序列化程序适用于所有通过Durable Functions扩展序列化的内容。如果需要更多控制,可以创建更复杂的序列化器。

答案 1 :(得分:0)

虽然您可能无法从Activity返回多态结果,但是您是否考虑过返回可以由Orchestrator进行反序列化并进行相应处理的序列化值。这不是理想的方法,但是会给您完成相同任务的能力。

答案 2 :(得分:0)

当然,在调用之前和之后添加序列化代码是可行的,但次优。活动功能签名将失去其类型特异性。可行,但不是很优雅。