Publikacja i subskrypcja zdarzeń (przykład), część VII

Dziś o kolejnym, moim zdaniem jednym z najważniejszych elementów programowania rozproszonego, a mianowicie o zdarzeniach. Jak w każdej analogicznej technologii, mamy zaimplementowany wzorzec obserwator. Każdy węzeł może nasłuchiwać konkretnej wiadomości i jak tylko zostanie ona opublikowana, wszyscy subskrybenci zostaną poinformowani.

Zacznijmy od przykładu. W poprzednich wpisach stworzyliśmy Example.API oraz klienta. Dzisiaj rozszerzymy solucję o dwa nowe projekty: Subscriber1 oraz Subscriber2. Skorzystamy z wiadomości AddPerson oraz dodamy pierwsze zdarzenie PersonAdded:

public class PersonAdded : IEvent
{
   public Guid PersonId { get; set; }
}
public class AddPerson:IMessage
{
   public Guid PersonId { get; set; }
   public string FirstName { get; set; }        
   public string LastName { get; set; }
}

Zamiast IMessage, implementujemy IEvent. To właśnie te zdarzenie będziemy publikować.  Następnie modyfikujemy AddPersonHandler z Example.API:

class AddPersonHandler : IHandleMessages<AddPerson>
{
   private readonly IBus _bus;

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

   public void Handle(AddPerson message)
   {
       Console.WriteLine("Adding person. {0} {1}",message.FirstName,message.LastName);
       _bus.Publish(new PersonAdded(){PersonId = message.PersonId});
   }
}

Jak widać publikacja zdarzeń jest bardzo prosta. Kolejny etap to implementacja subskrybentów. Musimy stworzyć dwa nowe projekty oraz standardowo zainstalować nServiceBus, zainicjalizować EndPointCofig. Niczym to się nie różni od Example.API więc nie będę tego powtarzał. W pliku konfiguracyjnym jednak, musimy określić jakie wiadomości będą nasłuchiwane. Skorzystamy z konfiguracji klienta i powinno to wyglądać następująco:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
    <section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />
  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="Example.Contracts" Endpoint="Example.API@localhost" />
    </MessageEndpointMappings>
  </UnicastBusConfig>
</configuration>

Obsługa zdarzeń niczym nie różni się od obsługi innych wiadomości zatem handler wygląda tak:

public class AddPersonEventHandler:IHandleMessages<PersonAdded>
{
   public void Handle(PersonAdded message)
   {                        
       Console.WriteLine("Subscriber 1. Person added: {0}",message.PersonId);
   }
}

Oczywiście analogicznie sytuacja wygląda dla innych subskrybentów.  Możliwa jest również ręczna subskrypcja za pomocą:

Bus.Subscribe<PersonAdded>();    
Bus.Unsubscribe<PersonAdded>();

Jeśli chcemy zablokować autosubskrypcję to:

configuration.DisableFeature<AutoSubscribe>();

W praktyce jednak wygodniej jest korzystać z pliku konfiguracyjnego + autosubskrypcji, jak to zostało pokazane wcześniej.

Na początek taki prosty przykład wystarczy. W przyszłym wpisie, pokażę jak to działa od strony wewnętrznej bo oczywiście nie jest to zwykłe zdarzenie rozproszone…

Leave a Reply

Your email address will not be published.