  
<div id="snippet_161" class="snippet">
  <h2><a href="/snippets/161-Using-backgroundrb-to-execute-tasks-asynchronously-in-Rails" title="Using backgroundrb to execute tasks asynchronously in Rails - Ruby - backgroundrb, rails, ruby, distributed, messaging">Using backgroundrb to execute tasks asynchronously in Rails</a></h2>
  <div class="details">
    <a style="background-color: #FFFF94;" href="http://snippets.aktagon.com/languages/124-Ruby">
      Ruby</a> posted about 1 year ago by christian
          
  </div>

  <div class="body">
    <p>Draft&#8230;</p>


	<h2>Planning on using BackgroundDRB? Take a long look at the alternatives first</h2>


	<p>Ask yourself, do you really need a complex solution like BackgroundDRB? Most likely you don&#8217;t, so use a simple daemonized process instead, see <a href="http://snippets.aktagon.com/snippets/212-How-to-create-a-daemon-process-using-Ruby-and-the-daemons-RubyGem">this snippet about the daemons gem</a> for  more information.</p>


	<p>Heck, even a simple Ruby script run by cron every 5 minutes will be more stable than BackgroundDRB and require less work.</p>


	<p>Even if you really need to process a lot of data asynchronously in the background, I wouldn&#8217;t recommend BackgroundDRB, it&#8217;s riddled with bugs and unstable in production, so use the <a href="http://agilewebdevelopment.com/plugins/bj">BJ plugin</a> instead.</p>


	<p>Anyway, continue reading if you want to use BackgroundDRB&#8230;</p>


	<h2>Installing the prerequisites:</h2>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> $ sudo gem install chronic packet 
</pre></p>


	<h2>Installing backgroundrb</h2>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> $ cd rails_project
<span class="line-numbers">   2 </span> $ git clone git<span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>/</span><span class="Operator">/</span>gitorious.<span class="FunctionName">org</span><span class="Operator">/</span>backgroundrb<span class="Operator">/</span>mainline.<span class="FunctionName">git</span> vendor<span class="Operator">/</span>plugins<span class="Operator">/</span>backgroundrb
</pre></p>


	<p>You can also get the latest stable version from the Subversion repository:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> svn co http<span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>/</span><span class="Operator">/</span>svn.<span class="FunctionName">devjavu</span>.<span class="FunctionName">com</span><span class="Operator">/</span>backgroundrb<span class="Operator">/</span>trunk  vendor<span class="Operator">/</span>plugins<span class="Operator">/</span>backgroundrb
</pre></p>


	<h2>Setup backgroundrb</h2>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> rake backgroundrb<span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>setup</span>
</pre></p>


	<h2>Create a worker</h2>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> .<span class="Operator">/</span>script<span class="Operator">/</span>generate worker feeds_worker
