Saturday, August 9, 2008

Asynchronous access via Ruby On Rails

Over the last month we have been pondering upon a major problem that needed to be implemented in a Ruby On Rails application. The statement of the problem is simple. I have a procedure/algorithm which takes two input sets, gets each element in the set and using a combination of the elements in the sets calculates a rating. As the problem it self suggests, this is a tedious process. Database access is evident and the procedure is also lengthy. I decided to write the algorithm implementation in the lib folder, so that it is accessible inside the application, and then call it inside the controllers.

If the algorithm was called inside the controller, the response would stall until the whole algorithm was completed. This is NOT what I wanted. The user should not be affected by the time the algorithm took to complete. The requirement here was to run this process as another thread/process at another place. To replicate the application environment in another server dedicated to this did not seem to be a great idea.

Thats when background process was suggested. Running the algorithm as another thread was another option. As the algorithm only required the sets, it could be run as a different thread. But the environment that the server provides must still be loaded. Ap4r came to the rescue here. Asynchronous Processing For Ruby could be used by any rails application to route all those tedious and time consuming accesses. This I thought was a smart way of doing a background process, although it is NOT a background process. It is just another url access. The Gem must be installed along with the plugin and the server must be started and wallah !! You are in ! Simple as that.

Next comes the trigger, ie the part where you actually need to start the background process. I had two places which acted as triggers. One was in the controller part and the other was from a model. Triggering from the controller part was easy as the plug-in's init file actually added the ap4r method with the Action Controller. Triggering from the model was tricky. As far as I know there is no way to actually call a url/controller method from a model. Theoretically this is wrong as the controller is supposed to be the base and the model does not need to know the controller which is accessing it, if it is accessing it.

I took the easy way out of this by firing a system command which did a wget to the url. This method (corresponding to the url) written in the controller does an asynchronous access thus returning immediately. Thus the system command does not stall the execution of the model method when it is called. The ap4r server is still called and the algorithm is run asynchronously thus serving our need.

The algorithm had many stages of executions/ filters along with database accesses. I managed to use message passing by calling the send method for the objects and lots of array operations. I thought I did a pretty good job in writing the algorithm. The vast thought that has been gone in developing a language like ruby must be praised here. Kudos to Yukihiro “matz” Matsumoto.

No comments: