Rider Jones
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
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.
Multiple RailsCron Instances
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
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" endenddesc "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 &"}`endThis 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
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.
Installing and Using RailsCron
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"
./script/plugin install http://svn.kylemaxwell.com/rails_cron/trunk
class User < ActiveRecord::Base background :update_accounts, :every => 1.minute, :concurrent => false def self.update_accounts # do some scheduled processing endend
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
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 endThis example will retry 5 times before giving up but you can change yours to attempt retries for specific cases.
