Bus.SendLocal() vs. Bus.Publish()

1,711 views
Skip to first unread message

Christian Grønbæk Jørgensen

unread,
Jun 3, 2014, 2:28:07 PM6/3/14
to particula...@googlegroups.com
Hi

In our solution we are exposing an WCF endpoint, that allows systems to publish events via NServiceBus. 

Our service could look something like this:

        public void CustomerCreated(CustomerCreatedNotification notification)
       
{
           
try
           
{
               
this.Bus.Publish(notification);
           
}
           
catch (Exception ex)
           
{
               
throw new FaultException(ex.Message);
           
}
       
}


       
public void CustomerDeleted(CustomerDeletedNotification notification)
       
{
           
try
           
{
               
this.Bus.Publish(notification);
           
}
           
catch (Exception ex)
           
{
               
throw new FaultException(ex.Message);
           
}
       
}

This will work. However should an exception happen in the Bus.Publish(), i would require that the client (who is trying to publish data using the service) is capable of handling this and store the message internally.

Another approach could be to have the service do this:

        public void PowerSupplyContractCreated(PowerSupplyContractCreatedNotification notification)
       
{
           
try
           
{
               
this.Bus.SendLocal(notification);
           
}
           
catch (Exception ex)
           
{
               
throw new FaultException(ex.Message);
           
}
       
}

And then have a MessageHandler do the Bus.Publish():

    public class PowerSupplyContractCreatedPublisher : IHandleMessages<PowerSupplyContractCreatedNotification>
    {

        public void Handle(PowerSupplyContractCreatedNotification message)
        {
            this.Bus.Publish(message);
        }
    }

In this implementation the service would immediately stores the message in the queue, when doing the Bus.SendLocal() and send an response back to the client. Then the MessageHandler will eventually process the message and do the actual publishing.

Given our scenario, what would be the best approach? And what are the pro/cons of using Bus.SendLocal() versus Bus.Publish()?

Best regards
Christian

Joe Ratzloff

unread,
Jun 6, 2014, 12:13:45 AM6/6/14
to particula...@googlegroups.com
Christian,
From the error handling standpoint, AFIK, there isn't a difference.   When you publish a message, the bus will send it to all the subscribers the endpoint is aware of and has persisted for that type of message.    When you do a Bus.SendLocal, I believe the message is dropped into the inbound queue of the endpoint your code is currently running in.   I have seen it used mostly in Saga's where the provide a way to segment work and have one handler in a saga send a durable message back to itself....

You are correct in your observation about the brittle nature of your client to server communication.  it is synchronous and leaves the client with the burden of dealing with compensation.   A few ideas to deal with it would be to,:
1: If possible, get your client on the bus via self hosting and use the bus to send the message to the back end using full duplex communication (See the Full duplex/request response sample).  

2.) Do some work on your server side to make the invocation idempotent.   If the client gets and error as you suggest ( or worse, no response at all!!), it can invoke again but the server would detect it.  This can be tricky since transactions are involved.

However, I've seen what you are doing done before.   The act of doing a Bus.Send/Publish/etc is not an error prone endeavor as is IMO much better than invoking a downstream web service.  As you've noticed, the queue you are publishing to is transactional so any error will roll it back.. but in the case of self hosting in WCF,  there is no inbound queue to roll back to.

A pattern I have seen before in your scenario is to use the WCF service on the server to generate a unique ID (GUID)? and return it to the caller synchronously and then do a bus.Send to another endpoint.  Now, unless MSMQ is down or it's queues are full, it is quite reliable.  But of course, you must plan for the worst case so as the message reaches the backend, it should be de-duplicated as necessary in the case there was an error and the client did retry.  Once deduplicated and confirmed, then raise the event for the rest of the architecture to see from this backend endpoint.....

In financial transactions for example, we would look out for duplicates using some naturally occurring rules on business logic or ids.

I hope this gives you some clarification and a few ideas....
Regards,
Joe.

Alexey Zimarev

unread,
Jun 7, 2014, 2:01:20 PM6/7/14
to particula...@googlegroups.com

Fundamentally, Send is to send a command and Publish is to publish an event.

 

When you send a command with Send or SendLocal and there is no handler, it is considered as an error although the exception is only logged as informational. Publishing events with no matching handlers considered as normal.

--
You received this message because you are subscribed to the Google Groups "Particular Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to particularsoftw...@googlegroups.com.
To post to this group, send email to particula...@googlegroups.com.
Visit this group at http://groups.google.com/group/particularsoftware.
To view this discussion on the web visit https://groups.google.com/d/msgid/particularsoftware/c932c459-da1b-4711-9b37-edc1ecb68e05%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages