Run background jobs in Rails

Working on Ruby on Rails we come across many situations were we need to run programs in the background. There are several methods to approach the problem; each of them having its share of advantages and disadvantages. But before going into those methods itself, let us first look at the problems faced.

The Problem

Rails is pretty much self sufficient when it comes to web frameworks, but when it comes to long running background process, it runs into problems if not handled properly. For example – a large file needs to be uploaded from the browser and the web application processes it in the backend. It ends up in a UI that is unresponsive, a clogged up server which can’t take up any more requests etc etc.

The Solution

The solution is simple in theory, we have to change the program such that interface will just initiate the process and the actual processing is done in background. But this generates new problems. How do you now show the status and result of the operations in the user interface?. Luckily there are gems like delayed_job, Backgroun Job aka bj and workling which does exactly that, so you don’t really need to reinvent the wheel. We’ll take a look at one of these gems – delayed_job

delayed_job

Say we need an app which will upload a file, then do some time consuming operations on it and finally display a message “File uploaded” on success. Let’s say the method which will be called in the controller is processfile(filename), which will take a lot of time to execute.

This is how controller will look

class UploadController < ApplicationController
  def upload
    Upload.processfile(params[:dump][:tempfile])
  end
end

And Upload class as below

class Upload
  def processfile(file)
    sleep(30)
  end
end

Supposing the processfile method takes 30 seconds to complete (which it does in the above example), all further URL calls to the server after the file upload will be on hold for 30 seconds – not good. This is where delayed_job comes in. So how do we integrate delayed_job here? Let’s go step-by-step.

So first thing we need to do is add the gem to our Gemfile and run bundle install.

gem 'delayed_job_active_record'

After bundle install finishes, in the app home folder, run the below command:

rails generate delayed_job

This will generate the migration files required for delayed_job. Now we have to run database migration.

rake db:migrate

This will create the tables required by the gem. That lays the groundwork for using delayed_job. Let’s now start looking into the changes we need to make in code.

Luckily, we just need a small change in code as below:

Upload.processfile(filename)

to

Upload.delay.processfile(filename)

As you have noticed the only change in the code is that a “delay” is added in between the object name and the object’s method. Viola! Your job is now properly delayed and will not block other requests to the server. And if the delayed method fails for some reason you can check the last_error field in delayed_job table which shows the error encountered while running the method.

How does it work then? What happens here is that delayed_job added a method delay to all the objects. The delay method will create an entry in the delayed_jobs table with serialized object as yaml. There is a delayed_job daemon running in the background which picks up this job from the table and runs the appropriate method that is called after delay.

delayed_job uses either activerecord or mongoid to store the delayed job details. But what if you don’t want to any of these and only have Redis to work with. In this case we can use the MobME async_service gem which is easy to install and use. And it’s open source! Let’s take a look.

async_service

async_service uses redis queue as backend and we have to add items to be processed to a queue. async_service gives us the freedom of using any queue name and what to do after we pop an item from the queue. Let’s look in detail

First you have to add async_service to the Gemfile and run bundle install

gem "async_service"

After installation of the gem we can straight away start using it. Compared to delayed_job configuration of async_service is the easiest. So now lets take a look on how to use the gem with the help of the example given in async_service homepage.

class CalculatorMachine < AsyncService::Worker
  # You need to set a service name @service_name = 'in.mobme.calculator_machine'
  # This function is called on run
  def work
    loop do
      queue.remove("work_queue") do |item|
        result = item[:a] + item[:b]
        queue.add("result_queue", result)
      end
      sleep 5
    end
  end
end

Inorder to use the gem the target class has to inherit from the AsyncService::Worker. Inside this class we have to define a method “work” which decides what is to be done with the data that is present in queue. The method work is triggered internally when we call the run method (inherited from AsyncService::Worker). Since this example is for a calculator it pops an element from the queue “work_queue”, adds the elements and saves them to another queue “result_queue”.

To use this class make an instance of the class and call the run method on that instance.

calculator = CalculatorMachine.new
calculator.run

So to add two numbers we will insert the numbers to “work_queue” and we can read the output, which is the sum of the numbers, from the “result_queue” of Redis.

More complex tasks

For most projects this would be sufficient. But how about a requirement (that we had internally) that needs to run a maintenance job daily which takes hours to complete. Add to that, it was not initiated by user, i.e there won’t be a user who asks for it to be run and it needs to start by itself everyday. First solution was to set a cron job which does the same. But it outlived its usefulness when multiple processes needed to be run at multiple times daily, which meant to create multiple cron jobs or create a single script which can handle this. We went in for the latter solution since that was more maintainable.

Rails Runner

Enter Rails Runner – this was the perfect solution to our earlier problem. Rails Runner helps us to run scripts in the Rails application environment. All supporting files and gems needed for the application environment is taken care of automatically and we don’t need to tinker with all that too much and rather can concentrate mostly on the job at hand. And the script that we came up with, once started will wait for the assigned time and will start the jobs as required by specification which gives us more freedom to schedule any number of maintenance jobs at any time. And we don’t have to worry about configuring the cron in the server every time a new requirement comes, we just have to restart our rails runner.

The command for that looks like below:

~/app/folder$ rails runner path/to/file.rb
So in conclusion, Rails can handle long running and repeated background jobs very well – just that you need to use the right tools to do it the Rails way!

About the author

Neeraj is a network solutions developer who handles and takes good care of our core systems including our USSD and OBD stacks.

Asterisk and Visual Dial Plan (VDP)

In the Asterisk PBX, a dial plan is the basic building block of an IVR and extensions.conf is the configuration file that contains this dial plan.

Usually, dial plans contain a collection of contexts. In each context, we define the particulars of the call flow, and from each context we can jump either into an AGI (Asterisk Gateway Interface) or to some other context. AGI is very flexible and can be written in many different languages—Perl, PHP, C, Pascal et. al. Here at MobME, we mainly use Adhearsion, which is the Ruby wrapper around Asterisk AGI.

Visual Dial Plan is a graphical tool that provides a WYSIWYG GUI that enables users to design and validate Asterisk dial plans better. The output of the VDP editor is in a format that can then be directly processed by Asterisk. Though a commercial product VDP has a feature limited free version too. It is an ideal platform for someone new to Asterisk to create professional dial plans and even for   an expert to explore deep into the lesser known features Asterisk provides.

Configuring VDP with the local Asterisk

Before we can start, we need to configure VDP with an existing Asterisk installation. The below screen shot explains how this can be done. We can connect VDP either to a remote machine or to a local server. The screen shown below has the option to enter username, password and the Asterisk version. Once this is provided, you can proceed to establish a connection with Asterisk. If successfully connected, VDP is ready to use.

Starting a new dial plan

Create a new dial plan with the existing connection available. Provide a context name that you are going to start with. Now you should be able to view the work area and various other options. The below screen shot shows the options available under “Call Management”. Even though this is limited, it covers almost all features required to create a simple Dial Plan.

Dial plan using VDP

The above screen shot shows how the visual dial plan looks like. It is created using building blocks, which represents an asterisk feature. On right click, each of these blocks will provide an option to edit the parameters of that. The below screen shot shows such an edit option for the ‘queue’ block (second row second one) above.

The above dial plan is a simple one that initially plays a sound file. After that it waits for 5 seconds to receive a key press. If the key press is “1” then call will be routed to a queue named “patch-queue” and if the key pressed is “2” then next extension will curl an activation URL. If the response received for activation URL is a success, then a “thank-you” audio file will be played. Otherwise, a failure audio clip will be played. For an invalid key press, control will go to the “i” extension that plays an error sound file. Since the Dial plan created is simple, call will end after the above steps. Validate the dial plan and deploy the codes into the server.

The above figure is the extensions.conf file generated corresponding to the vdp that we created earlier.

Conclusion

Pros

  • It is quite easy to understand the working of VDP

  • The performance of IVRS will be much better if we can include the whole dial plan in extensions.conf (without using AGIs).

  • The dial plan created using VDP gives a much more professional outlook. It is well arranged and steps are labeled properly.

  • Many features of Asterisk are possibly unknown to a new developer, these can be explored using VDP.

Cons

  • Without using AGIs the dial plan can get extremely lengthy. In such situations, making small changes manually in the dial plan is very difficult.
  • For complicated trees it is better to continue using AGIs because of the need to use a lot of programming logic.
  • We have to do some manual changes in the configuration files other than extensions.conf. For example, if we want to create a queue then we have to add the queue member & strategy queue name et. al. in the queues.conf file. Only then we can choose that queue from the interface. Slightly cumbersome.

About the author

Jeethu is an engineer with the network solutions department of MobME. He mainly works on twiddling the back-ends of the big consumer mobile networks.

JSFoo Chennai 2012

JSFoo 2012 Chennai

JSFoo was a one day conference on building full size apps in JavaScript. They had a bunch of javascript geeks who had mastered the art of Javascript (not just your regular run of the mill jQuery) and wanted to show interesting stuff you can do with it to other folks. They had sessions ranging from from pure JavaScript apps in Node.js to real-time streaming of data to building responsive and interactive smartphone apps using pure Javascript!

The event was on February 18, and the venue was IITM Research Park Chennai. Our bus got late and we kind of missed the keynote and first session (Advanced JavaScript Techniques). There were sessions going on in parallel in two rooms and we had planned ahead which all sessions to attend.

  1. The next session was on “Production ready apps with flatiron” which was about Flatiron.js, a new node.js framework for creating web applications. Pavan Kumar Sunkara previewed the features of new framework and comparing it with Express.js
  2. JavaScript and the Compatible Web” was an interesting session which had very useful tips on creating websites for the mordern web. Rajasekharan Vengalil demoed detect and emulate the new CSS/HTML5 features using modernizer and pollyfills.
  3. Amplify your stack” was all about programming the right way following the right workflow. Aditya Yadav talked about tools and tips that will increase productivity as a web developer.
  4. Adding real time support to your web app” explained the new HTML5 Websockets feature to add real time support to your app. Kausikram Krishmasayee explained the steps required when designing a real time app.
  5. Node.js on Windows Azure” was all about hosting node.js app Windows cloud platform Azure
  6. Face/Off: jQuery Mobile vs Sencha Touch” was the most interactive sessions of all; Harish Sivaramakrishnan was very lively and he had a pretty funny presentation. He built jQuery Mobile and Sencha app simultaneously and explained which is best suited for different situations and developer needs.
  7. Ajax is history – Build real time apps in JavaScript” was yet another session on using socket.io and node.js to build real time apps.

It was fun attending the JSFoo, we had a great time. Hasgeek has a done a wonderful job bringing experts together and sharing thier ideas.

About the author

Software Engineer, VAS, likes to code and design interactive and responsive web interfaces!