my rails runner

Discussion in 'Ruby/Rails' started by Grzegorz Derebecki, Feb 3, 2010.

  1. Grzegorz Derebecki

    Grzegorz Derebecki New Member

    I want share with you my modified RailsRunner it works only with rack rails 2.3 i had separate RailsRunner for older version to if somone want i can post it too

    There is a few modifications:

    1. Process name changed now we see what is process name
    it looks like:

    91436 ?? S 3:33.42 ruby: RAILS: fdb.pl (production) (ruby)
    91437 ?? S 3:53.94 ruby: RAILS: fdb.pl (production) (ruby)
    91438 ?? S 3:29.63 ruby: RAILS: fdb.pl (production) (ruby)
    91439 ?? S 3:49.33 ruby: RAILS: fdb.pl (production) (ruby)

    you must set APP_NAME varible in litespeed env or it will use directory where you app is placed.


    2. second change is FIX problem with ENV varible
    after call server = Rack::Handler::LSWS ENV varible disaperd i rewrite it again.

    Code:
    #!/opt/ruby/bin/ruby 
    #
    Dir.chdir(ENV['RAILS_ROOT'])
    
    $0="RAILS: #{ENV['APP_NAME'] || ENV['RAILS_ROOT']} (#{ENV['RAILS_ENV']})"
    if GC.respond_to?(:copy_on_write_friendly=)
       GC.copy_on_write_friendly = true
    end
    
    
    require 'config/boot'
    require 'active_support'
    require 'action_controller'
    require 'fileutils'
    
    options = {
      :environment => (ENV['RAILS_ENV'] || "development").dup,
      :config => RAILS_ROOT + "/config.ru",
      :detach => false,
      :debugger => false
    }
    
    # fix bug in lsapi (ENV var disapper)
    env = ENV
    server = Rack::Handler::LSWS
    env.each { |k,v| ENV[k] ||= v }
    
    if File.exist?(options[:config])
      config = options[:config]
      if config =~ /\.ru$/
        cfgfile = File.read(config)
        if cfgfile[/^#\\(.*)/]
          opts.parse!($1.split(/\s+/))
        end
        inner_app = eval("Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, config)
      else
        require config
        inner_app = Object.const_get(File.basename(config, '.rb').capitalize)
      end
    else
      require 'config/environment'
      inner_app = ActionController::Dispatcher.new
    end
    
    app = Rack::Builder.new {
      use Rails::Rack::Static
      use Rails::Rack::Debugger if options[:debugger]
      run inner_app
    }.to_app
    
    ActiveRecord::Base.clear_all_connections! if defined?(ActiveRecord::Base)
    
    
    begin
      server.run(app, options.merge(:AccessLog => []))
    ensure
      puts 'Exiting'
    end
    

    hope that we be usefull for somone :)
  2. mistwang

    mistwang LiteSpeed Staff

    incorporate the "process name change" feature into our official Rails Runner code.
  3. mistwang

    mistwang LiteSpeed Staff

    After trouble shooting an issue with radiantCMS, I come up a new RailsRunner to address following issues:

    1. Failed to detect Rails version when application bundled with Rails like radiantCMS.
    use Rails::VERSION::STRING to get rails_ver now
    2. Add our own rack handler into RailsRunner, so, no need to patch Rack anymore.

    The new RailsRunners.rb is
    Code:
    #!/usr/bin/ruby
    
    $0="RAILS: #{ENV['APP_NAME'] || ENV['RAILS_ROOT']} (#{ENV['RAILS_ENV']})"
    if GC.respond_to?(:copy_on_write_friendly=)
        GC.copy_on_write_friendly = true
    end
    
    Dir.chdir( ENV['RAILS_ROOT'] )
    require 'config/boot'
    
    rails_ver = Rails::VERSION::STRING
    
    #if defined? RAILS_GEM_VERSION
    #    rails_ver = RAILS_GEM_VERSION
    #elsif ENV.include?('RAILS_GEM_VERSION')
    #    rails_ver = ENV['RAILS_GEM_VERSION']
    #else
    #    environmentrb = File.read('config/environment.rb')
    #    rails_ver = $1 if environmentrb =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
    #end
    
    if rails_ver != nil and rails_ver >= '2.3.0'
        #use rack
        require 'active_support'
        require 'action_controller'
        require 'fileutils'
    
        require 'rack/content_length'
        require 'lsapi'
    
        module Rack
          module Handler
            class LiteSpeed
              def self.run(app, options=nil)
                while LSAPI.accept != nil
                    serve app
                end
              end
              def self.serve(app)
                app = Rack::ContentLength.new(app)
    
                env = ENV.to_hash
                env.delete "HTTP_CONTENT_LENGTH"
                env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
    
                rack_input = StringIO.new($stdin.read.to_s)
    
                env.update(
                  "rack.version" => [1,0],
                  "rack.input" => rack_input,
                  "rack.errors" => $stderr,
                  "rack.multithread" => false,
                  "rack.multiprocess" => true,
                  "rack.run_once" => false,
                  "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
                )
    
                env["QUERY_STRING"] ||= ""
                env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
                env["REQUEST_PATH"] ||= "/"
                status, headers, body = app.call(env)
                begin
                  send_headers status, headers
                  send_body body
                ensure
                  body.close if body.respond_to? :close
                end
              end
              def self.send_headers(status, headers)
                print "Status: #{status}\r\n"
                headers.each { |k, vs|
                  vs.split("\n").each { |v|
                    print "#{k}: #{v}\r\n"
                  }
                }
                print "\r\n"
                STDOUT.flush
              end
              def self.send_body(body)
                body.each { |part|
                  print part
                  STDOUT.flush
                }
              end
            end
          end
        end
        
        options = {
            :environment => (ENV['RAILS_ENV'] || "development").dup,
            :config => RAILS_ROOT + "/config.ru",
            :detach => false,
            :debugger => false
        }
        
        server = Rack::Handler::LiteSpeed
        
        if File.exist?(options[:config])
            config = options[:config]
        if config =~ /\.ru$/
            cfgfile = File.read(config)
            if cfgfile[/^#\\(.*)/]
                opts.parse!($1.split(/\s+/))
            end
            inner_app = eval("Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, config)
        else
            require config
            inner_app = Object.const_get(File.basename(config, '.rb').capitalize)
        end
        else
            require 'config/environment'
            inner_app = ActionController::Dispatcher.new
        end
        
        app = Rack::Builder.new {
            use Rails::Rack::Static
            use Rails::Rack::Debugger if options[:debugger]
            run inner_app
        }.to_app
    
        ActiveRecord::Base.clear_all_connections! if defined?(ActiveRecord::Base)
    
        begin
            server.run(app, options.merge(:AccessLog => []))
        ensure
            puts 'Exiting'
        end
     
    else
      
        require 'config/environment'
        
        require 'initializer'
        require 'dispatcher'
        
        #require 'breakpoint' if defined?(BREAKPOINT_SERVER_PORT)
    
        #if RAILS_ENV=='production'
        #   require_dependency 'application'
        #   Dir.foreach( "app/models" ) {|f| silence_warnings{require_dependency f} if f =~ /\.rb$/}
        #   Dir.foreach( "app/controllers" ) {|f|  silence_warnings{require_dependency f} if f =~ /\.rb$/}
        #end
    
        require 'lsapi'
    
        #Close all DB connections established during initialization
        if defined?(ActiveRecord::Base)
        if defined?(ActiveRecord::Base.clear_active_connections!)
            ActiveRecord::Base.clear_active_connections!
        else
            ActiveRecord::Base.connection.disconnect!
            @reconnect = true
            ActiveRecord::Base.establish_connection
        end
        end
    
        while LSAPI.accept != nil
            if defined?(ActiveRecord::Base) and @reconnect
                ActiveRecord::Base.connection.reconnect!
                @reconnect = false
            end
    
            Dispatcher.dispatch
        end
    end
  4. Grzegorz Derebecki

    Grzegorz Derebecki New Member

    I think there is 1 litle problem with RailsRunner:

    Code:
     require 'active_support' 
     require 'action_controller'
    
    if you include config/boot i think they are arledy loaded if not
    it will load newest version of this libs even application runing older rails
    (if there is 2 rails version installed in system exemple: 2.3.5 and 2.3.4)
  5. mistwang

    mistwang LiteSpeed Staff

    So, you think it is safe to remove those. it was in the original RailsRunner.
  6. Grzegorz Derebecki

    Grzegorz Derebecki New Member

    i didn't checked yet but when i will test new loader (with include boot.rb) i will inform you.

Share This Page