<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Fixie - Home</title>
  <id>tag:blog.fixieconsulting.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://blog.fixieconsulting.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.fixieconsulting.com/" rel="alternate" type="text/html"/>
  <updated>2009-01-03T23:12:09Z</updated>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2009-01-03:743</id>
    <published>2009-01-03T23:08:00Z</published>
    <updated>2009-01-03T23:12:09Z</updated>
    <link href="http://blog.fixieconsulting.com/2009/1/3/concurrency-s-a-bitch" rel="alternate" type="text/html"/>
    <title>Concurrency's a bitch</title>
<content type="html">
            &lt;p&gt;On this Rails application I&#8217;m writing, I have a Person model.  When People are displayed to the user, the sort order is more complicated than a &lt;a href=&quot;&amp;lt;/p&quot;&gt;name asc&lt;/a&gt;&amp;gt;


	&lt;ul&gt;
	&lt;li&gt;First are featured People with a picture&lt;/li&gt;
		&lt;li&gt;Then are featured People without a picture&lt;/li&gt;
		&lt;li&gt;Then People with pictures and bio&lt;/li&gt;
		&lt;li&gt;Then People with a picture&lt;/li&gt;
		&lt;li&gt;Then People with a description&lt;/li&gt;
		&lt;li&gt;Then People with an address and phone number&lt;/li&gt;
		&lt;li&gt;And so on&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;What I ended up doing is adding a &#8220;priority&#8221; integer attribute to the Person model.  On a method that runs before the Person is saved, it figures out what attributes the Person has, and then assigns a priority number to the Person.  I gave a priority value of 10 to featured People with a picture, a priority value of 9 to a featured Person without a picture, and so on.  Indexed this column and whammo, the sorting works great, just add a &#8220;ORDER BY priority &lt;span class=&quot;caps&quot;&gt;DESC&lt;/span&gt;&#8221; &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; clause to your search statements.&lt;/p&gt;


	&lt;p&gt;Then it occurred to me when I was in the shower: &#8220;What happens if the rules change and People should be ordered differently?&#8221;  It&#8217;s happened twice so far, but it&#8217;s no problem since the application hasn&#8217;t launched yet.  I make the code change to the module (PersonRules, need a better name) and then run:&lt;/p&gt;


&lt;pre&gt;
Person.find(:all).each do |Person|
  Person.priority = PersonRules.generate_priority(Person)
  Person.save!
end
&lt;/pre&gt;

	&lt;p&gt;And that works.  Almost.&lt;/p&gt;


	&lt;p&gt;What happens if after you have loaded the Person objects in the find call and a user changes the name of Person while you&#8217;re looping through the People?&lt;/p&gt;


	&lt;p&gt;Prior to Rails 2.2, which I haven&#8217;t really upgraded to yet for most of my applications, that change would be overridden&lt;sup&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.  Say they update the name of the Person.  But the above code loop has already loaded the original Person object into memory and is going to be operating on that data&#8212;the priority for the original Person object (with the old name) will be updated and then saved.  So the user&#8217;s change to the Person name would be overwritten with the old name and new priority.&lt;/p&gt;


	&lt;p&gt;Ok, so you load the Person with &#8220;select for update&#8221; (I think in postgresql, don&#8217;t know if this syntax is what mysql uses).  You do this like:&lt;/p&gt;


&lt;pre&gt;
Person.find(:all).each do |Person|
  transaction do
    Person.lock!
    # now this bit of code is guaranteed to have an exclusive lock on the Person
    # if another bit of code is updating the Person at the same time, the database
    # will hang until it's done
    Person.priority = PersonRules.generate_priority(Person)
    Person.save!
  end