</pre></p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="Keyword">class</span> <span class="TypeName">FeedsWorker<span class="InheritedClass"> <span class="InheritedClass">&lt;</span> BackgrounDRb::MetaWorker</span></span>
<span class="line-numbers">   2 </span>   set_worker_name <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>feeds_worker</span>
<span class="line-numbers">   3 </span>   
<span class="line-numbers">   4 </span>   <span class="Keyword">def</span> <span class="FunctionName">create</span>(<span class="FunctionArgument">args <span class="Operator">=</span> <span class="BuiltInConstant">nil</span></span>)
<span class="line-numbers">   5 </span> <span class="LineComment">    <span class="LineComment">#</span> this method is called, when worker is loaded for the first time</span>
<span class="line-numbers">   6 </span>     logger.<span class="FunctionName">info</span> <span class="String"><span class="String">&quot;</span>Created feeds worker<span class="String">&quot;</span></span>
<span class="line-numbers">   7 </span>   <span class="Keyword">end</span>
<span class="line-numbers">   8 </span>   
<span class="line-numbers">   9 </span>   <span class="Keyword">def</span> <span class="FunctionName">update</span>(<span class="FunctionArgument">data</span>)
<span class="line-numbers">  10 </span>     logger.<span class="FunctionName">info</span> <span class="String"><span class="String">&quot;</span>Updating <span class="String"><span class="String">#{</span><span class="LibraryClassType">Feed</span><span class="String"><span class="String">.</span><span class="FunctionName">count</span></span><span class="String">}</span></span> feeds.<span class="String">&quot;</span></span>
<span class="line-numbers">  11 </span>     
<span class="line-numbers">  12 </span>     seconds <span class="Operator">=</span> <span class="LibraryClassType">Benchmark</span>.<span class="FunctionName">realtime</span> <span class="Keyword">do</span>
<span class="line-numbers">  13 </span>       thread_pool.<span class="FunctionName">defer</span> <span class="Keyword">do</span>
<span class="line-numbers">  14 </span>         <span class="LibraryClassType">Feed</span>.<span class="FunctionName">update_all</span>()
<span class="line-numbers">  15 </span>       <span class="Keyword">end</span>
<span class="line-numbers">  16 </span>     <span class="Keyword">end</span>
<span class="line-numbers">  17 </span> 
<span class="line-numbers">  18 </span>     logger.<span class="FunctionName">info</span> <span class="String"><span class="String">&quot;</span>Update took <span class="String"><span class="String">#{</span><span class="String"><span class="String">'</span>%.5f<span class="String">'</span></span> <span class="Operator">%</span> seconds<span class="String">}</span></span>.<span class="String">&quot;</span></span>
<span class="line-numbers">  19 </span>   <span class="Keyword">end</span>
<span class="line-numbers">  20 </span> <span class="Keyword">end</span>
</pre></p>


	<h2>Starting backgroundrb</h2>


	<p>First configure backgroundrb by opening config/backgroundrb.yml in your editor:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span>:
<span class="line-numbers">   2 </span>   <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>ip</span>: <span class="Number">0.0</span>.<span class="Number">0.0</span>
<span class="line-numbers">   3 </span> 
<span class="line-numbers">   4 </span> <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>development</span>:
<span class="line-numbers">   5 </span>   <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span>:
<span class="line-numbers">   6 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>port</span>: <span class="Number">11111</span>     <span class="LineComment"><span class="LineComment">#</span> use port 11111</span>
<span class="line-numbers">   7 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>log</span>: foreground <span class="LineComment"><span class="LineComment">#</span> foreground mode,print log messages on console</span>
<span class="line-numbers">   8 </span> 
<span class="line-numbers">   9 </span> <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>production</span>:
<span class="line-numbers">  10 </span>   <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span>:
<span class="line-numbers">  11 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>port</span>: <span class="Number">22222</span>      <span class="LineComment"><span class="LineComment">#</span> use port 22222</span>
</pre></p>


	<p>Next, start backgroundrb in development mode:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> .<span class="Operator">/</span>script<span class="Operator">/</span>backgroundrb <span class="Operator">-</span>e development <span class="Operator">&amp;</span>
</pre></p>


	<h2>Call your worker</h2>


	<p>From the command line:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> $ script<span class="Operator">/</span>console
<span class="line-numbers">   2 </span> <span class="Variable">Loading</span> development environment (<span class="Variable">Rails</span> <span class="Number">2.0</span>.<span class="Number">2</span>)
<span class="line-numbers">   3 </span> <span class="Operator">&gt;&gt;</span> <span class="LibraryClassType">MiddleMan</span>.<span class="FunctionName">worker</span>(<span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>feeds_worker</span>).<span class="FunctionName">update</span>() 
</pre></p>


	<h2>When things go wrong</h2>


	<p>Asynchronous programming is complex, so expect bugs&#8230;</p>


	<h3>Rule #1 know who you&#8217;re calling.</h3>


	<p>If you give your MiddleMan the wrong name of your worker, he&#8217;ll just spit this crap at you:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="Variable">You</span> have a <span class="BuiltInConstant">nil</span> object <span class="Keyword">when</span> you didn<span class="String"><span class="String">'</span>t expect it!</span>
<span class="line-numbers">   2 </span> <span class="String">The error occurred while evaluating nil.send_request</span>
<span class="line-numbers">   3 </span> <span class="String">/usr/local/lib/ruby/gems/1.8/gems/packet-0.1.5/lib/packet/packet_master.rb:44:in `ask_worker<span class="String">'</span></span>
<span class="line-numbers">   4 </span> <span class="String"><span class="String">/</span></span><span class="String">Users</span><span class="String"><span class="String">/</span></span>christian<span class="Operator">/</span><span class="Variable">Documents</span><span class="Operator">/</span><span class="Variable">Projects</span><span class="Operator">/</span>xxx<span class="Operator">/</span>vendor<span class="Operator">/</span>plugins<span class="Operator">/</span>backgroundrb<span class="Operator">/</span>server<span class="Operator">/</span>lib<span class="Operator">/</span>master_worker.<span class="FunctionName">rb</span>:<span class="Number">104</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>in</span> <span class="String"><span class="String">`</span>process_work'</span>
<span class="line-numbers">   5 </span> <span class="String">/Users/christian/Documents/Projects/xxx/vendor/plugins/backgroundrb/server/lib/master_worker.rb:35:in <span class="String">`</span></span>receive_data<span class="String"><span class="String">'</span></span>
<span class="line-numbers">   6 </span> <span class="String">/usr/local/lib/ruby/gems/1.8/gems/packet-0.1.5/lib/packet/packet_parser.rb:29:in `call<span class="String">'</span></span>
<span class="line-numbers">   7 </span> <span class="String"><span class="String">/</span></span><span class="String">usr</span><span class="String"><span class="String">/</span></span>local<span class="Operator">/</span>lib<span class="Operator">/</span>ruby<span class="Operator">/</span>gems<span class="Operator">/</span><span class="Number">1.8</span><span class="Operator">/</span>gems<span class="Operator">/</span>packet<span class="Operator">-</span><span class="Number">0.1</span>.<span class="Number">5</span><span class="Operator">/</span>lib<span class="Operator">/</span>packet<span class="Operator">/</span>packet_parser.<span class="FunctionName">rb</span>:<span class="Number">29</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>in</span> <span class="String"><span class="String">`</span>extract'</span>
<span class="line-numbers">   8 </span> <span class="String">/Users/christian/Documents/Projects/xxx/vendor/plugins/backgroundrb/server/lib/master_worker.rb:31:in <span class="String">`</span></span>receive_data<span class="String"><span class="String">'</span></span>
</pre></p>


	<p>So for example this command would generate the above mentioned error:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="LibraryClassType">MiddleMan</span>.<span class="FunctionName">worker</span>(<span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>illegal_worker</span>).<span class="FunctionName">update</span>() 
</pre></p>


	<p>It&#8217;s always nice to see a cryptic error messages such as this, it really deserves an award.</p>


	<h3>Check for bugs and bug fixes</h3>


	<p><a href="http://gitorious.org/projects/backgroundrb/repos/mainline/logs/master">git mainline commits</a></p>


	<h3>Going to production</h3>


	<p>Starting the daemon:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> .<span class="Operator">/</span>script<span class="Operator">/</span>backgroundrb <span class="Operator">-</span>e production start
</pre></p>


	<h2>Configuring your task to run periodically</h2>


	<p>The following example makes backgroundrb call the FeedsWorker&#8217;s update method once every 15 minutes:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>production</span>:
