2

I have a web service that receives requests from users and returns some json. I need to save the json string in the database so for the moment, the write query occurs before the response is sent back.

Is there a way to send the response first and then do the write query, after the response left the web service?

Thanks.

frenchie
  • 51,731
  • 109
  • 304
  • 510
  • could you explain/clarify more about this. I think you may be mixing terms and is causing confusion. a request is sent from the client and received by the server. the request is processed by the server. the server sends a response and the client receives the response. – Jason Meckley Jan 29 '12 at 00:36
  • Ok, updated the semantics. Still looking to write to the DB after the response left; is this possible? – frenchie Jan 29 '12 at 12:01

5 Answers5

2

There's a couple of different options here - they all have tradeoffs, though, and would be pretty esoteric. You don't mention why you want to do this, so I'm guessing performance. If that's the case, I think you're barking up the wrong tree - a simple write is almost certainly not your performance problem.

So, off the top of my head:

  1. Queuing, as Ragesh mentions, would be a nice approach. This gets you similar semantics of a transaction, while off loading the write. You still have to write to the queue, though, which may be about the same overhead as writing to the DB.
  2. You could spawn a new thread (using either the ThreadPool or System.Threading.Thread - there's some debates about which is preferable in ASP.NET) to handle the write. This can generally work, but you may have issues with unhandled exceptions, app domain restarts, etc.
  3. You could store the JSON data into a static or Application variable, then use a Timer to periodically write them to the DB. This will be multithreaded code, so you will need to synchronize read/writes to the collection.
  4. Similar to #3, store the JSON data into Cache and use the invalidation callback to write to the DB.
  5. Lots of variations on store somewhere (memory, disk, flat DB table, etc.), process later (ASP.NET, scheduled task, Windows Service, Sql Agent, etc.).

@frenchie says: a response starts by reading the json string from the db and ends with writing it back. In other words, if the user sends a request, the json string that's going to be read must be the one that was written in the previous response.

That complicates things, since inherent in async work is not knowing when something is done. If you require the async portion (writing back to the DB) to be done before handling the next request, you'll have to execute a wait to make sure it actually completed. In order to do that, you'll need to keep server side state on the client - not exactly a best practice as far as services go (though, it sounds like you're already doing that with these JSON request/response pairs).

Given the complications, I would make sure that you've done your profiling and determined it is indeed a performance problem.

Community
  • 1
  • 1
Mark Brackett
  • 84,552
  • 17
  • 108
  • 152
  • Thanks for your answer. I should have added that a response starts by reading the json string from the db and ends with writing it back. In other words, if the user sends a request, the json string that's going to be read must be the one that was written in the previous response. Does this change anything? Also, the size of the string is around 4K; should I just not worry about it given the size? – frenchie Jan 30 '12 at 11:41
1

You should look at using message queues like MSMQ, ActiveMQ or RabbitMQ to do this. When you receive your request, you'll put the relevant data in to the queue, and send your response to the client. At the other end of the queue, you'll have some process that reads from the queue and inserts data in to your database.

Ragesh
  • 2,800
  • 2
  • 25
  • 36
  • Hi, thanks for the ideas. There's something important I should have mentioned. The response starts by reading a json string. So the write must happen so that when the user sends a requests, we're reading the latest json string. What happens if the latest json string is in the queue instead of the DB when a request comes in? Do these queuing services handle that? – frenchie Jan 30 '12 at 11:45
  • You want the write to be asynchronous, but your situation needs it to be synchronous. It sounds to me like you're making things overly complicated for no real benefit. Just write synchronously to the database and be done with it. Why do you want jump through all these hoops just to avoid writing one string to the database? – Ragesh Jan 30 '12 at 11:58
1

You can do schedule a query work like

ThreadPool.QueueUserWorkItem(state => 
      this.AsynchronousExecuteReference());

 // and run
 static void AsynchronousExecuteReference()
 {
    // run here your sql update
 }

One other example using Thread inside an class and you can pass parameters to it.

public class RunThreadProcess
{
    // Some parametres
    public int cProductID;

    // my thread
    private Thread t = null;

    // start it
    public Thread Start()
    {
        t = new Thread(new ThreadStart(this.work));
        t.IsBackground = true;
        t.SetApartmentState(ApartmentState.MTA);
        t.Start();

        return t;
    }

    // actually work
    private void work()
    {
        // do thread work
        all parametres are available here
    }
}

And here is how I run it

  var OneAction = new RunThreadProcess();
    OneAction.cProductID = 100;
    OneAction.Start();

Do not worry about memory, CG knows that this process is used until the thread ends, so I have check it and CG not delete it and wait the thread to ends.

Aristos
  • 66,005
  • 16
  • 114
  • 150
  • Hi, The json string that I'm writing to the DB is also needed for the next request; ie. the requests begin by reading that json string. Also, thanks for the code. Where do I put the "ThreadPool..." and how does it execute after the response left? – frenchie Jan 30 '12 at 11:39
  • @frenchie This is send this thread on the query pool and when its time come is execute, If I remeber well this is not so safe, I will place some more example with a way to pass parametres. – Aristos Jan 30 '12 at 12:35
  • You should use the asynchronous methods on your data client classes in order to do the most with the I/O completion ports. – vtortola Jan 31 '12 at 10:59
  • ok, thanks for the detailed answer; I'm going to use it! Great reply. – frenchie Feb 01 '12 at 13:14
  • @frenchie I use this code/class as it is here, some years now and its work perfect, no memory or other issues with my code (except of course if you need to add mutex lock for synchronization.) In my pages I open 2 or 3 threads and do work parallel and after the page ends I also run similar 1-2 works. – Aristos Feb 01 '12 at 13:59
0

this is missing the point of a request/response. unless you want to get into async commands like a service bus, but that's pub/sub, not request/response. the point of request/response is to do the work on the server after receiving the request and before sending the response. even if the work is sending an async message to a service bus.

Jason Meckley
  • 7,589
  • 1
  • 24
  • 45
0

You could try moving your web service URL to an ASPX page where the lifecycles come in to play.

In the code-behind, call your routine that does the main portion of the work in Page_Load or Page_Prerender (or whenever is appropriate prior to the response being sent) and then do your DB work in the Page_Unload event which occurs after the response has been sent (http://msdn.microsoft.com/en-us/library/ie/ms178472.aspx).

pete
  • 24,141
  • 4
  • 37
  • 51