<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>The Napkin ~ A Blog By Highgroove Studios comments on Running Background Jobs in Ruby on Rails</title>
    <link>http://cleanair.highgroove.com/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>The Napkin ~ A Blog By Highgroove Studios comments</description>
    <item>
      <title>"Running Background Jobs in Ruby on Rails": comment by Rafael Lima</title>
      <description>&lt;p&gt;I&amp;#8217;m using rails_cron but I don&amp;#8217;t know why, I cannot restart rails_cron with a capistrano task.&lt;/p&gt;


	&lt;p&gt;task :restart_cron, :roles =&amp;gt; :web do
  run &amp;#8220;cd #{deploy_to} &amp;#38;&amp;#38; &amp;#8221; +
      &amp;#8221;#{rake}  RAILS _ENV=#{rails_env} cron_graceful&amp;#8221; 
end&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m running :restart_cron after :apache_reload task.&lt;/p&gt;


	&lt;p&gt;Everytime I deploy, rails_cron stop working&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Any ideas?&lt;/p&gt;</description>
      <pubDate>Fri, 18 Aug 2006 13:51:03 EST</pubDate>
      <guid>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-97</guid>
      <link>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-97</link>
    </item>
    <item>
      <title>"Running Background Jobs in Ruby on Rails": comment by Dave</title>
      <description>&lt;p&gt;Wonderful. Just what I&amp;#8217;ve been looking for. Thanks.&lt;/p&gt;</description>
      <pubDate>Tue, 11 Jul 2006 16:09:11 EST</pubDate>
      <guid>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-29</guid>
      <link>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-29</link>
    </item>
    <item>
      <title>"Running Background Jobs in Ruby on Rails": comment by Mr. Neighborly</title>
      <description>&lt;p&gt;Holy crap those look incredibly useful.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m totally overhauling my storefront/PDF generator process with rails_cron.&lt;/p&gt;


	&lt;p&gt;Thanks a lot for the information. :)&lt;/p&gt;</description>
      <pubDate>Fri, 23 Jun 2006 14:35:06 EST</pubDate>
      <guid>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-18</guid>
      <link>http://cleanair.highgroove.com/articles/2006/06/23/running-background-jobs#comment-18</link>
    </item>
    <item>
      <title>"Running Background Jobs in Ruby on Rails" by cbq</title>
      <description>&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; rails_cron is no longer available, and &lt;a href="http://github.com/dougal/daemon_generator/"&gt;daemon_generator&lt;/a&gt; has moved.  BackgrounDRB has gone through a major rewrite, and I&amp;#8217;ve got a chapter on Background Processing in &lt;a href="http://www.amazon.com/Rails-Way-Addison-Wesley-Professional-Ruby/dp/0321445619"&gt;The Rails Way&lt;/a&gt; by Obie Fernandez. Thanks to Chris Johnson and Douglas F Shearer for the updated information.&lt;/p&gt;


	&lt;p&gt;Without a way to run long-running tasks, &lt;a href="http://heartbeat.highgroove.com"&gt;Heartbeat&lt;/a&gt;, our &lt;a href="http://www.railsday2006.com"&gt;2006 Rails Day Entry&lt;/a&gt;, wouldn&amp;#8217;t have had a pulse.&lt;/p&gt;


	&lt;p&gt;Like Heartbeat, most web applications need to run regulary scheduled or long-running tasks at some point in their life-cycle. These tasks are often not inititated by a web request. How can you check the validity of a &lt;span class="caps"&gt;URL&lt;/span&gt; every 15 minutes? How do we get an eCommerce store to calculate the most popular items every 5 hours? How can we re-index our site for searching every day?&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;ve ever had to do this, chances are you&amp;#8217;ve used cron (the *nix tool used to schedule remote tasks) coupled with script/runner. However, wouldn&amp;#8217;t it be great if you could maintain your tasks and background &amp;#8220;jobs&amp;#8221; inside the ruby language, or even better, as part of your Rails application?&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s explore two ways to do this: the excellent &lt;a href="http://backgroundrb.rubyforge.org/"&gt;BackgrounDRb&lt;/a&gt; plugin by Ezra Zygmuntowicz, which was used to power Heartbeat, and the fabulous &lt;a href="http://svn.kylemaxwell.com/rails_cron/trunk/README"&gt;rails_cron&lt;/a&gt; by Kyle Maxwell.&lt;/p&gt;

&lt;h3&gt;Why not just use cron jobs?&lt;/h3&gt;


	&lt;p&gt;Any time you introduce a new piece to a system, there&amp;#8217;s room for bugs.  Adding pieces, especially ones that must be setup on individual platforms and deployment environments and in a &amp;#8220;different&amp;#8221; language compound and add complexity.&lt;/p&gt;


	&lt;p&gt;Also, Kyle Maxwell has this to say about cron:&lt;/p&gt;


&lt;blockquote&gt;when used with RoR, has the following shortcomings:

