Worker that uses Distributor and Callback - does not work

msmq
nservicebus

(George) #1

Could anyone provide working example of Worker that uses distributor and Callback ?
There is nothing about it on Callback Usage page. Just only about client Callbacks, but I need callback from Worker that uses distributor. Right now worker stops to communicate (send ready message) with distributor.


(Sean Farmar) #2

Hi George,
The callback feature is designed to work for Client to server scenario only.

Can you explain what is the issue you are trying to solve?

What version of NServiceBus are you using?


(Ramon Smits) #3

Hi George,

The behavior that probably is happening is that the worker isn’t receiving its response back and while that happens the worker is blocked. The response is received on the distributor but then forwarded to on one of the other workers. On that worker the callback wasn’t made and you would see something like the following error one of the workers logs:

2017-11-08 23:05:50.765 INFO NServiceBus.Unicast.Transport.TransportReceiver Failed to process message
System.InvalidOperationException: No handlers could be found for message type: MyResponse

As Sean already suggested, callback shouldn’t be used in this scenario.

Alternatively, you should just have a regular handler that processes that response message.

If you require to correlate between the request and the response then you could use a saga:

You can also use regular handlers for this but this is where sagas are really useful as a lot of plumbing has already been done for you.

Regards,
Ramon


(George) #4

Thank you for the responses.
Actually my question is based on issue with worker and distributor in case worker creates new EndpointConfiguration and starts new EndpointInstance and later uses this EndpointInstance to publish messages.
After a few messages are published worker looses connection with distributor and stops processing messages at all.
In this case I see these logs on worker side:
2017-09-22 22:30:00.007 INFO NServiceBus.ReadyMessageSender SKIPPED Ready message for message with id 25cb92b2-a2d8-47df-8452-7b221ef42048 because of sessionId mismatch. MessageSessionId bb5e4c9a-6b32-438f-817a-241f9e535bd6, WorkerSessionId f3686f5a-543f-4a25-bc36-0c4737c0462e

Maybe I need to create another topic about this issue?


(Ramon Smits) #5

Hi George,

Could you share why you require this construction? Why don’t you just do a context.Publish? I’m not sure why you require callbacks.

The message you are referring to is an INFO message and can safely be ignored. When a worker starts it enlists itself at the distributor. If you restart the worker 10x, then now the distributor has a lot of slots for that worker. This mechanism makes sure that ‘old’ worker slots which have a different session ID will not result in the worker getting too much work as it is not confirming messages back to the distributor.

The message flow is explained in the following documention:

Looking forward to your response about using callbacks within a handler.

Regards,
Ramon


(George) #6

I’m not sure why you require callbacks.

callbacks was just a hypothetical thoughts and probably we can skip it’s discussion

Could you share why you require this construction? Why don’t you just do a context.Publish?

Because inside worker I call some dll’s method (the deep of such invocations is unknown) which do publish (not directly but by using IoC) and I cannot pass context in to this method, so I create new EndpointInstance.
Let me explain it in a simple way:
I created IPublisher interface and implementation as some type of proxy around NServiceBus classes what helps to publish a message. So I can publish a message by calling
Publisher.Publish(message)
under the hood this method creates new EndpointConfiguration and starts new EndpointInstance.
further, I have dll that calls this Publish method inside it’s method:
public class OrderBuilder{
public DoOrder(order)
{
publisher.Publish(setSomethingMsg);
}
}
and inside NSB Handler I call
public Task Handle(OrderMessage OrderMessage, IMessageHandlerContext context)
{
OrderBuilder.DoOrder(OrderMessage.ToOrderObject())
}
and that’s it.
There is no way to pass IMessageHandlerContext into DoOrder and publisher.Publish.
This architecture works on our production environment for years.
But after we upgraded to NSB v6 we run into this issue.


(Ramon Smits) #7

Hi George,

Yes, you are right that with V6 you are required to pass the context around. It, unfortunately, is not as easy as using IBus directly for your current code base. Code that is invoking a Send or Publish now needs to know if they do this in the context of an incoming message or not but in most cases it probably would be within receiving a message.

If you do not use the context but IMessageSession then any sends or publishes done via this interface are not reliable and can cause duplicate sends in case of errors. I definitely advise not to invoke this indirectly within a message receive context.

We are currently aware that this behavior is causing some of our customers migration issues like you are currently experiencing. We are busy developing a solution for this but not yet released as it hasn’t been thoroughly tested yet. Could you please contact us via support@particular.net so that we can provide you with a beta version? Just mention my name (Ramon) in the message and refer to this post on our forum.

Regards,
Ramon


(Daniel Marbach) #8

Hi George

The component that @ramonsmits talked about is release for v6. The announcement can be found

Be aware the plugin requires .NET 4.6.1 to run

Regards
Daniel