end
&lt;/pre&gt;

	&lt;p&gt;This should work, afaik.  I don&#8217;t like it though:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;You have to remember to lock the Person object whenever you do something like this.  &lt;/li&gt;
		&lt;li&gt;If generating the priority took a while, the Person object would be locked for a while.&lt;/li&gt;
		&lt;li&gt;It adds more code.&lt;/li&gt;
		&lt;li&gt;How do you test this?&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;There&#8217;s another way to do this, that&#8217;s using optimistic locking.  You add a lock_version column to your model.  That version number is updated every time the Person object is updated.  So in the above example, the Person object would be loaded with a lock_version of 10, then when the Person&#8217;s name is updated by another user, the lock_version would increment to 11, and then when the priority is generated and the original Person object is saved, ActiveRecord would notice that the lock_version value for the Person has been modified and would throw a nasty exception.&lt;/p&gt;


	&lt;p&gt;Now that works, except that you have to be aware of the possibility of the exception and rescue it if you don&#8217;t want the request to die a fiery death.  Now, in most circumstances, not rescuing it would work just fine, since this type of problem wouldn&#8217;t happen more often, and it&#8217;s better to crash and burn as opposed to have the possibility of bad data.  So there&#8217;s a case to be made for always adding a lock_version column to all of the models that have the remote possibility of concurrent updates.&lt;/p&gt;


	&lt;p&gt;But say you wanted something that didn&#8217;t require locking the Person object, or rescuing lock_version exceptions all the time.  I can think of a couple of options that &lt;em&gt;might&lt;/em&gt; work&#8212;I have not tried them out yet.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Add a version column to the Person model.  When the Person is updated, instead of updating the existing Person database row, insert a new one with the Person data and update the version number.  Then when you select the Person, add a &#8220;order by version desc&#8221;.  Problem with this approach is that any other objects that refer to the Person would need to be updated with the new Person id.  But it has the advantage of keeping old versions of People around, you could then easily rollback or provide &#8220;undo&#8221; functionality.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Add a new model: PersonPriority.  This would have two columns: person_id and priority.  When you want to update the priority of the Person, you don&#8217;t have to modify the Person itself, you can update this model.  Problem: extra table/model, and doing a sort on the Person would be more complex.  (Can you do this indexing with sphinx?)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;How do you handle concurrency in your applications?  Am I missing any approaches here?&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; I believe in Rails 2.2, Rails only updates the parts of models that change.  So if only the name field of a Person has been changed, when the object is saved, only the name field update is included in the generated &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; update statement.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2008-11-09:721</id>
    <published>2008-11-09T15:46:00Z</published>
    <updated>2008-11-16T05:51:14Z</updated>
    <link href="http://blog.fixieconsulting.com/2008/11/9/setting-up-ubuntu" rel="alternate" type="text/html"/>
    <title>Setting Up Ubuntu</title>
