2014-09-05 3 views
1

Я работаю с саг в ребус и из моего опыта с NServiceBus вы могли бы ответить на создателю Саги, чтобы дать обновления, что-то вроде этого:Ребус эквивалентно NServiceBus Saga ReplyToOriginator

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; } 
} 
+0

У вас есть какой-либо другой код ? Не могли бы вы дать краткий обзор технологии, которую вы описываете? Я занимаюсь программированием в течение последних 18 лет, я понятия не имею, о чем вы говорите. Если это что-то новое, было бы неплохо, если бы вы могли связать его с существующими технологиями, которые в настоящее время доступны. – Neolisk

+1

Я добавил пример, для технологии см. Теги (ReBus, C#) –

ответ

3

Нет, к сожалению, нет ответа ORIGINATOR функции в сагах Ребуса на данный момент. Вы можете легко сделать это, хотя, за счет сохранения конечной составителя, когда ваша сага создается как это (во всех Handle методов сообщений, которые могут инициировать сагу):

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

, а затем, когда вы хотите, чтобы ответить назад к возбудитель:

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

Я часто думал о добавлении это ребус, хотя, либо в качестве дополнительного поля на ISagaData, или в качестве дополнительного интерфейса ISagaDataWithOriginator, что вы могли бы, возможно применить к данным саг, но я никогда был нужен (достаточно) сам.

+0

Спасибо, человек, я очень благодарен вам за ответ. –

1

Если каждый отправитель является отдельной (виртуальной) машиной, как и в моей реализации, вы могли бы получить гарантированный ответ отправителя, используя их машину уникального идентификатора или MAC-адрес в имени очереди ответа, как это:

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

Если каждый отправитель имеет уникальный идентификатор очереди, потребитель может ответить автору, просто используя Bus.Reply.

Уникальный идентификатор машины может быть определена с помощью 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; 
     } 
    } 
    } 
} 

Или с помощью МАС-адрес машины (наш резервный код):

if (string.IsNullOrEmpty(uuid)) 
{ 
    uuid = NetworkInterface.GetAllNetworkInterfaces() 
    .Where(ni => ni.OperationalStatus == OperationalStatus.Up) 
    .FirstOrDefault() 
    .GetPhysicalAddress().ToString(); 
} 
Смежные вопросы