0

I have a nservice bus project which which i will call connector. My connector receives variouis kinds of messages for example ClientChangeMessage, ClientContactChangeMessage. My connector has not implemented saga so i have handler for each message so for ClientChangeMessage I have ClientChangeMessageHandler which gets fired when connector receives ClientChangeMessage and a ClientContactChangeMessageHandler when i receive a ClientContactChangeMessage.

Now while looking at the sagas implementation i found myself writing the following code (If the Client contact message comes before the ClientChange message i.e the client does not exist in the database):

public class ClientContactChangeMessageHandler : ClientMessageHandler, 
    IHandleMessages<ClientContactChangeMessage>, 
    IAmStartedByMessages<ClientContactChangeMessage>, 
    IHandleMessages<ClientChangeMessage>
{
    [SetterProperty]
    public IClientContactChangeDb ClientContactChangeDb{get;set;}

    [SetterProperty]
    public IBusRefTranslator BusRefTranslator{get;set;}

    static ClientContactChangeMessageHandler()
    {
        Logger = LogManager.GetLogger(typeof (ClientContactChangeMessageHandler));
    }

    static ILog Logger;

    public void Handle(ClientContactChangeMessage message)
    {
        //Some handling logic
    }

    public void Handle(ClientChangeMessage message)
    {
        throw new NotImplementedException();
    }

    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<ClientContactChangeMessage>(s => s.Id, m => m.Id);
        ConfigureMapping<ClientChangeMessage>(s => s.Id, m => m.Id);
        // Notice that we have no mappings for the OrderAuthorizationResponseMessage message. This is not needed since the HR
        // endpoint will do a Bus.Reply and NServiceBus will then automatically correlate the reply back to
        // the originating saga
    }
}


public class ClientMessageHandler : BaseMessageHandler
{
}

public class BaseMessageHandler : Saga<MySagaData>
{
}

public class MySagaData : IContainSagaData
{
    public Guid Id { get; set; }
    public string Originator { get; set; }
    public string OriginalMessageId { get; set; }
}

As can be seen from the example I now have to implement the handle for the CLientChangeMessage as well , now i have already defined a handler for my ClientChangeMessage ,do i have to handle it again over here because if further on in time the ClientChangeMessage does come i would expect it to be caught and processed by the ClientChangeMessageHandler nad not by this one.

I would like to store a message if and only if i don't find the local reference for the Client in my database . Looking at the examples for saga on the web i dont't see any particular place or condition where this would be handled. I am hoping i would be storing the message inside the ClientContactChange handle method.

Any help would be much appreciated,

Thanks

UPDATE:

It would seem that i did not understand properly how to implement NService Bus Saga. The mistake which i made here according to me was that I considered A Client Contact change to be a single entity i.e independent of the Client Change message. So therefore i think i ma wrong in implementing the Saga just for client contact change . Here is how I had to change my code:

 public class ClientSaga : Saga<ClientSagaState>, 
        IAmStartedByMessages<ClientChangeMessage>, 
        IAmStartedByMessages<ClientContactChangeMessage>, 
        IHandleTimeout<ClientSagaState>
    {
        [SetterProperty]
        public IClientContactChangeDb ClientContactChangeDb{get;set;}

        [SetterProperty]
        public IBusRefTranslator BusRefTranslator{get;set;}



        public void Handle(ClientContactChangeMessage message)
        {
            //Some handling logic
            //Check if client is not in database then store the state
            this.ClientContactChange=message;
            //if client is in the data base then 
            MarkAsComplete();
        }

        public void Handle(ClientChangeMessage message)
        {
            //Update or create the client depending on the situation
            //check for dependencies
            if(this.ClientContactChange !=null)
            {
                 //Handle the contact change
            }
        }

        public override void ConfigureHowToFindSaga()
        {
            ConfigureMapping<ClientContactChangeMessage>(s => s.ClientRef, m => m.ClientRef);
            ConfigureMapping<ClientChangeMessage>(s => s.ClienttnRef, m => m.Id);
            // Notice that we have no mappings for the OrderAuthorizationResponseMessage message. This is not needed since the HR
            // endpoint will do a Bus.Reply and NServiceBus will then automatically correlate the reply back to
            // the originating saga
        }
    }


    public class ClientSagaState: IContainSagaData
    {
        //i dont need these three fields
        public Guid Id { get; set; }
        public string Originator { get; set; }
        public string OriginalMessageId { get; set; }

       // the fields which i needed
       public Guid ClientRef {gee; set;}
       public ClientChangeMessage ClientChange {get;set;}
       public ClientContactChange ClientContactChange {get;set;}

    }
4

1 回答 1

1

由于两个处理程序都处理相同的消息类型,因此都将被调用。如果您愿意,可以使用 ISpecifyMessageHandlerOrdering 指定调用它们的顺序。此外,您可以根据可能解决次要问题的条件短路此链。

如果这不起作用,您可能需要考虑对消息进行版本控制,以优雅的方式支持这两种情况。

于 2013-08-01T19:22:07.373 回答