Upgrading from Ruby 1.8.7 to 1.9.2 on AppCloud

  • ruby 1.8.7
  • ruby 1.9.2
  • mikel lindsaar
  • rubyx
  • rubyx sentinel

    Ruby 1.9.2 is now publicly available to all Engine Yard AppCloud customers. To celebrate Ruby 1.9.2 availability, our friend and partner Mikel Lindsaar pulled together an awesome guest post about his experience upgrading from Ruby 1.8.7 to Ruby 1.9.2. Mikel heads up rubyx where him and the rubyx team work to provide maintenance services, stack upgrades, code inspection and green field development for many AppCloud clients.

###Speed Demon - Ruby 1.9.2 At rubyx we recently performed a Ruby 1.8.7 to Ruby 1.9.2 upgrade for one of our clients, AgenciesHQ.

AgenciesHQ uses Engine Yard AppCloud to host their application and made use of the rubyx Sentinel service to perform a Rails 3 and Ruby 1.9.2 upgrade.

The results were impressive. Here is the screen shot of one of the New Relic performance graphs (lower is better):

The upgrade was completed on the 25th of January and pushed into production. As you can see the response time dramatically improved from the 450ms - 550ms range, down to a 275ms - 325ms range, about a 40% improvement.

Additionally, upgrading to Ruby 1.9.2 also produced a big increase in the Apdex score (higher is better) as can be seen here:

Note, statistically these graphs are just pretty pictures. I am very aware that this is by no means an exhaustive statistical comparison of Ruby 1.8.7 and Ruby 1.9.2, but the change is significant enough to be obvious.

While the graphs only show one month prior to the 1.9.2 update, I can assure you the previous months were just as bad, if not worse, as we had been incrementally updating the application code to be more efficient over the months.

We also updated the AgenciesHQ application from Rails 2.3 to Rails 3.0. This was done before the 1.8.7 to 1.9.2 update and we did not save graphs for this as the performance change was negligible. So there is no “performance” excuse not to upgrade from a Rails 2.3 stack to a Rails 3.0 one.

###How to perform the upgrade to 1.9.2

Preparation

There are three important steps I believe you should have done before you attempt a Ruby 1.9.2 upgrade on your Rails stack. These are only recommended steps and are by no means mandatory, but they will save you time in the long run.

First off, upgrading your stack to a new version can always present unexpected problems. So before doing this, it is always a great idea to invest some hours in polishing up your test/spec suite and cucumber features or other integration tests that you have been putting off for a rainy day.

Secondly, if your application is not using a Gemfile for its gem dependency management, now is a good time to do this. Handling gem version problems during a 1.9.2 upgrade becomes trivial with a Gemfile. You’ll also need to update your Gemfile to the mysql2 gem. When you create/rebuild your environment with Ruby 1.9.2 you will have an updated database.yml generated that requires the mysql2 adapter.

Third, upgrade your app to Rails 3.0. While this is not strictly needed as the latest Rails 2.3 version runs fine on 1.9.2, the same can’t be said for all the dependent gems you might have in your application.

Gems that have been upgraded to run with Rails 3.0 are more likely to also be compatible with Ruby 1.9.2 than say, a gem you installed when your app was running rails 2.3.0. At the very least, if you can’t upgrade to 3.0 yet, update your Rails app to the most recent version of Rails 2.3, and go through your Gemfile and upgrade your gems to the most recent versions you can that still support Rails 2.3.

With these three steps done, you are now ready to test your app’s 1.9.2 support. We recommend doing this in a feature branch in your Git repository, as it can take a while and you don’t want to halt production bug fixes because your master branch is broken in various states of upgrades. Once you have your feature branch, updating to 1.9.2 is quite trivial if you have RVM installed. It can be as simple as:

$ rvm install ruby-1.9.2-p136
$ cd path/to/app
$ rvm ruby-1.9.2-p136
$ rvm use 1.9.2-p136@your_app_name --create
$ bundle install

Once your gems are all installed, go ahead and run your test suites. Unless you are insanely lucky, you WILL have failures, there have been a few syntax updates and deprecations in 1.9.2.

Some examples of changes that we ran into during the AgenciesHQ upgrade were:

  • FasterCSV is now just called CSV in Ruby 1.9.2
  • You need to make sure that your Gemfile specifies that the ruby-debug19 gem is available in both the test and development environments by specifying it using group :test, :development in the Gemfile
  • 1.9.2 doesn’t support the use of a : in a when clause of a case statement any more
  • Hash#key has been removed and replaced with Hash#index
  • The {:key, :value} format for Hash is no longer allowed

These were the changes that hit us on this one upgrade. Yours will most likely be different. A good summary of Ruby 1.9 changes was done by Sam Ruby, this is a great place to start, as well as this 1.9.2 Tips post.

With your test suite running on Ruby 1.9.2, we are ready to try it out live, push the feature branch up your Git repository.

Testing on AppCloud

So getting this working in your environment does not have to mean hours of down time. Especially if you are on Engine Yard AppCloud. The way we go about doing it is using the AppCloud clone environment service.

First, login to the AppCloud console and perform the following:

  1. Follow “More Options” on the application you want to upgrade.
  2. Follow the “Clone Environment” option. If this doesn’t show up, do a snapshot.
  3. Call the cloned environment “your_app_production_1_9_2”.
  4. Let the cloned environment boot, it should come up green and ready to serve.
  5. Go to More Options in the “your_app_production_1_9_2” environment and follow “Edit Environment”.
  6. Go to “Show advanced options”.
  7. Change the Ruby version to Ruby 1.9.2.
  8. Press the “Update Environment” button.

Now we have the “your_app_production_1_9_2” setup to test. However, this may or may not boot at the moment as we will be running on your old pre 1.9.2 upgrade code. So in the “your_app_production_1_9_2” environment, follow the “Applications” button and put the name of your 1.9.2 feature branch into the Ref box and press Deploy.

Your app should now deploy with the latest code on 1.9.2 and should be ready to test.

Some debug hints if this doesn’t work:

  1. Look through the custom log and base log as to reasons why you could be getting failures. These usually provide a descriptive error log.
  2. Try re-uploading your custom chef recipes to the cloned environment. These should already be there, but sometimes this can help, do this with the ey recipes upload and ey recipes apply commands.
  3. Contact your support team to get them to help debug the problem.

Once your app is running on Ruby 1.9.2 in the test environment, get some of your users to log into the test environment and have a play around, make sure you tell them though that it is a copy and all data they enter will be lost!

Get feedback and fix any changes, it is important that you really try all key features of your app — especially ones that depend on external gems or systems like image processing, s3 storage and the like.

Once you are happy with all of this, it is time to go live.

Deployment

__Once you have a working system in the test environment, it is time to schedule a downtime for your users and go live.

The broad steps are:

  1. Take your apps off line ey web disable will do this for you.
  2. Take a backup of the database. (Just to be safe!)
  3. Snapshot the environment within the Engine Yard AppCloud interface, by following the “Snapshot” button in the production environment pane.
  4. Once the snap shot is complete, follow “More Options” and follow “Edit Environment”.
  5. Go to “Show advanced options”.
  6. Change the Ruby version to Ruby 1.9.2.
  7. Press the “Update Environment” button.
  8. Once the environment has updated (remember, it may not go green as you are still running on the old code base) go to the “applications” tab and change the Ref to be the 1.9.2 branch then click deploy.
  9. Let the environment deploy and you should be green.
  10. Re enable the site and check to make sure everything is working fine.

After you are happy with the deployment and know you will not be rolling back, merge your 1.9.2 feature branch back into your production or master branch, push to your git repository and then during another maintenance window, go into the Application pane of your production environment and change the Ref back to master and click Deploy again.

At any point if things really break, you can change the environment back to Ruby 1.8.7, JRuby or Ruby Enterprise Edition in the Edit Environment pane and set your Ref back to master and deploy. This will put you back to where you started.

And if all else fails, you can restore from the Snapshot you took before you started. ###Summary So this is good news. While there have been a lot of posts about the speed increase that Ruby 1.9.2 brings, it is also good to see what happens on a real world application and how safe this can be to experiment with on Engine Yard AppCloud.

For further information or help with your application, get in touch with us at rubyx or see our site for more information on the services we offer to upgrade your application to Rails 3 or Ruby 1.9.2.

You can also review the Using Ruby 1.9.2 with Engine Yard AppCloud docs for instructions.