@madpilot makes

Make scheduling jobs easier – use web services!

Web developers deal with scheduled jobs a lot. Any online application that deals with paid subscriptions needs to remind users when they need to pay up. Other apps may require data mining services to be run on a nightly basis.

This is pretty easy to do – run a cronjob under *nix or a scheduled task under windows. However, where things get tricky is when you have spent an in ordinate amount of time coding business logic into you application. Duplicating this logic for an external script to be run by cron is pretty silly, not to mention bug-prone. However there is a quick and simple solutions: Web services!

By setting up a web service that does your maintainence, you can leverage the classes and business rules that you have already written. For example, if we take a Model-View-Controller framework (such as Rails or CakePHP) we may have logic that will do data manipulations before the data is saved to the database. There is no way I would want to try and emulate what these frameworks do in an external script. By using web services, you are calling the framework natively and you avoid all of these problems.

How it works

It is really simple:

  1. Setup a webservice that will perform the functions you need to run on a regular basis.
  2. Create a simple script that calls the web services.
  3. Add this script to you crontab or task scheduler

The beauty is that you don’t even need to bother setting up the web service using SOAP or XML-RPC – REST will do the job quite nicely, especially since the web service is designed to only be used by you. However, when using rails I like to use SOAP, because it is so easy to setup and use. Here is a simple example:

housekeeping_controller.rb
  1. class HousekeepingController < ApplicationController
  2. wsdl_service_name ‘Housekeeping’
  3. web_service_api HouseKeepingAPI
  4. def maintain()
  5. # Run you maintainence script here
  6. end
  7. end

This file is the webservices controller. You would add your logic here – this may be expiring users or automatically checking email.

housekeeping_api.rb
  1. class HousekeepinApi < ActionWebService::API::Base
  2. api_method :maintain, :returns => [:string]
  3. end

This file defines the method to the web service caller. I usually set the return to type :string so I can output statistical messages or errors that occur during the job.

housekeeping_job.rb
  1. #!/usr/bin/ruby -w
  2. require ‘soap/wsdlDriver’
  3. include SOAP
  4. begin
  5. wsdl = ‘path_to_wsdl_file’
  6. factory = WSDLDriverFactory.new(wsdl)
  7. housekeeping = factory.create_rpc_driver
  8. out = housekeeping.maintain
  9. put_s out
  10. rescue Exception
  11. $stderr.print “An error occured: #{$!}n
  12. $stderr.print “Detailes error description, if any:n
  13. raise
  14. end

This file is called by the cronjob. You will need to replace the string path_to_wsdl_file with the path to the real WSDL file. You get get the WSDL file from a Rails web service by querying /:controller/wsdl (so in this example http://www.yoursite.com/housekeeping/wsdl – pipe the returned xml to a file and save it.

Then it is just a matter of adding the housekeeping_run.rb command to you cronjob! Cron will even email you the results that get returned by your service – Nifty!

Nice an easy, eh?

6 comments

  1. Cool, thanks for the tip! I'm trying to do this with the CakePHP framework but not quite sure how to go about it. Do you know of any good tutorials on setting this up w/ Cake? I've never used Ruby or SOAP, so looking at your code snips above is pretty greek to me.



    Thanks!
  2. Hi Zack,



    There are many ways of doing it with CakePHP. At the moment, setting up SOAP is pretty difficult, but one thing that I quite often do is setup a function in a controller that does the maintainence and call it via a cronjob using a command line web client such as wget or curl.
  3. Thanks Myles,



    I guess I'll hold off on learning SOAP then, as it sounds like quite a project and I don't have much time right now. I'll go with wget for the time being.



    Cheers!
  4. Hi, Myles

    This is what I need. I tried backgroundrb, but It may not stable enough for our project. This one is easy and cool. One question, there is a login needed in our project. So where should I put the login information in 'houlsekeeping_job.rb' file? Since anytime window task scheduler call the housekeeping.rb, what showed on the console is it will stop at login.

    Thanks in advance
  5. Hi Leo,



    It depends on how you are doing your authentication. I assume you are using SOAP? There are a couple of ways that you can do authentication in SOAP.



    1. Sending credentials via the SOAP header

    2. Using HTTP authentication



    Unfortunately, the samples in the SOAP4R use the SOAP driver class, which is a bit different to the factory class (The later generates the former).



    I've got some code laying around, I'll try and dig it up for you.
  6. Pingback: Alban’s blog » Blog Archive » soap4r and keep-alive

Leave a comment