简体   繁体   English

Nservice总线Sagas实现

[英]Nservice bus sagas implemetation

I have a nservice bus project which which i will call connector. 我有一个nservice总线项目,我将其称为连接器。 My connector receives variouis kinds of messages for example ClientChangeMessage, ClientContactChangeMessage. 我的连接器接收各种消息,例如ClientChangeMes​​sage,ClientContactChangeMes​​sage。 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. 我的连接器尚未实现传奇,因此我为每个消息都配备了处理程序,因此对于ClientChangeMes​​sage,我具有ClientChangeMes​​sageHandler,当连接器接收到ClientChangeMes​​sage时,将触发该事件;当我接收到ClientContactChangeMes​​sage时,将触发一个ClientContactChangeMes​​sageHandler。

Now while looking at the sagas implementation i found myself writing the following code (If the Client contact message comes before the ClientChange message ie the client does not exist in the database): 现在,在查看sagas实现时,我发现自己在编写以下代码(如果Client contact消息在ClientChange消息之前,即该客户端在数据库中不存在):

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. 从示例中可以看出,我现在还必须实现CLientChangeMes​​sage的句柄,现在我已经为我的ClientChangeMes​​sage定义了一个处理程序,我是否必须在这里再次处理它,因为如果能及时处理ClientChangeMes​​sage的话我希望它可以被ClientChangeMes​​sageHandler捕获和处理,而不是不被此处理。

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. 我希望我将消息存储在ClientContactChange处理方法中。

Any help would be much appreciated, 任何帮助将非常感激,

Thanks 谢谢

UPDATE: 更新:

It would seem that i did not understand properly how to implement NService Bus Saga. 看来我不太了解如何实现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 ie independent of the Client Change message. 我根据我在这里犯的错误是,我认为客户联系人更改是单个实体,即独立于客户更改消息。 So therefore i think i ma wrong in implementing the Saga just for client contact change . 因此,因此我认为仅出于客户联系变更而实施Saga是错误的。 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;}

    }

Since both handlers handle the same message type, both will be called. 由于两个处理程序都处理相同的消息类型,因此两者都将被调用。 If you like you could specify the order in which they get called using ISpecifyMessageHandlerOrdering. 如果愿意,可以使用ISpecifyMessageHandlerOrdering指定调用它们的顺序。 Furthermore, you can short circuit this chain based on a condition which may solve the secondary issue. 此外,您可以根据可能解决第二个问题的条件来短路此链。

If that does not work, you may want to consider versioning the message to support both scenarios in a graceful way. 如果这不起作用,则您可能需要考虑对消息进行版本控制以以一种优美的方式支持这两种方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM