Thursday, March 15, 2012

Make scheduled jobs in heroku safer for your wallet.

I recently checked my current usage on Heroku to find that I had used a much higher than expected number of dyno-hours. The project CheckTheSock.com is a RC aviation website that provides some weather data. The forecast data is pulled every hour via FTP by a rake task that is run with a scheduled job in Heroku. Normally this takes around a minute to run and uses about 13 or 14 dyno-hours in a month. Less than half way through this month I found that it had already burned through over 200 dyno-hours.

After digging into the problem I found that the FTP connection was hanging for some reason. After a little research I came up with a solution that works pretty nicely and for more than just hanging FTP connections.

It turns out that ruby's standard library includes a library named Timeout which provides a way to terminate the execution of a thread. Using this library it is very simple to set a time limit for a block of code in a rake test.

task :task_that_takes_a_long_time_sometimes do
  Timeout.timeout(30) do
    #The code that takes a long time to run sometimes
  end
end

That will raise a Timeout::Error if the code takes longer than 30 seconds to run. The error will cause the rake task to exit, preventing unexpected dyno-hour usage.

Wednesday, February 29, 2012

Rails A/B testing with Split on Heroku

I recently decided to start doing some A/B testing on www.checkthesock.com. The last time I tried A/B testing I used Google website optimizer, it worked fairly well but I did not like how difficult it was to setup a test. This time I looked around for A/B testing tools for rails. I ended up finding split and so far I have been very happy with the results. The documentation is fairly good but it did take a little fiddling to get it working on Heroku.

First off add the Redis to Go add-on in Heroku, the Nano plan is free and has been sufficient for my needs so far. Install redis on the dev server. I use a mac so that was as simple as "brew install redis" and then I followed the brew instructions for getting redis to start on login.

To install the split gem add the following to the Gemfile

 gem 'split', '0.3.3', :require => 'split/dashboard'

To set the development environment up in a way that is compatible to how Redis to Go is configured on Heroku add the following to config/environments/development.rb

ENV['REDISTOGO_URL'] = 'redis://localhost:6379'
Then create an initializer for redis in config/initializers/redis.rb and put the following in that file.
uri = URI.parse(ENV['REDISTOGO_URL'])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :username => uri.user)
To configure split to use the applications redis configuration create config/initializers/split.rb and add the following.
Split.redis = REDIS

To setup the split dashboard add the following to config/routes.rb

mount Split::Dashboard, :at => 'split'
To add authentication to the dashboard add the following to config/initializers/split.rb
Split::Dashboard.use Rack::Auth::Basic do |username, password|
  username == 'username' && password == 'password'
end

Setting up an A/B test is super easy just follow the instructions in the split README.

Resources:

Note: These instructions are for rails 3.x, the listed resources do have instructions for earlier versions of rails.

Friday, February 3, 2012

Testing to ensure code gets cleaned up.

The other day I was working on a change on www.checkthesock.com that involved getting rid of some pages. It is generally a good idea to redirect those URL's to a relevant location so that search engines and people can get to a useful location. Eventually no one uses the old URL anymore and whatever code is redirecting it is just sitting around gathering dust.

I wanted to make sure I eventually cleaned up the code I had doing the redirection. In the past I have tried several different ways of remembering to do this; try to remember, put a note somewhere, or put a reminder in my calendar. None of those have ever ended up working out. None of those methods involve anything that is part of my normal working process.

The solution I came up with was to write a test that checks to see if the code is still around at some future date. I run my tests all the time as part of my normal workflow and I never release code without fixing a broken test. Now at some future point in time the test will break and I will not forget to clean up my unused code. Seems like a potentially useful pattern. In a few months, when my tests start breaking to remind me to clean stuff up, I will discover if it is useful or just really annoying.

Monday, January 23, 2012

Rails 3.2 development environment asset issue

I just tracked down and dealt with an issue I was having after upgrading www.checkthesock.com to rails 3.2. After the upgrade assets (css, javascript) were not updating unless I restarted the server process. Took me a while to track down the issue but I finally tracked it down to asset fingerprinting. Asset fingerprinting is off by default in the development environment but I had turned it on to debug an issue a long time ago.

If you are having similar problems make sure that you have the following line in "config/environments/development.rb"

  config.assets.digest = false

Friday, January 20, 2012

Rails 3.2 on Heroku asset:precompile issue

I just upgraded www.checkthesock.com to Rails 3.2 and found that the asset precompile step of the release was not working properly.

Here is the output I was getting:

-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       could not connect to server: Connection refused
       Is the server running on host "127.0.0.1" and accepting
       TCP/IP connections on port 5432?
       
       Tasks: TOP => environment
       (See full trace by running task with --trace)
       Precompiling assets failed, enabling runtime asset compilation
       Injecting rails31_enable_runtime_asset_compilation

The issue was rails was trying to connect to the database during the precompile process, and heroku is setup not to allow that. I am guessing that this issue is due to a change in the rails initialization setup in rails 3.2.

It turns out that the fix for this is very simple as long as you don't actually need to connect to the database during asset precompiling. All you need to do is add the following line to 'config/application.rb'

config.assets.initialize_on_precompile = false

Additional Resources

Monday, November 21, 2011

rescue_from temporary fix for rails 3.0 and 3.1

In rails 3.0 and 3.1 rescue_from will not successfully rescue a ActionController::RoutingError (Bug Report). Based on comments in the bug report here is the solution I came up with. A way that handles this bug temporarily and once it is fixed all that needs to be cleaned up is a single line in the routes.

First set up a simple errors controller:
class ErrorsController < ApplicationController
  def missing_page
   render :status => :not_found
  end
end

The view for missing_page is intended to be shown to visitors as the 404 page, it uses the application layout as set up here but you can set :layout to false or whatever other layout you might wish to use.
In the application controller add the following lines:
rescue_from ActiveRecord::RecordNotFound, :with => :missing_page
rescue_from ActionController::UnknownAction, :with => :missing_page
rescue_from ActionController::RoutingError, :with => :missing_page
The first two lines work as expected, the line with ActionController::RoutingError does not work correctly though, it will start working once the bug is fixed.

The temporary fix for routing errors not being handled properly is to add the following line as the last route in the route file.
match '*path', :to => 'errors#missing_page'

Once the bug is fixed all you need to do to clean this up is remove the line that was placed at the end of the route file.

Thursday, September 8, 2011

Rails Code QA Update

I just released an updated version of Rails Code QA which now supports rails 3.0 and 3.1 as well as ruby 1.8.x and ruby 1.9.x


Installation
If you are using ruby 1.8.x all you need to do to install rails_code_qa in your rails 3.x app is add the following line to your Gemfile.
gem "rails_code_qa"


If you are using ruby 1.9.x you will also need to add the following to your test/test_helper.rb file
require 'simplecov'
SimpleCov.start 'rails'


Code Coverage
Rails Code QA takes care of picking which code coverage tool to use based on the version of ruby you are using. If you are using ruby 1.8.x code coverage is calculated using rcov and if you are using ruby 1.9.x coverage is calculated using simplecov.

Static Code Analysis
Rails Code QA also runs flog and flay to help you find other issues in your apps code.


Resources