class PhusionPassenger::ClassicRails::FrameworkSpawner

This class is capable of spawning Ruby on Rails application instances quickly. This is done by preloading the Ruby on Rails framework into memory, before spawning the application instances.

A single FrameworkSpawner instance can only hold a single Ruby on Rails framework version. So be careful when using FrameworkSpawner: the applications that you spawn through it must require the same RoR version. To handle multiple RoR versions, use multiple FrameworkSpawner instances.

FrameworkSpawner uses ApplicationSpawner internally.

Note: FrameworkSpawner may only be started asynchronously with PhusionPassenger::AbstractServer#start. Starting it synchronously with PhusionPassenger::AbstractServer#start_synchronously has not been tested.

Public Class Methods

new(options = {}) click to toggle source

Creates a new instance of FrameworkSpawner.

Extra supported options:

  • framework_version: The Ruby on Rails version to use. It is not checked whether this version is actually installed.

All other options will be passed on to ApplicationSpawner and RequestHandler.

Note that the specified Rails framework will be loaded during the entire life time of the FrameworkSpawner server. If you wish to reload the Rails framework's code, then restart the server by calling PhusionPassenger::AbstractServer#stop and PhusionPassenger::AbstractServer#start.

# File lib/phusion_passenger/classic_rails/framework_spawner.rb, line 66
def initialize(options = {})
        if !options.respond_to?(:'[]')
                raise ArgumentError, "The 'options' argument does not seem to be an options hash"
        end
        @framework_version = options["framework_version"]
        if options.has_key?("print_framework_loading_exceptions")
                @print_framework_loading_exceptions = options["print_framework_loading_exceptions"]
        else
                @print_framework_loading_exceptions = true
        end
        if !@framework_version
                raise ArgumentError, "The 'framework_version' option must specified"
        end
        
        super()
        @options = options
        self.max_idle_time = DEFAULT_FRAMEWORK_SPAWNER_MAX_IDLE_TIME
        define_message_handler(:spawn_application, :handle_spawn_application)
        define_message_handler(:reload, :handle_reload)
end

Public Instance Methods

reload(app_group_name = nil) click to toggle source

Remove the cached application instances at the given group name. If nil is specified as group name, then all cached application instances will be removed, no matter the group name.

Long description: Application code might be cached in memory by a FrameworkSpawner. But once it a while, it will be necessary to reload the code for an application, such as after deploying a new version of the application. This method makes sure that any cached application code is removed, so that the next time an application instance is spawned, the application code will be freshly loaded into memory.

Raises:

# File lib/phusion_passenger/classic_rails/framework_spawner.rb, line 188
def reload(app_group_name = nil)
        connect do |channel|
                if app_group_name.nil?
                        channel.write("reload")
                else
                        channel.write("reload", app_group_name)
                end
        end
rescue SystemCallError, IOError, SocketError
        raise Error, "The framework spawner server exited unexpectedly: #{e}"
end
spawn_application(options = {}) click to toggle source

Spawn a RoR application using the Ruby on Rails framework version associated with this FrameworkSpawner. When successful, an Application object will be returned, which represents the spawned RoR application.

All options accepted by PhusionPassenger::ClassicRails::ApplicationSpawner.new and PhusionPassenger::ClassicRails::RequestHandler.new are accepted.

FrameworkSpawner will internally cache the code of applications, in order to speed up future spawning attempts. This implies that, if you've changed the application's code, you must do one of these things:

Raises:

  • AbstractServer::ServerNotStarted: The FrameworkSpawner server hasn't already been started.

  • AppInitError: The application raised an exception or called exit() during startup.

  • ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.

  • FrameworkSpawner::Error: The FrameworkSpawner server exited unexpectedly.

# File lib/phusion_passenger/classic_rails/framework_spawner.rb, line 140
def spawn_application(options = {})
        app_root = options["app_root"]
        options = sanitize_spawn_options(options)
        options["app_root"] = app_root
        # No need for the ApplicationSpawner to print exceptions. All
        # exceptions raised by the ApplicationSpawner are sent back here,
        # so we just need to decide here whether we want to print it.
        print_exceptions = options["print_exceptions"]
        options["print_exceptions"] = false
        
        begin
                connect do |channel|
                        channel.write("spawn_application", *options.to_a.flatten)
                        result = channel.read
                        if result.nil?
                                raise IOError, "Connection closed"
                        end
                        if result[0] == 'exception'
                                e = unmarshal_exception(channel.read_scalar)
                                if print_exceptions && e.respond_to?(:child_exception) && e.child_exception
                                        print_exception(self.class.to_s, e.child_exception)
                                elsif print_exceptions
                                        print_exception(self.class.to_s, e)
                                end
                                raise e
                        else
                                return AppProcess.read_from_channel(channel)
                        end
                end
        rescue SystemCallError, IOError, SocketError => e
                raise Error, "The framework spawner server exited unexpectedly: #{e}"
        end
end
start() click to toggle source

Overrided from PhusionPassenger::AbstractServer#start.

May raise these additional exceptions:

  • FrameworkInitError: An error occurred while loading the specified Ruby on Rails framework.

  • FrameworkSpawner::Error: The FrameworkSpawner server exited unexpectedly.

# File lib/phusion_passenger/classic_rails/framework_spawner.rb, line 92
def start
        super
        begin
                channel = MessageChannel.new(@owner_socket)
                result = channel.read
                if result.nil?
                        raise Error, "The framework spawner server exited unexpectedly."
                else
                        status = result[0]
                end
                if status == 'exception'
                        child_exception = unmarshal_exception(channel.read_scalar)
                        stop
                        message = "Could not load Ruby on Rails framework version #{@framework_version}: " <<
                                "#{child_exception.class} (#{child_exception.message})"
                        options = { :version => @framework_version }
                        if @print_framework_loading_exceptions
                                print_exception(self.class.to_s, child_exception)
                        end
                        raise FrameworkInitError.new(message, child_exception, options)
                end
        rescue IOError, SystemCallError, SocketError => e
                stop if started?
                raise Error, "The framework spawner server exited unexpectedly: #{e}"
        rescue
                stop if started?
                raise
        end
end