ReBus equivalent to NServiceBus Saga ReplyToOriginator

本文关键字:Saga ReplyToOriginator NServiceBus to equivalent ReBus | 更新日期: 2023-09-27 18:20:46

我正在ReBus中与Sagas合作,根据我在NServiceBus的经验,您可以回复Saga的原始创建者以提供更新,类似于以下内容:

 Saga<>.ReplyToOriginator

我看不出ReBus有同等的方法可以做到这一点。有没有办法做到这一点,如果没有,我可以使用什么样的好模式(除了发起人轮询)来实现同样的效果?一个例子是试图创建一个客户,而客户希望在尝试更改其地址之前知道它是何时创建的。

下面是一个我很快拼凑起来的客户场景的琐碎例子:

public class CreateCustomerSaga : Saga<CreateCustomerData>,
    IAmInitiatedBy<CreateCustomerCommand>,
    IHandleMessages<CustomerUniqunessCheckResult>
{
    private readonly IBus _bus;
    private readonly ICustomerResourceAccess _customerResourceAccess;
    public CreateCustomerSaga(IBus bus, ICustomerResourceAccess customerResourceAccess)
    {
        _bus = bus;
        _customerResourceAccess = customerResourceAccess;
    }
    public override void ConfigureHowToFindSaga()
    {
        Incoming<CustomerUniqunessCheckResult>(x => x.IsCustomerUnique).CorrelatesWith(y => y.CustomerId);
    }
    public void Handle(CreateCustomerCommand message)
    {
        Data.CustomerId = message.CustomerId;
        Data.CustomerName = message.CustomerName;
        _bus.Send(new CheckCustomerUniquenessCommand(message.CustomerId));
    }
    public void Handle(CustomerUniqunessCheckResult message)
    {
        if (message.IsCustomerUnique)
        {
            _customerResourceAccess.CreateCustomer(Data.CustomerId, Data.CustomerName);
            // This is what seems to be missing from ReBus to reply to the original sender
            _bus.?(new CustomerCreatedEvent(Data.CustomerId));
        }
        else
        {
            // This is what seems to be missing from ReBus to reply to the original sender
            _bus.?(new CustomerAlreadExistsEvent(Data.CustomerId));
        }
    }
}
public class CustomerCreatedEvent
{
    public Guid CustomerId { get; set; }
    public CustomerCreatedEvent(Guid customerId)
    {
        CustomerId = customerId;
    }
}
public class CustomerAlreadExistsEvent
{
    public Guid CustomerId { get; set; }
    public CustomerAlreadExistsEvent(Guid customerId)
    {
        CustomerId = customerId;
    }
}
public class CustomerUniqunessCheckResult
{
    public bool IsCustomerUnique { get; set; }
}
public class CheckCustomerUniquenessCommand
{
    public CheckCustomerUniquenessCommand(Guid customerId)
    { }
}
public interface ICustomerResourceAccess
{
    void CreateCustomer(Guid customerId, string customerName);
}
public class CreateCustomerCommand
{
    public Guid CustomerId { get; set; }
    public string CustomerName { get; set; }
}
public class CreateCustomerData : ISagaData
{
    public CreateCustomerData()
    {
        Id = Guid.NewGuid();
    }
    public Guid CustomerId { get; set; }
    public string CustomerName { get; set; }
    public Guid Id { get; set; }
    public int Revision { get; set; }
}

ReBus equivalent to NServiceBus Saga ReplyToOriginator

没有,不幸的是,Rebus的sagas中目前没有对发起人函数的回复。不过,您可以很容易地做到这一点,当您的传奇故事被创建时,通过存储发起者的端点(在所有可以启动传奇故事的消息的Handle方法中):

if (IsNew) {
    Data.Originator = MessageContext.GetCurrent().ReturnAddress;
}

然后当你想回复发起者时:

bus.Advanced.Routing.Send(Data.Originator, new HelloThereMyFriend());

不过,我经常考虑将其添加到Rebus中,要么作为ISagaData上的一个额外字段,要么作为一个额外的接口ISagaDataWithOriginator,您可以选择将其应用于您的传奇数据,但我自己从未有过(足够的)需求。

如果每个发送者都是一个单独的(虚拟)机器,就像在我的实现中一样,你可以通过在回复队列名称中使用他们的机器唯一ID或MAC地址来获得对发起者的保证回复,如下所示:

Bus = Configure.With(adapter)
               .Transport(t => t.UseSqlServer(DbConfiguration.DatabaseConnectionString,
                                              sInstanceId, sInstanceId + ".Error")
               .EnsureTableIsCreated())
               ...

如果每个发起方都有一个唯一的队列ID,那么消费者只需使用Bus.reply.就可以回复发起方

唯一的机器id可以使用System.Management:确定

string uuid = string.Empty;
ManagementClass mc = new System.Management.ManagementClass("Win32_ComputerSystemProduct");
if (mc != null)
{
  ManagementObjectCollection moc = mc.GetInstances();
  if (moc != null)
  {
    foreach (ManagementObject mo in moc)
    {
      PropertyData pd = mo.Properties["UUID"];
      if (pd != null)
      {
        uuid = (string)pd.Value;
        break;
      }
    }
  }
}

或者使用机器的MAC地址(我们的后备代码):

if (string.IsNullOrEmpty(uuid))
{
  uuid = NetworkInterface.GetAllNetworkInterfaces()
  .Where(ni => ni.OperationalStatus == OperationalStatus.Up)
  .FirstOrDefault()
  .GetPhysicalAddress().ToString();
}