Rider Jones

July 8th, 2006

Check out Rider Jones out of Vancouver.

There’s a lot of garbage on MySpace to wade through some times but once in a while you come across some great music. I think their MySpace page is burned into my screen at this point. Can’t wait until I get the EP’s.

WhatMyFriendsLike.com

July 6th, 2006

In addition to MySpace Maps I also created WhatMyFriendsLike.com

It lets you create a ranked list of all the music, movies and books your MySpace friends like.

This one was also written entirely in Ruby on Rails sharing most of the code with MySpace Maps.

Just to follow up on my last post about using RailsCron.

If you want to run multiple instances of RailsCron you need to change the startup tasks in the rake file.

In my particular case I wanted a separate instance running for each of the sites that required it. I’m running them all as Daemons so I changed the cron_start target in my rake file.

From the root of of your app edit the rake file:
vi vendor/plugins/trunk/tasks/startup.rake
Change
desc "Starts RailsCron as a daemon"
task :cron_start do
  if `#{sudo "ps x | grep RailsCron | grep -v grep"}`.strip.blank?
    mode = ENV['RAILS_ENV'] || "development"
    puts `#{sudo "nohup ruby script/runner -e #{mode} \"RailsCron.start\" > /dev/null 2>&1 &"}`
  else
    puts "RailsCron already started"
  end
end
To the following:
desc "Starts RailsCron as a daemon"
task :cron_start do
    mode = ENV['RAILS_ENV'] || "development"
    puts `#{sudo "nohup ruby script/runner -e #{mode} \"RailsCron.start\" > /dev/null 2>&1 &"}`
end

This removes the check for an existing RailsCron process and lets you start a new one. Be careful.

Now you can run rake cron_start from the root of each app that requires a RailsCron instance. Running rake cron_stop will stop all the RailsCron processes so you’ll have to start each one up again.

MySpace Maps

July 5th, 2006


I just finished up this little site that maps all your MySpace friends using Google Maps. For those interested the app is written entirely in Ruby on Rails. The maps are rendered using Google Maps and the Geocoding is done through Yahoo.

I’ll probably be adding support for Yahoo Maps when I have some time.

If you have suggestions, problems, or would just like to discuss the application feel free to comment here.

I recently started using Kyle Maxwell’s RailsCron for a couple Ruby on Rails apps I’ve been playing with. Cron turned out to be a headache in my case and I wanted ActiveRecord support without having to jump through any hoops.

Some of the shortcomings of Cron with RoR (from the RailsCron readme):
  • Significant startup resources required
  • Lots of RAM to run simultaneous processes
  • Hard to start/stop/affect the background processes from within Rails.

The documentation is sparse and there are very few examples to be found online.

This is straight from the readme:
RailsCron.create(
      :command => "Object.do_something()", 
      :start => 2.minutes.from_now,
      :every => 12.hours,               # default: 1.day 
      :finish => 2.years.from_now       # optional
    )

    RailsCron.destroy_all
    RailsCron.find_by_command "some_command"
There are a couple ways to install. Here’s what I did. From the root of your rails app run:
./script/plugin install  http://svn.kylemaxwell.com/rails_cron/trunk
I set it up to run in the background. In my model I put the following:
class User < ActiveRecord::Base
  background :update_accounts, :every => 1.minute, :concurrent => false    

  def self.update_accounts
    # do some scheduled processing
  end  
end

The above will run the update_accounts method every minute. You can set it up so that it can run separate threads concurrently if it’s still working on the old one. It didn’t make sense in my case so I used :concurrent => false.

It has the following set of rake tasks:
  • cron_start—Starts RailsCron as a daemon
  • cron_foreground—Starts RailsCron in the foreground
  • cron_stop—Graceful stop
  • cron_kill
  • cron_graceful—Graceful restart
  • cron_status

For example to stop then restart RailsCron you can run the following:

rake cron_graceful
That’s it. It should create a table in your database to keep track of the tasks.

HTTP get Timeout

July 3rd, 2006

One of my apps does quite a few http requests (using Net::HTTP.get) for pages from another site.

I kept running into timeout problems that I initially assumed were http timeouts since it took up to 5 minutes to run sometimes. After banging my head against it for a while I finally came up with a solution for handling slow responding or non-responsive websites. Basically it catches the timeout error and reattempts the request. In my case I don’t care about the exception raised except to make a new request, but you might want to keep track of it and raise it at the end to do something with it.

# retrieve a page
  def self.get_page(url)
    retrycount = 0
    resp = nil
    begin
      timeout(60) do
        resp = Net::HTTP.get(URI.parse(url))    
        resp.to_s    
      end
    rescue TimeoutError      
      if(retrycount < 5)
        retrycount+=1
        retry
      else
        logger.info("ERROR url: " + url)
        logger.info("ERROR Timeout error in get_page, attempt #" + retrycount.to_s)
        nil
      end
    end
    resp.to_s    
  rescue Exception => exception
    logger.info("ERROR Unknown error in get_page")
    logger.info(exception.class.to_s + " " + exception.message.to_s + " " + exception.backtrace.to_s) 
    nil
  end

This example will retry 5 times before giving up but you can change yours to attempt retries for specific cases.