I think it’s not possible. Callbacks are for simple Request/Response scenario where by design client (in your sample WCF) making Request expects the Response so it’s blocked until receive Response from the receiver. Saga is for more complex scenarios with non-blocking operations so by design client (in your sample WCF) cannot expect the Response or at least immediate response. If you don’t have to have immediate response on the client side you could try to use:
but your scenario sounds like standard collecting data from many places so why not retrieve and aggregate them directly from WCF service receives HTTP request?
Thanks Michal. That is very useful information.
I agree with your suggestion about calling and aggregating directly from the WCF service.
However, if (because of other considerations) we did need go down the saga route, do you think there would be any issues with using ReplyToOriginator and passing in the original WCF
callback Replyto address.
(Obviously a saga will be slower than orchestrating directly from the WCF service)
You don’t have to put address calling ReplyToOriginator. NServiceBus will reply automatically to the Endpoint who initialized the Saga instance. In your scenario it will be Endpoint (E1) hosting in WCF. I think you don’t even have to use callbacks:
Correct, ReplyToOriginator will make sure to populate the NServiceBus.CorrelationId header with the message ID that started the saga to make sure that registered callbacks trigger correctly
Thanks. Do I understand correctly, to handle the ReplyToOriginator saga response, the WCF service would need to declare a message handler - rather than use the messageSession.Request<MyResponse>() signature?
It IS possible, a callback is just a blocking request/response mechanism.
You can invoke a saga which does any kind of work. As long as it uses ReplyToOriginator the callback mechanism can correlate the response to the request.
Sagas that aggregate using scatter gather is very common and often just exists a few hundred milliseconds.
You do not need to use a handler. Handlers to process a response should be used for actual asynchronous processes. Meaning, there is not a user in a user-interface ‘waiting’ (blocked) for a response.
There are some concerns:
Not receiving a response in a timely fashion does not mean the operation was not succesful, just that it is delayed.
Asynchronous processes are better of using a task based user interface of which the user can be updated via for example SignalR.
I’m more concerned about why the callback saga construct is needed. If this is just a complex query you are probably better to just query the storage directly from the UI. It often is an anti-pattern to use request/response messaging to do querying.
that’s why I receive No handlers could be found for message type: ObjectResponseMessage in Samples.Callbacks.Sender Endpoint so that’s why I thought the scenario described at the beginning of this Topic is not possible. After fix request to:
and if you want to use callbacks you don’t need to declare separate message Handler for the Response from Saga. Otherwise yes you need.
It’s interesting Topic so let’s try to analyze possibilities discussed so far from the failure point of view:
blocking query from WCF (or UI directly) - no NServiceBus
blocking Request from WCF using Callbacks
no-blocking Send from WCF using standard Send/Replay (Request/Response)
At the first point (preferred) there is expectation of immediate Exception when something goes wrong.
At the third point there isn’t this kind of expectation. When something goes wrong (no transient error) the message will be moved to the error queue but the WCF won’t be wait for the response.
At the second point there could be a situation when message will be in the error queue but WCF will be blocked and wait for the response.
@andreasohlund, @ramonsmits is there something like default callback timeout when calling endpointInstance.Request<...>(...) apart from Cancellation or restarting the process?
@Sean-R if you have to use Callbacks you could take to the consideration the failure scenario.
@ramonsmits Thanks for your advice. I agree, it feels like that would be simpler and quicker to call out directly from the WCF service. In our particular scenario, there are other processes that will be using the same saga workflow. I think this is one of the reasons for also wanting to push the web service data through the Saga.
Unfortunately, SignalR is not an option in this case as its an external legacy web service with many clients.
no-blocking Send from WCF using standard Send/Replay (Request/Response)
Interesting. Would option 3 require a MessageHandler hosted in the Web Process? With this approach would it be possible to respond to the original Http request?
YES the MessageHandler for response is required otherwise you will receive the similar behavior like my example above.
Unfortunately NO after sending the message the WCF Request is closing. As @ramonsmits mentioned it’s possible to use SignalR for updating the user but like you said this is not an option for your scenario.