<summary type="html">&lt;p&gt;Although my preferred platform is &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; for personal stuff, I use Ubuntu Linux for work.  I do all my work in Ubuntu via VMware Fusion.&lt;/p&gt;


	&lt;p&gt;Great thing about Ubuntu is &lt;a href=&quot;http://www.debian.org/doc/manuals/apt-howto/ch1.en.html&quot;&gt;apt&lt;/a&gt;.  It makes setting up the machine for development really easy.  &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; has &lt;a href=&quot;http://www.macports.org&quot;&gt;Mac Ports&lt;/a&gt;, but imo apt is better.  Plus, working in a VM allows you to have multiple OS installs, allows you to backup your setup easily, you can take snapshots, and work on the same OS that you deploy your software to.&lt;/p&gt;


	&lt;p&gt;Read on to read my notes on how to setup Ubuntu for work.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Although my preferred platform is &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; for personal stuff, I use Ubuntu Linux for work.  I do all my work in Ubuntu via VMware Fusion.&lt;/p&gt;


	&lt;p&gt;Great thing about Ubuntu is &lt;a href=&quot;http://www.debian.org/doc/manuals/apt-howto/ch1.en.html&quot;&gt;apt&lt;/a&gt;.  It makes setting up the machine for development really easy.  &lt;span class=&quot;caps&quot;&gt;OS X&lt;/span&gt; has &lt;a href=&quot;http://www.macports.org&quot;&gt;Mac Ports&lt;/a&gt;, but imo apt is better.  Plus, working in a VM allows you to have multiple OS installs, allows you to backup your setup easily, you can take snapshots, and work on the same OS that you deploy your software to.&lt;/p&gt;


	&lt;p&gt;Read on to read my notes on how to setup Ubuntu for work.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Download Ubuntu 8.04 Server &lt;span class=&quot;caps&quot;&gt;ISO&lt;/span&gt; from from &lt;a href=&quot;http://mirrors.kernel.org/ubuntu-releases/8.04/ubuntu-8.04.1-server-i386.iso&quot;&gt;http://mirrors.kernel.org/ubuntu-releases/8.04/ubuntu-8.04.1-server-i386.iso&lt;/a&gt;.  &lt;/li&gt;
		&lt;li&gt;Purchase / install &lt;a href=&quot;http://www.vmware.com/products/fusion/&quot;&gt;VMware Fusion 2&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Create the VM, point the install disc to the downloaded Ubuntu &lt;span class=&quot;caps&quot;&gt;ISO&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Configure the VM, give it a lot of hard drive space.  It doesn&#8217;t use all the hard drive space, but you want it to think that it has access to as much space as it needs.  I gave it 50GB.&lt;/li&gt;
		&lt;li&gt;Start the VM, press enter a bunch of times.  Install process should be pretty easy.&lt;/li&gt;
		&lt;li&gt;I enter &#8220;localhost.com&#8221; as the hostname.  Read on to find out why.&lt;/li&gt;
		&lt;li&gt;When it asks you what software to install, pick OpenSSH, PostgreSQL, and Samba.&lt;/li&gt;
		&lt;li&gt;Reboot, login.&lt;/li&gt;
		&lt;li&gt;Type in: &lt;tt&gt; sudo apt-get update &lt;/tt&gt;  This will update the package information on your system.&lt;/li&gt;
		&lt;li&gt;Type in: &lt;tt&gt;sudo apt-get dist-upgrade &lt;/tt&gt; This will update all the software.&lt;/li&gt;
		&lt;li&gt;Install the software you work with.  For me, I type in the following:&lt;/li&gt;
	&lt;/ul&gt;


&lt;ul&gt;
	&lt;li&gt;Note the VM&#8217;s IP address by running &lt;tt&gt; ifconfig -a &lt;/tt&gt;.  For me, the IP address 192.168.206.128.  &lt;/li&gt;
		&lt;li&gt;Add this line to your &#8220;host&#8221; (i.e. the physical OS) /etc/hosts file: &lt;tt&gt; 192.168.206.128 localhost.com &lt;/tt&gt;.  This allows you you to use localhost.com as the name of the machine &#8211; you don&#8217;t have to remember the IP address.&lt;/li&gt;
		&lt;li&gt;See if you can ssh into localhost.com from your host machine.  Hopefully you can.&lt;/li&gt;
		&lt;li&gt;Install rubygems: &lt;tt&gt; curl http://rubyforge-files.ruby-forum.com/rubygems/rubygems-1.3.1.tgz | tar zxv &#38;&#38; cd rubygems-1.3.1 &#38;&#38; sudo ruby setup.rb  &#38;&#38; sudo ln -s /usr/bin/gem1.8 /usr/bin/gem&lt;/tt&gt;&lt;/li&gt;
		&lt;li&gt;Install any rubygems you work with.  I install haml, capistrano, hoe, mongrel, and webby.&lt;/li&gt;
		&lt;li&gt;Add yourself as a postgers user: &lt;tt&gt; sudo su postgres -c &#8220;createuser &lt;span class=&quot;caps&quot;&gt;YOUR&lt;/span&gt;_USER_NAME&#8221; &lt;/tt&gt;&lt;/li&gt;
		&lt;li&gt;Install the apache phusion software: &lt;tt&gt; sudo /usr/bin/passenger-install-apache2-module &lt;/tt&gt;&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2008-11-09:717</id>
    <published>2008-11-09T15:02:00Z</published>
    <updated>2008-11-09T21:01:37Z</updated>
    <link href="http://blog.fixieconsulting.com/2008/11/9/enterprise-rails" rel="alternate" type="text/html"/>
    <title>Enterprise Rails</title>
