Rebus:多个传奇处理相同的消息 - 或 - 传奇中 request/reply 的最佳实践

Rebus: Multiple sagas handling same message -OR- best practice for request/reply in saga

我有一个场景,我正在 Saga 中处理一条消息,可能需要更多信息,因此发送了一条我希望得到回复的请求消息。

问题是回复没有当前 saga 独有的信息 - 它有一个我想使用的 ID,但多个 sagas 可能同时请求这个 ID,因此 Rebus 不允许它(例外: Correlation property 'Bla' has value '86' in existing saga data with ID 2d12a863-12ed-4632-82d8-290e041c4eed).

如果无法让多个 saga 处理一条消息,我的替代方案是能够匹配请求 saga 的回复。据我所知,曾经有过对此的支持,但在以后的版本中被删除了。

我已经尝试使用 rbs2-corr-id header 来实现它,并且它在我的测试中有效,但感觉就像一个 hack。

有更好的方法吗?不修改消息?

我考虑过使用另一个传奇作为一种代理,方法是关联可能共享的 ID 并拥有原始传奇的相关 ID 列表。但是我担心可能存在并发问题导致原始传奇等待代理传奇。

下面的代码应该能说明问题:

public class Message
{
    public Guid Id { get; set; }
    public int OtherId { get; set; }
}

public class Request
{
    public int OtherId { get; set; }
}

public class Response
{
    public int OtherId { get; set; }
    public string MissingInfo { get; set; }
}

public class SagaData : ISagaData
{
    public Guid Id { get; set; }
    public int Revision { get; set; }

    public Guid MessageId { get; set; }
    public int OtherId { get; set; }
}

public class MySaga : Saga<SagaData>, IAmInitiatedBy<Message>, IHandleMessages<Response>
{
    IBus _bus;

    public MySaga(IBus bus)
    {
        _bus = bus;
    }

    public async Task Handle(Message message)
    {
        Data.OtherId = message.OtherId;

        // Send Request expecting someone to .Reply(new Response { OtherId = ,... })
        await _bus.Send(new Request { OtherId = message.OtherId });
    }

    public async Task Handle(Response message)
    {
        // Do something with message.MissingInfo
    }

    protected override void CorrelateMessages(ICorrelationConfig<SagaData> config)
    {
        config.Correlate((Message m) => m.Id, s => s.MessageId);

        // This works as long as only one saga has this ID
        config.Correlate((Response m) => m.OtherId, s => s.OtherId);
    }
}

I've tried implementing this using the rbs2-corr-id header, and it works in my tests, however it feels like a hack.

嗯...这是一个聪明的技巧。我认为这实际上是您可以做的最好的事情:利用请求的相关 ID 在您的控制之下这一事实,并且回复将携带相同的相关 ID。

如何将相关 ID 设置为您希望在收到回复时再次看到的 ID?

然后将您的回复与

之类的内容相关联
protected override void CorrelateMessages(ICorrelationConfig<InviteToTeamByEmail> config)
{
    config.CorrelateHeader<YourReply>(Headers.CorrelationId, d => d.Bla);
}

(假设关联 属性 的名称实际上是 Bla...)