2

场景:我用 10 个步骤构建了一个 saga。它正在更新各种系统,整个传奇可能需要几分钟才能完成。

传奇从另一个系统的数据开始,用户在其中输入客户的信息。

我无法看到用户何时在他们的系统中输入数据,但我每 x 分钟读取一次系统更改的数据。

我的问题是,每当我使用客户数据开始 saga 时,我需要确保同一客户的前一个 saga 已经完成。如果用户在输入数据上花费了 10 分钟,系统可能会针对同一个客户启动 5 个流程,并且流程可能会超过之前的流程,从而导致数据混乱。

有谁知道我该如何解决这个问题?

提前致谢。

奥莱

4

2 回答 2

0

如果不更改 saga 以及客户端系统正在发送的消息,您将无法解决此问题。

您的问题是 saga 可能配置为在收到某种消息类型时启动,每次用户对客户进行更改时,客户端应用程序都会生成该消息类型。

让我们将此消息称为:

public class ClientTypedSomethingAboutCustomer 
{
    int CustomerId {get;set;}
    ...
}

您的传奇将设置如下:

public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
{
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<ClientTypedSomethingAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);
        ...
    }
    ...
}

这会导致初始化 saga 并在 IContainSagaData 实现中设置客户 ID 值,用于接收到的每条客户端消息。

要解决更多消息初始化新 saga 的问题,您可以创建另一种消息类型,以区分某人何时开始键入有关客户的内容,然后键入有关该客户的其他内容。

就像是:

public class ClientTypedSomethingElseAboutCustomer 
{
    int CustomerId {get;set;}
    ...
}

那么你的传奇会是这样的:

public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
    ,IHandleMessages<ClientTypedSomethingElseAboutCustomer>
{
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<ClientTypedSomethingAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);

        ConfigureMapping<ClientTypedSomethingElseAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);
    }
    ...
}

这将确保有关客户的所有消息都将路由到单个 saga 实例。

通过在单线程模式下运行 NServiceBus 可以实现近似的排队行为。这可能会限制为客户创建并发 saga,但我不想依赖这个。

于 2016-01-04T17:01:59.643 回答
0

@janpieter_z 和 @tom-redfern 都是正确的:确保您可以将 saga 映射到某种客户 ID。

您还可以实现复杂的 saga 查找逻辑来找到正确的 saga,对应于传入的消息。

此外,如果多条消息未按正确顺序到达,则可以将它们设置为“IAmStartedByMessages”。

最后,谁在向您的传奇发送消息?saga 不应该负责发送请求以收集数据吗?也许每 10 秒通过超时或其他方式,直到几分钟内没有收到任何内容,或者处理程序回复了不同的消息?

于 2016-01-05T07:59:19.477 回答