<content type="html">
            &lt;p&gt;I recently picked up the book &lt;a href=&quot;http://www.amazon.com/gp/product/0596515200?ie=UTF8&amp;amp;#38;tag=whatisbestinl-20&amp;amp;#38;linkCode=as2&amp;amp;#38;camp=1789&amp;amp;#38;creative=390957&amp;amp;#38;creativeASIN=0596515200&quot;&gt;Enterprise Rails&lt;/a&gt; by Dan Chak.&lt;/p&gt;


	&lt;p&gt;it&#8217;s an excellent book, and was sorely needed by me.  The biggest thing for me was that it explains how to use a good (i.e. &lt;a href=&quot;http://www.postgresql.org/&quot;&gt;PostgreSQL&lt;/a&gt;) database effectively and shows how to use materialized views, triggers, and so forth in a Rails application.&lt;/p&gt;


	&lt;p&gt;It also delves into how to organize a large Rails application, separating your models into modules and then into standalone services.  Afaik, no other book shows how to do this sort of stuff.&lt;/p&gt;


	&lt;p&gt;We&#8217;re looking to apply it to this site.  (note: not all the tests are counted, since &#8220;rake stats&#8221; only shows the specs, not the &#8220;historical&#8221; tests in the tests directory)&lt;/p&gt;


&lt;pre&gt;
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Libraries            |  1301 |  1003 |      24 |     168 |   7 |     3 |
| Models               |  6112 |  4927 |     110 |     757 |   6 |     4 |
| Helpers              |  1836 |  1575 |       0 |     176 |   0 |     6 |
| Controllers          |  4342 |  3696 |      90 |     478 |   5 |     5 |
| Model specs          |  2915 |  2417 |       2 |       9 |   4 |   266 |
| View specs           |   370 |   301 |       0 |       1 |   0 |   299 |
| Controller specs     |  1307 |  1043 |       0 |       4 |   0 |   258 |
| Helper specs         |   432 |   286 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                | 18615 | 15248 |     226 |    1593 |   7 |     7 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 11201     Test LOC: 4047     Code to Test Ratio: 1:0.4

&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2008-08-23:718</id>
    <published>2008-08-23T15:23:00Z</published>
    <updated>2008-11-09T15:23:27Z</updated>
    <link href="http://blog.fixieconsulting.com/2008/8/23/how-to-dynamically-create-activerecord-classes" rel="alternate" type="text/html"/>
    <title>How To Dynamically Create ActiveRecord Classes</title>
<content type="html">
            &lt;p&gt;A question came up on &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; on someone commenting on how it was a pain to have a file for each ActiveRecord class if they were all really simple and basically the same.  I cooked up the following code for him.&lt;/p&gt;


&lt;p&gt;So, in your environment file (or some other appropriate place), you can create these classes with just one line of code per class.  Of course, the method that creates the class can get more complicated &lt;del&gt;- you could pass in options if the classes needed to differ from each other.  This is a really simple example of the power of metaprogramming -&lt;/del&gt; writing code that writes code.&lt;/p&gt;


	&lt;p&gt;Quite helpful if you don&#8217;t want to repeat yourself all the time.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2008-07-31:719</id>
    <published>2008-07-31T15:23:00Z</published>
    <updated>2008-11-09T15:25:55Z</updated>
    <link href="http://blog.fixieconsulting.com/2008/7/31/advertising-for-useful-things" rel="alternate" type="text/html"/>
    <title>Advertising for useful things</title>
<content type="html">
            &lt;p&gt;Software that we as a small web consulting company can not live without:&lt;/p&gt;


