views:

129

answers:

3

I'm building a .NET web service that will be consumed by a vendor's application, and I'm not sure how to accomplish the following:

  • The vendor will call my webserivce with some information, but wants an acknowledgement returned quickly, just stating that I received their info. They don't care what I do with it, and don't want acknowledgement that I've finished processing.
  • The info that I was passed needs to do something behind the scenes and act on the information in a time-sensitive manner - i.e., take some actions within a few minutes. I'll be contacting a number of other web services, as well as doing some database work. Obviously, this will be after I've responded "Success" to the calling application.

I don't have control over the way the vendor accesses my service, and the method they're using to call it is synchronous, so I need to respond quickly to let the calling app continue its work. As I see it, there are two choices, though I'm open to others:

  1. Since the calling app is essentially submitting to a queue so that the process I've written can process it, I can have the web service just submit the item to the database (or an MSMQ or another queue) and then return success. The queue process will pick up processing from there.
  2. Ideally, I pictured that my service could return "Success" and then just continue processing on its own, but I'm not sure if this is possible. Since my processing is time-sensitive, kicking off the back-end processing of the new request is ideal, so wait time is minimal.

Are there any other ideas, or does one of these sound preferable?

A: 
  1. Receive the request
  2. Spin off background process (e.g. with a BackgroundWorker) with the passed-in parameters
  3. Return an acknowledgement - with a Guid or similar identifier of the request
  4. Do your processing ...
    1. In the meantime, the caller can ping your service for a status update based on the identifier
    2. While the processing is happening, return either a "still working" response or, if you're clever or can accurately predict it, return a progress measure (maybe as a percentage done or a quantity of time left)
  5. When the processing is done, return a "success" message to the status request
  6. Make the solution available, via the identifier you replied with earlier
Unsliced
A: 

Option 1 is the way to go, as the application already supports queueing.

As for an option 2 - you can start a worker thread from you web service, this will process the work and you can proceed to return "success" from the main thread.

Oded
+2  A: 

I think 1st is the only possible solution. 2nd is very bad design. Assume you process each request for 1 second, and there are 2 requests coming in 1 second in average. You will quickly run out of resources (because more and more threads will be used)

1st one is good because you have all control on how you will store and process requests. Good design is to have web service as frontend that will just answer "Success" and enqueue requests. As a persistent storage i recommend MSMQ or database. Then create a service app that will have pool of threads and will pick from queue(db).

Andrey
+1 - the first option is fault-tolerant, more scalable, and it will be easier to maintain and extend after the initial investment, offering a better separation of concerns across your applications. I'd only consider option two if those things aren't important, or aren't as important as getting your service up and running fast.
Jeff Sternal
Interesting thought - it didn't occur to me until I was posting that I'm essentially just rolling my own queue anyways. Is there a way for me to send a hit to a Windows Service running somewhere to let it know about the new queue item, since I will have stored it in the database, or do I need to wait for the service to check the queue itself and see the new item?
rwmnau
@rwmnau - I'd just configure the service to check the queue itself. If you're using the .NET System.Messaging APIs, you can execute `MessageQueue.Receive` in a loop, with a reasonable timeout. When it times out, check to see if the service is shutting down. Break the loop if it is, otherwise, go back to receiving messages. The process will pick messages up as soon as they are written to the target queue. (Except during the brief period in which it's checking whether or not it should shut down.)
Jeff Sternal
You can make your life even easier - you can use WCF with MSMQ bind and don't write a single line of code to handle MSQM.
Andrey