处理多个事件的状态转换 [英] Handling transition to state for multiple events

查看:118
本文介绍了处理多个事件的状态转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个MassTransitStateMachine,它可以协调涉及创建多个事件的过程.

I have a MassTransitStateMachine that orchestrates a process which involves creating multiple events.

所有事件一旦完成,我希望状态转换为清理"阶段.

Once all of the events are done, I want the state to transition to a 'clean up' phase.

以下是相关的状态声明和过滤器功能:

Here is the relevant state declaration and filter function:

        During(ImportingData,
            When(DataImported)
                // When we get a data imported event, mark this source as done. 
                .Then(MarkImportCompletedForLocation),

            When(DataImported, IsAllDataImported)
                // Once all are done, we can transition to cleaning up...
                .Then(CleanUpSources)
                .TransitionTo(CleaningUp)
        );


    ...snip...


    private static bool IsAllDataImported(EventContext<DataImportSagaState, DataImportMappingCompletedEvent> ctx)
    {
        return ctx.Instance.Locations.Values.All(x => x);
    }

因此,当状态为 ImportingData 时,我希望收到多个 DataImported 事件.每个事件都将其位置标记为已完成,以便 IsAllDataImported 方法可以确定是否应过渡到下一个状态.

So while the state is ImportingData, I expect to receive multiple DataImported events. Each event marks its location as done so that that IsAllDataImported method can determine if we should transition to the next state.

但是,如果最后两个 DataImported 事件同时到达,则转换为 CleaningUp 阶段的处理程序将触发两次,而我最终尝试执行清理两次.

However, if the last two DataImported events arrive at the same time, the handler for transitioning to the CleaningUp phase fires twice, and I end up trying to perform the clean up twice.

可以用自己的代码解决这个问题,但是我希望状态机能够解决这个问题.我是在做错什么,还是我自己需要解决争用?

I could solve this in my own code, but I was expecting the state machine to manage this. Am I doing something wrong, or do I just need to handle the contention myself?

推荐答案

Chris提出的解决方案在我的情况下不起作用,因为我遇到了多个相同类型的事件.仅在所有这些事件都到达时,我才需要过渡. CompositeEvent 构造不适用于此用例.

The solution proposed by Chris won't work in my situation because I have multiple events of the same type arriving. I need to transition only when all of those events have arrived. The CompositeEvent construct doesn't work for this use case.

我对此的解决方案是在 MarkImportCompletedForLocation 方法期间引发一个新的 AllDataImported 事件.现在,此方法可以确定是否以线程安全的方式完成了所有子导入.

My solution to this was to raise a new AllDataImported event during the MarkImportCompletedForLocation method. This method now handles determining whether all sub-imports are complete in a thread safe way.

所以我的状态机定义是:

So my state machine definition is:

            During(ImportingData,
            When(DataImported)
                // When we get a data imported event, mark the URI in the locations list as done. 
                .Then(MarkImportCompletedForLocation),

            When(AllDataImported)
                // Once all are done, we can transition to cleaning up...
                .TransitionTo(CleaningUp)
                .Then(CleanUpSources)
        );

不再需要 IsAllDataImported 方法作为过滤器.

The IsAllDataImported method is no longer needed as a filter.

传奇状态具有Locations属性:

The saga state has a Locations property:

public Dictionary<Uri, bool> Locations { get; set; }

MarkImportCompletedForLocation方法的定义如下:

And the MarkImportCompletedForLocation method is defined as follows:

    private void MarkImportCompletedForLocation(BehaviorContext<DataImportSagaState, DataImportedEvent> ctx)
    {
        lock (ctx.Instance.Locations)
        {
            ctx.Instance.Locations[ctx.Data.ImportSource] = true;
            if (ctx.Instance.Locations.Values.All(x => x))
            {
                var allDataImported = new AllDataImportedEvent {CorrelationId = ctx.Instance.CorrelationId};
                this.CreateEventLift(AllDataImported).Raise(ctx.Instance, allDataImported);
            }
        }
    }

(我已经写了这篇文章,以便了解一般流程的工作方式;我认识到MarkImportCompletedForLocation方法需要通过验证字典中是否存在键来提高防御性.)

(I've just written this so that I understand how the general flow will work; I recognise that the MarkImportCompletedForLocation method needs to be more defensive by verifying that keys exist in the dictionary.)

这篇关于处理多个事件的状态转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