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
...)
我有一个场景,我正在 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
...)