&lt;ul&gt;
    &lt;li&gt;For keeping track of our tasks, we use &lt;a href=&quot;http://pivotaltracker.com&quot;&gt;Pivotal Tracker&lt;/a&gt;.  The estimation and prioritizing features are what makes it work well for us.  And it&#8217;s free for now!&lt;/li&gt;
    &lt;li&gt;To make and share documents and spreadsheets, &lt;a href=&quot;http://docs.google.com&quot;&gt;Google Docs&lt;/a&gt; does the trick.&amp;lt;!&lt;del&gt;-more&lt;/del&gt;-&amp;gt;&lt;/li&gt;
    &lt;li&gt;For email, good old &lt;a href=&quot;http://www.google.com/a/&quot;&gt;Google Apps&lt;/a&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://tickspot.com&quot;&gt;Tickspot&lt;/a&gt; lets us keep track of time spent on each client.&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://highrisehq.com&quot;&gt;Highrise&lt;/a&gt; keeps track of people that we know and what&#8217;s new with them.&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; keeps our websites and software running.  I love how they handle so much of the system administration work that I would otherwise have to do.&lt;/li&gt;
    &lt;li&gt;For remote communication, &lt;a href=&quot;http://www.adiumx.com/&quot;&gt;Adium&lt;/a&gt; rocks.  It&#8217;s a perfect instant messaging client.  Well, not quite perfect.  It needs to do video.&lt;/li&gt;
    &lt;li&gt;For editing/programming, Jordan uses &lt;a href=&quot;http://macromates.com/&quot;&gt;TextMate&lt;/a&gt;, Joe uses &lt;a href=&quot;http://www.vim.org/&quot;&gt;vim&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://blog.fixieconsulting.com/">
    <author>
      <name>joe</name>
    </author>
    <id>tag:blog.fixieconsulting.com,2008-07-30:720</id>
    <published>2008-07-30T15:24:00Z</published>
    <updated>2008-11-09T15:25:14Z</updated>
    <link href="http://blog.fixieconsulting.com/2008/7/30/starling-and-facebook" rel="alternate" type="text/html"/>
    <title>Starling and Facebook</title>
<summary type="html">&lt;p&gt;It&#8217;s really important to make sure that your Rails controllers complete their actions quickly.  If you have some code in their that takes a while to execute (say, a remote network call), you need to have that stuff done in a different process or thread.&lt;/p&gt;


	&lt;p&gt;For &lt;a href=&quot;http://apps.facebook.com/dailycaption&quot;&gt;Daily Caption&lt;/a&gt;, we use &lt;a href=&quot;http://http://rubyforge.org/projects/starling/&quot;&gt;Starling&lt;/a&gt; to queue up messages that need to get sent to Facebook.  Another program, creatively called &#8220;facebook_daemon&#8221; watches the Starling queue.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;It&#8217;s really important to make sure that your Rails controllers complete their actions quickly.  If you have some code in their that takes a while to execute (say, a remote network call), you need to have that stuff done in a different process or thread.&lt;/p&gt;


	&lt;p&gt;For &lt;a href=&quot;http://apps.facebook.com/dailycaption&quot;&gt;Daily Caption&lt;/a&gt;, we use &lt;a href=&quot;http://http://rubyforge.org/projects/starling/&quot;&gt;Starling&lt;/a&gt; to queue up messages that need to get sent to Facebook.  Another program, creatively called &#8220;facebook_daemon&#8221; watches the Starling queue.&lt;/p&gt;
&lt;p&gt;So, you&#8217;ll want to install starling and memcached in the usual fashion.&lt;/p&gt;


Then, in &lt;tt&gt;config/initializers/starling.rb&lt;/tt&gt;, put:
&lt;pre&gt;
ports = { 'production' =&amp;gt; &quot;memcache-server:22122&quot;, &quot;development&quot; =&amp;gt; &quot;localhost:22122&quot;, &quot;test&quot; =&amp;gt; &quot;localhost:22122&quot; }
STARLING = MemCache.new(ports[RAILS_ENV])
&lt;/pre&gt;

To add stuff to the Starling queue, you can do stuff like:
&lt;pre&gt;
STARLING.set &quot;key-of-some-sort&quot;, &quot;value&quot; 
&lt;/pre&gt;

