Looper - Dead-simple Ruby daemons

Looper is a simple Ruby module for running a piece of code like a daemon. No forking involved, no detaching from the terminal, simply running a nice healthy loop, but allowing your code to bail out of it, and making it responsive to signals.

Check out the initial blog post for more background.

Looper on Github

Installation

   
  % gem sources -a http://gems.github.com
  % sudo gem install billymeltdown-looper

How It Works:

You implement a class like “DoSomething” that checks for new message objects and then does something to them. This class will include Looper in order to easily loop, respond to shutdown signals, and it can then be run via script/runner as a daemon.

The loop handles sleeping between runs, and will catch any unhandled exceptions that bubble up and keep on truckin’. Thus, if you want to exit on a particular exception, you’ve got to rescue it in your code and call exit_loop.

Here’s an example to illustrate:

require 'looper'

class DoSomething
  include Looper

  attr_accessor :run

  def initialize(config)
    @run = true
    # do config stuff, etc...
    @sleep = config[:sleep].nil? ? 60 : config[:sleep]
  end # initialize

  def run
    loopme(@sleep) do
      begin
        # this is where the meat of your code goes...
        messages = twitter.direct_messages({:since => since.strftime("%a, %d %b %Y %H:%M:%S %Z")})
      rescue Twitter::EpicFailure => e
        puts "bailing out, dude!"
        exit_loop
      end
    end
  end
end

# and here's how we kick it off:
DoSomething.new( { :sleep => 10 } ).run

Now we can just kick that off any way we like and background the process, but we tend to use it with script/runner in our Rails environments to have access to our models and such. It boils down to:

@$ nohup script/runner -e RAILS_ENV /path/to/DoSomething.rb

And then looking up the PID by matching on /path/to/DoSomething.rb via grep and use kill to send the term signal.