&lt;ul&gt;
&lt;li&gt;Significant startup resources required&lt;/li&gt;
&lt;li&gt;Lots of &lt;span class="caps"&gt;RAM&lt;/span&gt; to run simultaneous processes&lt;/li&gt;
&lt;li&gt;Hard to start/stop/affect the background processes from within Rails&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

	&lt;h3&gt;rails_cron&lt;/h3&gt;


	&lt;p&gt;rails_cron is &amp;#8220;a way to execute background tasks using your Ruby on Rails environment.&amp;#8221;  Perhaps the closest replacement yet to external cron scripts, rails_cron provides an easy-to-use language for creating and maintaining tasks.  Just look at this example link processor:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;RailsCron.create(
    :command =&amp;gt; "Link.process()", 
    :start =&amp;gt; 1.minutes.from_now,
    :every =&amp;gt; 30.seconds,               
    :finish =&amp;gt; 2.years.from_now
  )&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;RailsCron.destroy_all
RailsCron.find_by_command "Link.process()"&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;If you&amp;#8217;ve ever had to play with crontab, and it&amp;#8217;s myriad of 0 1 0 0 0 columns, then this is a breath of fresh air.&lt;/p&gt;


	&lt;p&gt;rails_cron stores its tasks in the database and once it starts up using rake tasks for starting and stopping&amp;#8212;it will poll the db every minute (overridable) for new tasks to execute.  This is especially nice for changing a daily task to a weekly one on the fly, without having to edit a crontab.&lt;/p&gt;


	&lt;h3&gt;BackgrounDRb&lt;/h3&gt;


	&lt;p&gt;BackgrounDRb is a plugin&amp;#8212;or rather, as Ezra puts it: &amp;#8220;a small framework for divorcing long running tasks from Rails request/response cycle.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;The best example is in the case of a file upload or process that you wouldn&amp;#8217;t want a user&amp;#8217;s &lt;span class="caps"&gt;HTTP&lt;/span&gt; request to have to sit and wait for.  When a user initiates a task that will take a while, you simple create a worker and backgrounDRb handles spawning a thread and keeping track of it&amp;#8217;s job &amp;#8220;key&amp;#8221; or id for you.  You can even update your own variable, such as a &amp;#8220;progress&amp;#8221; meter variable to poll the &amp;#8220;worker&amp;#8221; for current status.&lt;/p&gt;


	&lt;p&gt;After installing, the latest version even has a generator for creating a worker for you.  Let&amp;#8217;s generate a worker that will check a link every 30 seconds:&lt;/p&gt;


	&lt;p&gt;script/generate worker LinkProcessor&lt;/p&gt;


	&lt;p&gt;Now edit the newly created lib/workers/link_processor_worker.rb and add:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;while (var == true) # condition
  Link.process # do something
  sleep(30) # wait 30 seconds
end&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, starting up the background server and letting your workers run totally independent of a web request is a simple matter of running a small script/runner task (fired off by a rake task) to kick off your workers:&lt;/p&gt;


	&lt;p&gt;/lib/tasks/start_worker.rake&lt;/p&gt;


	&lt;p&gt;desc &amp;#8220;Start up my worker background process&amp;#8221; 
  task :process =&gt; :environment do
    `#{RAILS_ROOT}/script/runner &amp;#8216;Link.start_worker&amp;#8217;`
  end&lt;/p&gt;


	&lt;p&gt;class Link start_worker method:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;def self.start_worker
   job_key = MiddleMan.new_worker :class =&amp;gt; :link_processor_worker,
                                  :args =&amp;gt; "none" 
   # store job_key for reference...
   # start more worker tasks
 end&lt;/code&gt;&lt;/pre&gt;


	&lt;h3&gt;Gotchas&lt;/h3&gt;


BackgrounDRb&amp;#8217;s latest version has code to load the Rails environment, controlled by a configuration file.  However, be careful when including classes or libraries that backgroundRB might not know about.  In order to load your entire environment, you&amp;#8217;ll need to load up all of Rails by changing a few lines of code in the script/backgroundrb/start task:
&lt;pre&gt;
if CONFIG['load_rails']
ActiveRecord::Base.establish_connection(YAML.load(ERB.new(IO.read("#{RAILS_ROOT}/#{CONFIG['databse_yml']}")).result)[CONFIG['environment']])
end
&lt;/pre&gt;
to read:
&lt;pre&gt;
if CONFIG['load_rails']
   require "#{RAILS_ROOT}/config/environment" 
end
&lt;/pre&gt;
It&amp;#8217;s a bit of a memory hog, so if you can get away with loading specific libraries instead of &lt;span class="caps"&gt;ALL&lt;/span&gt; of Rails, you&amp;#8217;re better off.

	&lt;p&gt;Also, rails_cron will install a table in your database called rails_cron&amp;#8212;be sure it exists in all of your environments.&lt;/p&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;Rails still has a way to go before long-running tasks are as easy as other Rails conventions, but the current offerings are suitable for a production environment.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Jun 2006 01:58:00 EST</pubDate>
      <guid>&lt;a href="/articles/2006/06/23/running-background-jobs"&gt;Running Background Jobs in Ruby on Rails&lt;/a&gt;</guid>
      <link>&lt;a href="/articles/2006/06/23/running-background-jobs"&gt;Running Background Jobs in Ruby on Rails&lt;/a&gt;</link>
    </item>
  </channel>
</rss>