In our FacebookPublisher model, we have the following method:
&lt;pre&gt;
class FacebookPublisher &amp;gt; Facebooker::Rails::Publisher
  def self.queue action, args
    STARLING.set &quot;facebook_actions&quot;, [action, *args]
  end
  # and more
&lt;/pre&gt;

If we need to update Facebook, say, with a updated comment notification, the following code does the trick:
&lt;pre&gt;
FacebookPublisher.queue(:deliver_notify_caption_comment, self.caption, self)
&lt;/pre&gt;

	&lt;p&gt;This adds, to the key &#8220;facebook_actions&#8221;, an array that looks like this: &lt;tt&gt; [:deliver_notify_caption_comment, [self.caption, self]]&lt;/tt&gt;&lt;/p&gt;


	&lt;p&gt;You following?  At this point, we have that array stored in Starling.  Now, it&#8217;s up to another program to monitor Starling and pop messages off its queue.&lt;/p&gt;


&lt;pre&gt;
#!/usr/bin/env ruby
require 'rubygems'
require 'daemons'
require File.dirname(__FILE__) + &quot;/../config/environment&quot; 

class FacebookDaemon
  TIMEOUT = 5

  def self.do_publisher_things args
    puts &quot;Running FB publisher&quot; 
    puts args.inspect
    action = args.first
    args = args[1..-1]
    Timeout.timeout(TIMEOUT) { FacebookPublisher.send action, *args}
  end

  def self.do_profile_updates args
    puts &quot;Doing profile update&quot; 
    puts args.inspect
    user, fb_user, content = args
    Timeout.timeout(TIMEOUT) { fb_user.profile_fbml = content }
    Timeout.timeout(TIMEOUT) { user.update_friends! }
  end

  def self.update
    begin
      while fetch = STARLING.get(&quot;facebook_actions&quot;)         
        do_publisher_things(fetch) 
      end
      while fetch = STARLING.get(&quot;facebook_profile_update&quot;) 
        do_profile_updates(fetch)  
      end
    rescue StandardError =&amp;gt; e
      puts &quot;**** EXCEPTION!!! fetch = #{ fetch.inspect } *** &quot; 
      puts e
      puts e.backtrace.inspect
    end
  end
end

ActiveRecord::Base.logger = Logger.new STDOUT

options = {
  :app_name =&amp;gt; &quot;facebook_daemon&quot;,
  :ARGV =&amp;gt; ARGV,
  :dir_mode =&amp;gt; :normal,
  :dir =&amp;gt; File.expand_path(File.dirname(__FILE__) + '/../log'),
  :multiple =&amp;gt; false,
  :backtrace =&amp;gt; true,
  :monitor =&amp;gt; false
}

Daemons.run_proc(&quot;facebook_daemon&quot;, options) do
  loop do
    FacebookDaemon.update
    sleep 1
  end
end
&lt;/pre&gt;

	&lt;p&gt;It&#8217;s pretty straightforward stuff, &lt;tt&gt;FacebookDaemon.update&lt;/tt&gt; is called once a second.  The &lt;tt&gt;update&lt;/tt&gt; method pops stuff off the Starling queue, and then calls &lt;tt&gt;do_publisher_things&lt;/tt&gt; with whatever array was stored.  &lt;tt&gt;do_publisher_things&lt;/tt&gt; knows that the method is the first thing in the array, so calls that method.  Hence, &lt;tt&gt;FacebookPublisher.deliver_notify_caption_comment&lt;/tt&gt; (or whatever is on the queue to be called) is called, and Facebook gets sent the call.&lt;/p&gt;


	&lt;p&gt;If you keep the slow code out of the Rails request cycle, everyone will be happy.  I&#8217;ve outlined one strategy, but there are more.  We also use &lt;a href=&quot;http://codeforpeople.rubyforge.org/svn/bj/trunk/README&quot;&gt;BackgroundJob&lt;/a&gt; to move slow stuff out of the cycle.&lt;/p&gt;
          </content>  </entry>
</feed>
