Making long/bulk web operations offline/asynchronous

As web is a stateless medium of interaction, every action is a request/response pair. As this request response pair should have a definite life cycle there are timeouts attached to It i.e. you can not wait for a request’s response forever. There comes a problem where you want to execute longish actions. These longish actions doesn’t exists in common websites as these websites restrict these actions by limiting their scopes but in some web applications these longish actions are required like CRMs where you can import contact lists of significant sizes and later manage them using CRM application. Now loading this big contact file can take longer than timeout of request/response which can problem for the user of these applications.

Another example can be taken as exporting a big report which can be done synchronously but may be problematic for user which will keep downloading it for long time.

Following are some of solutions which can be considered for above problem:

A. Queuing longish/bulk actions and notify the user later when the actions is performed for the worker thread of queue.

B. Perform action synchronously but update its status to user using different thread.

Let’s take each approach one by one.

Approach A: In this case, you need a separate infrastructure with your application which acts as queue of actions which will help you in following ways:

1. It will control the load on your application as only limited number bulky or longish actions will be allowed. Because of the queue of actions, it can be controlled and worker threads can be configured accordingly.

2. More control over reporting the status of each action. User can be notified in different ways about completion of an action started by him e.g. an email notification can be sent to him on completion of his action.

Implementation will require following:

1. A place to store this queue of actions. It can be a DB table or in-memory queue. Queue should store all the inputs required to perform that action.
2. A thread or set of threads to perform queued actions and update action’s status in queue.
3. A notification mechanism to notify the user.

Approach B: You do not require an a complete queue like infrastructure in this approach. You need to perform your long or bulk operation in following steps:

1. Create a table to store progress of long/bulk operation
2. Generate a requestID and insert a row in table created against that requestID
3. Now while doing this long/bulk operation, keep updating the progress of operation against generated requestID.
4. On web application, keep fetching the status of operation against the generate requestID and keep showing this to the user until operation is complete.

You can use Ajax in following way to display the progress of any long action using jquery:

function doLongAction(){
    // Generate a requestID and store an entry against this long action
    var requestId = '';
    $.ajax({
        url: '../portal/longAction?q=addlongOperation',
        type: "POST",
	    cache: false,
	    dataType: "json",
	    async: false,
	    success: function(msg){
		    if(msg.result == 'success') {
			    requestId = msg.requestid;
		    } else if(msg.result == 'error') {
			    // Show error
		    }
	    },
	    error: function(msg){
		    // Show error
	   }
    });

    var serverUrl = '../portal/longAction?q=startLongAction&requestId=' + requestId;
    $.ajax({
        url: serverUrl
        type: "POST",
	    cache: false,
	    dataType: "json",
	    async: false,
	    success: function(msg){
		    if(msg.result == 'success') {
			    // do nothing
		    } else if(msg.result == 'error') {
			    // show error
		    }
	    },
	    error: function(msg){
		    //show error
	    }
    });
    showlongActionProgress(requestId);
}

function showlongActionProgress(requestId) {
    var progressInfo = function getProgressInfo() {
    var serverurl = ''../portal/longAction?q=fetchActionDetail&requestId=' + requestId;
        $.ajax({
            url: serverurl,
	        type: "POST",
	        cache: false,
	        dataType: "json",
	        async: false,
	        success: function(msg){
		       if(msg.result == 'success' && msg.detail.status == 'INPROGRESS') {
			    // Show progress
		       } else if(msg.result == 'success' && msg.detail.status == 'DONE') {
			    // Show success
		           clearInterval(progressInfoHandle);
		       } else if(msg.result == 'error') {
			    // Show error
                            clearInterval(progressInfoHandle);
		       }
	         },
	       error: function(msg){
		    clearInterval(progressInfoHandle);
	            //Show Error
	       }
        });
    };
    var progressInfoHandle = setInterval(progressInfo, 500);
}

Most Commented Posts

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

No comments yet.

Leave a comment

(required)

(required)