<span class="line-numbers">   2 </span>   <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span>:
<span class="line-numbers">   3 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>port</span>: <span class="Number">22222</span>      <span class="LineComment"><span class="LineComment">#</span> use port 22222</span>
<span class="line-numbers">   4 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>lazy_load</span>: <span class="BuiltInConstant">true</span>  <span class="LineComment"><span class="LineComment">#</span> do not load models eagerly</span>
<span class="line-numbers">   5 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>debug_log</span>: <span class="BuiltInConstant">false</span> <span class="LineComment"><span class="LineComment">#</span> disable log workers and other logging</span>
<span class="line-numbers">   6 </span> <span class="LineComment"><span class="LineComment">#</span> Cron based scheduling</span>
<span class="line-numbers">   7 </span> <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>schedules</span>:
<span class="line-numbers">   8 </span>   <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>feeds_worker</span>:
<span class="line-numbers">   9 </span>     <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>update</span>:
<span class="line-numbers">  10 </span>       <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>trigger_args</span>: <span class="Operator">*</span> <span class="Operator">*</span><span class="Operator">/</span><span class="Number">15</span> <span class="Operator">*</span> <span class="Operator">*</span> <span class="Operator">*</span> <span class="Operator">*</span>
<span class="line-numbers">  11 </span>       <span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>data</span>: <span class="String"><span class="String">&quot;</span>Hello world<span class="String">&quot;</span></span>
</pre></p>


	<p>At the time of writing, the cron scheduler seems to be broken, so I prefer hard-coding the interval in the worker&#8217;s create method:</p>


	<p><pre class="active4d"><span class="line-numbers">   1 </span> <span class="Keyword">def</span> <span class="FunctionName">create</span>
<span class="line-numbers">   2 </span>            <span class="FunctionName">add_periodic_timer</span>(<span class="Number">15</span>.<span class="FunctionName">minutes</span>) { update }
<span class="line-numbers">   3 </span>          <span class="Keyword">end</span>
</pre></p>


	<p>If using Vlad or Capistrano, it&#8217;s also a good idea to fix script/backgroundrb by changing these lines: 
<pre class="active4d"><span class="line-numbers">   1 </span> pid_file <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span><span class="String"><span class="String">#{</span><span class="Variable">RAILS_HOME</span><span class="String">}</span></span>/../../shared/pids/backgroundrb_<span class="String"><span class="String">#{</span><span class="Variable">CONFIG_FILE</span><span class="String">[</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span><span class="String">]</span><span class="String">[</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>port</span><span class="String">]</span><span class="String">}</span></span>.pid<span class="String">&quot;</span></span>
<span class="line-numbers">   2 </span> <span class="Variable">SERVER_LOGGER</span> <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span><span class="String"><span class="String">#{</span><span class="Variable">RAILS_HOME</span><span class="String">}</span></span>/../../shared/log/backgroundrb_server_<span class="String"><span class="String">#{</span><span class="Variable">CONFIG_FILE</span><span class="String">[</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>backgroundrb</span><span class="String">]</span><span class="String">[</span><span class="UserDefinedConstant"><span class="UserDefinedConstant">:</span>port</span><span class="String">]</span><span class="String">}</span></span>.log<span class="String">&quot;</span></span>
</pre></p>


	<h3>Resources</h3>


	<p><a href="http://backgroundrb.rubyforge.org/">Backgroundrb homepage</a></p>


	<p><a href="http://gnufied.org/2008/02/12/backgroundrb-best-practises/">Backgroundrb best practices</a></p>


	<p><a href="http://backgroundrb.rubyforge.org/scheduling/index.html">Backgroundrb scheduling</a></p>


	<p><a href="http://www.johnyerhot.com/2008/02/11/debugging-backgroundrb/">Debugging backgroundrb</a></p>


	<p><a href="http://backgroundrb.rubyforge.org/files/README.html">Backroundrb&#8217;s  README </a></p>


	<p><a href="http://nubyonrails.com/articles/about-this-blog-beanstalk-messaging-queue">topfunky&#8217;s messaging article</a></p>
  </div>

  <div style="font-size: 0.8em;margin:0.5em;">
    
      Tagged <a href="/tags/404-backgroundrb">backgroundrb</a>, <a href="/tags/9-rails">rails</a>, <a href="/tags/8-ruby">ruby</a>, <a href="/tags/405-distributed">distributed</a>, <a href="/tags/406-messaging">messaging</a>
    
    
  </div>
</div>






