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 AbstractServer#start. Starting it synchronously with AbstractServer#start_synchronously has not been tested.
APP_SPAWNER_MAX_IDLE_TIME | = | 120 |
APP_SPAWNER_CLEAN_INTERVAL | = | APP_SPAWNER_MAX_IDLE_TIME + 5 |
[RW] | time | An attribute, used internally. This should not be used outside Passenger. |
Creates a new instance of FrameworkSpawner.
Valid options:
- :version: The Ruby on Rails version to use. It is not checked whether this version is actually installed.
- :vendor: The directory to the vendor Rails framework to use. This is usually something like "/webapps/foo/vendor/rails".
It is not allowed to specify both version and vendor.
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 AbstractServer#stop and AbstractServer#start.
[ show source ]
# File lib/passenger/framework_spawner.rb, line 81 81: def initialize(options = {}) 82: if !options.respond_to?('[]''[]') 83: raise ArgumentError, "The 'options' argument not seem to be an options hash" 84: end 85: @version = options[:version] 86: @vendor = options[:vendor] 87: if !@version && !@vendor 88: raise ArgumentError, "Either the 'version' or the 'vendor' option must specified" 89: elsif @version && @vendor 90: raise ArgumentError, "It is not allowed to specify both the 'version' and the 'vendor' options" 91: end 92: 93: super() 94: define_message_handler(:spawn_application, :handle_spawn_application) 95: define_message_handler(:reload, :handle_reload) 96: end
Remove the cached application instances at the given application root. If nil is specified as application root, then all cached application instances will be removed, no matter the application root.
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:
- ArgumentError: app_root doesn‘t appear to be a valid Ruby on Rails application root.
- FrameworkSpawner::Error: The FrameworkSpawner server exited unexpectedly.
[ show source ]
# File lib/passenger/framework_spawner.rb, line 188 188: def reload(app_root = nil) 189: if app_root.nil? 190: server.write("reload") 191: else 192: server.write("reload", normalize_path(app_root)) 193: end 194: rescue SystemCallError, IOError, SocketError 195: raise Error, "The framework spawner server exited unexpectedly" 196: end
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.
See ApplicationSpawner.new for an explanation of the lower_privilege and lowest_user parameters.
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:
- Restart this FrameworkSpawner by calling AbstractServer#stop, then AbstractServer#start.
- Reload the application by calling reload with the correct app_root argument.
Raises:
- AbstractServer::ServerNotStarted: The FrameworkSpawner server hasn‘t already been started.
- ArgumentError: app_root doesn‘t appear to be a valid Ruby on Rails application root.
- 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.
[ show source ]
# File lib/passenger/framework_spawner.rb, line 146 146: def spawn_application(app_root, lower_privilege = true, lowest_user = "nobody") 147: app_root = normalize_path(app_root) 148: assert_valid_app_root(app_root) 149: exception_to_propagate = nil 150: begin 151: server.write("spawn_application", app_root, lower_privilege, lowest_user) 152: result = server.read 153: if result.nil? 154: raise IOError, "Connection closed" 155: end 156: if result[0] == 'exception' 157: raise unmarshal_exception(server.read_scalar) 158: else 159: pid, listen_socket_name, using_abstract_namespace = server.read 160: if pid.nil? 161: raise IOError, "Connection closed" 162: end 163: owner_pipe = server.recv_io 164: return Application.new(app_root, pid, listen_socket_name, 165: using_abstract_namespace == "true", owner_pipe) 166: end 167: rescue SystemCallError, IOError, SocketError => e 168: raise Error, "The framework spawner server exited unexpectedly" 169: end 170: end
Overrided from AbstractServer#start.
May raise these additional exceptions:
- FrameworkInitError: The specified Ruby on Rails framework could not be loaded.
- FrameworkSpawner::Error: The FrameworkSpawner server exited unexpectedly.
[ show source ]
# File lib/passenger/framework_spawner.rb, line 103 103: def start 104: super 105: begin 106: status = server.read[0] 107: if status == 'exception' 108: child_exception = unmarshal_exception(server.read_scalar) 109: stop 110: if @version 111: message = "Could not load Ruby on Rails framework version #{@version}: " << 112: "#{child_exception.class} (#{child_exception.message})" 113: else 114: message = "Could not load Ruby on Rails framework at '#{@vendor}': " << 115: "#{child_exception.class} (#{child_exception.message})" 116: end 117: options = { :vendor => @vendor, :version => @version } 118: raise FrameworkInitError.new(message, child_exception, options) 119: end 120: rescue IOError, SystemCallError, SocketError 121: stop 122: raise Error, "The framework spawner server exited unexpectedly" 123: end 124: end