views:

121

answers:

1

Hi,

Imagine the following setup: a Silverlight client tunnels a serialized command over the network using a WCF service which in turn deserializes the command and sends it using NServiceBus to a generic host which is responsible for processing the command. The WCF service has - upon sending the command - registered a callback to be invoked. The generic host validates the command and 'returns' an error code (either 0 == success or >0 == failure).

Note: The WCF service is modelled after the built-in WCF service. The difference is that this WCF service receives a 'universal command' (not an IMessage), deserializes it into a real command (which does implement IMessage), and consequently sends the deserialized command off to the bus.

When unexpected exceptions occur, the command gets (after a certain amount of retries) queued in an error queue. At this point, the initiating WCF service sits there idle, unaware of what just happened. At some later point, the Silverlight client will time out according to the WCF client proxy configuration.

Things which are fuzzy in my head:

  1. Does NServiceBus handle this scenario in any way? When does the timeout exception get thrown (if at all)? Or is this something exclusive to sagas?
  2. Presuming I use [OperationContract(AsyncPattern=true)], are there any WCF related timeout settings that will kill the service operation? Or will the EndXXX method be somehow called? Or will it sit there forever, leaking, waiting for something that will never come?

Ways to proceed:

  1. reuse existing timeout mechanisms, provided things don't leak.
  2. build my own timeout mechanism between the wcf service and nservicebus.
  3. notify the wcf service somehow when the command lands in the error queue.
  4. build my own async notifcation mechanism using full blown callback message handler in the WCF service layer.

Things I've done:

  1. run the example provided with NServiceBus.
  2. spiked the happy case.

Any guidance on how to proceed is welcome, be it blog post, mailing list entries, ...

Some motivations for picking my current approach

  • I'm trying to leverage some of the scalability advantages (using distributor in a later phase) of NServiceBus.
  • I don't want to host a gazillion WCF services (one for each command), that's why I cooked up a bus-like WCF service.
  • Even though this is somewhat request/response style, I'm mostly concerned with gracefully handling a command reply not coming through.
A: 

You can develop any sort of message type you desire, IMessage is simply a marker interface. If you inspect the WSDL file that the service mex endpoint provides, there is no reference to IMessage, therefore you can define any command you like in you service. That being the case you should be able to use the provided WCF host.

I was able to reproduce the issue you describe using the built-in WCF hosting option. When an exception is thrown, the entire transaction is rolled back and this includes the Bus.Return, and therefore the service never gets a response.

I found a hack around this that I could provide, but I recommend reconsidering how you are using the service. If you are truly looking to do some expensive operations in a separate process then I would recommend in your WCF endpoint that you do a Bus.Send to a different process altogether. This would ensure to your client that the command was successfully received and that work is in progress. From there it would be up to the server to complete the command(some up front validation would help ensure its success). If the command was not completed successfully this should be made known on another channel(some background polling from the client would do).

Adam Fyles
It's not an expensive operation - we might have to wait a while when the separate process is under load, we might not get an answer because of unexpected things that have happened, but we should be able to handle these situations gracefully.
Yves Reynhout
Do you need an immediate response? Can you show the appropriate result to the user and check back for status later? Much like this site, comments don't really commit right away. If you post a comment and refresh it disappears. Can you take the same approach?
Adam Fyles
I do get the whole mantra of "Thanks for your command. We'll be executing it ASAP. When it's done we'll email you.".
Yves Reynhout
There are just reasons why certain commands need immediate feedback. Imagine making a dentist appointment in an async fashion. That would cause a lot of emails if he's a busy dentist. All I'm saying is that certain workflows are synchronous by nature, because doing it otherwise would cause too much compensation afterwards.
Yves Reynhout
I totally agree, sounds to me like you don't need the asynchronous communication that NSB provides, seems like a regular request/response service will suffice. If you are worried about response time under load then maybe some other techniques can be applied(load balancing etc.)
Adam Fyles
In the case of a dentist appointment, you can look at having the command include a range of dates/times that work for the patient and have the system email back the time that fits the dentist.
Udi Dahan
I deal with dentists whose patients don't even have an email. When they're on the phone they want a confirmation, i.e. a date, time and place (so they can write it down on their calendar). Changing workflows to fit the asynchronous bill feels awkward to say the least. But in the same breath one could also say "Old habits die hard".
Yves Reynhout