27/08/2010

Rails3 on joyent shared (rvm way) - Followup

In my last post I wrote about installing rails3 on ruby 1.8.7 on a joyent shared accelerator. After finishing up my install an restarting my new app/toy/site I noticed a couple things.

On Ruby versions

Ruby 1.8.7 works whether its p299 or p302, the thing that fails is net-ssh with it's weird relocation error.

Ruby 1.9.x doesnt compile, period.

On deploying the production environment


Joyent recommends 2 ways of setting up a production environment on its shared environment:
  • using mongrel
  • using lighttpd
Now, I played with lighttpd back in v2.x, and found it hard to keep running, si I wanted to try mongrel.

Plainly put, I am out of luck: mongrel even 1.2.0pre doesn't work well with rails3. it seems it integrates at a low level in the core rails stack. Except that there were massive changes in the rails3 stack with the inclusion of rack as the core of the stack. As a result some file/class called "dispatcher" is missing and trying the normal mongrel_rails start command just fails with the error shown below:
jean@xps:~/dev/rails/giftr$ mongrel_rails start
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
/home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:239:in `require': no such file to load -- dispatcher (LoadError)
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:239:in `block in require'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:225:in `block in load_dependency'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:591:in `new_constants_in'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:225:in `load_dependency'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0.rc2/lib/active_support/dependencies.rb:239:in `require'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/rails.rb:148:in `rails'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/bin/mongrel_rails:116:in `block (2 levels) in run'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/configurator.rb:149:in `call'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/configurator.rb:149:in `listener'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/bin/mongrel_rails:102:in `block in run'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/configurator.rb:50:in `call'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/configurator.rb:50:in `initialize'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/bin/mongrel_rails:86:in `new'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/bin/mongrel_rails:86:in `run'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/lib/mongrel/command.rb:210:in `run'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/gems/mongrel-1.2.0.pre2/bin/mongrel_rails:282:in `<top (required)>'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/bin/mongrel_rails:19:in `load'
 from /home/jean/.rvm/gems/ruby-1.9.2-p0/bin/mongrel_rails:19:in `<main>'
This problem is not joyent specific though (and the captured output comes from my dev station hence the ruby 1.9.x, but I have the exact same stack trace on the joyent shared.

Since mongrel is trying to keep backward compatibility with all versions of rails we are in a tight spot. Defects already exist about this in both rails and mongrel, but no solution in sight for the moment (and this is way over my head for now) :
At the same time, using rails server works like a charm starting up mongrel. I am not sure what the difference is to be honnest.

The deploy solution which works for me

In the meantime, starting rails server seems to work fine.Therefore, here is what I did, found a stop script somewhere on the net (sorry I don't remember where) which works fine:
#!/usr/bin/env bash 
EXPECTED_ARGS=1
E_BADARGS=65

if [ $# -ne $EXPECTED_ARGS ]
then
  echo "Usage: `basename $0` {pid_file}"
  exit $E_BADARGS
fi

if [ -f $1 ]
then
  cp $1 $1.stopping
  cat $1 | xargs kill
  mv $1.stopping $1.stopped 
else
  echo "Usage: `basename $0` {pid_file}"
  exit $E_BADARGS
fi
combined with a tweaked deploy.rb recipe to both link the bundler gem folder and the database config file, and to use my scripts :
set :application, "giftr"
set :repository,  "git@github.com:jeantil/giftr.git"

set :scm, :git # Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`

set :deploy_to, "/users/home/#{user}/domains/giftr.byjean.eu/apps/giftr"

#role :web, "#{host}.joyent.us"                          # Your HTTP server, Apache/etc
#role :app, "#{host}.joyent.us"                          # This may be the same as your `Web` server
#role :db,  "#{host}.joyent.us", :primary => true # This is where Rails migrations will run

server "#{kemp}.joyent.us", :app, :web, :db, :primary => true
set :user, "#{user}"
set :use_sudo, false
# If you are using Passenger mod_rails uncomment this:
# if you're still using the script/reapear helper you will need
# these http://github.com/rails/irs_process_scripts
set :port_number, "#{portnum}"  


namespace :deploy do

  task :start, :roles => :app do
    run "cd #{deploy_to}/current; rails s -e production -p #{port_number} -d -P #{deploy_to}/shared/pids/giftr.pid"
    run "echo \"WEBSITE HAS BEEN STARTED\""
  end
  task :stop, :roles => :app do
    run "cd #{deploy_to}/current; script/stop  #{deploy_to}/shared/pids/giftr.pid"
    run "echo \"WEBSITE HAS BEEN STOPPED\""    
  end
  task :restart, :roles => :app do
    run "cd #{deploy_to}/current; script/stop  #{deploy_to}/shared/pids/giftr.pid ; rails s -e production -p #{port_number} -d -P #{deploy_to}/shared/pids/giftr.pid"
    run "echo \"WEBSITE HAS BEEN RESTARTED\""
  end
  after 'deploy:update_code', 'bundler:bundle_new_release'
end

namespace :bundler do
  task :create_symlink, :roles => :app do
    shared_dir = File.join(shared_path, 'bundle')
    release_dir = File.join(current_release, '.bundle')
    run("mkdir -p #{shared_dir} && ln -s #{shared_dir} #{release_dir}")
  end

  task :bundle_new_release, :roles => :app do
    bundler.create_symlink
    run "cd #{release_path} && bundle install --without test"
  end
  after "bundler:bundle_new_release", :link_production_files
end


# database.yml task
desc "Link in the production database.yml"
task :link_production_files do
  run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
end
Obviously, you will want to replace #{host}, #{user} and #{portnum} with the appropriate values for your host.

Aucun commentaire: