Class | PhusionPassenger::SpawnManager
In: | lib/phusion_passenger/spawn_manager.rb
Parent: | AbstractServer

The spawn manager is capable of spawning Ruby on Rails or Rack application instances. It acts like a simple fascade for the rest of the spawn manager system.

Note: SpawnManager may only be started synchronously with AbstractServer#start_synchronously. Starting asynchronously has not been tested. Don‘t forget to call cleanup after the server‘s main loop has finished.

## Ruby on Rails optimizations

Spawning a Ruby on Rails application is usually slow. But SpawnManager will preload and cache Ruby on Rails frameworks, as well as application code, so subsequent spawns will be very fast.

Internally, SpawnManager uses Railz::FrameworkSpawner to preload and cache Ruby on Rails frameworks. Railz::FrameworkSpawner, in turn, uses Railz::ApplicationSpawner to preload and cache application code.

In case you‘re wondering why the namespace is "Railz" and not "Rails": it‘s to work around an obscure bug in ActiveSupport‘s Dispatcher.

### Methods

cleanup new reload spawn_application

### Included Modules

Utils

### Public Class methods

new()

[Source]

        # File lib/phusion_passenger/spawn_manager.rb, line 55
    55:         def initialize
    56:                 super()
    57:                 @spawners = AbstractServerCollection.new
    58:                 define_message_handler(:spawn_application, :handle_spawn_application)
    59:                 define_message_handler(:reload, :handle_reload)
    60:                 define_signal_handler('SIGHUP', :reload)
    61:
    62:                 # Start garbage collector in order to free up some existing
    63:                 # heap slots. This prevents the heap from growing unnecessarily
    64:                 # during the startup phase.
    65:                 GC.start
    66:                 if GC.copy_on_write_friendly?
    67:                         # Preload libraries for copy-on-write semantics.
    68:                         require 'base64'
    69:                         require 'phusion_passenger/application'
    70:                         require 'phusion_passenger/railz/framework_spawner'
    71:                         require 'phusion_passenger/railz/application_spawner'
    72:                         require 'phusion_passenger/rack/application_spawner'
    73:                         require 'phusion_passenger/html_template'
    74:                         require 'phusion_passenger/platform_info'
    75:                         require 'phusion_passenger/exceptions'
    76:
    77:                         # Commonly used libraries.
    78:                         ['mysql', 'sqlite3'].each do |lib|
    79:                                 begin
    80:                                         require lib
    81:                                 rescue LoadError
    82:                                         # Do nothing; ignore if not present.
    83:                                 end
    84:                         end
    85:                 end
    86:         end

### Public Instance methods

cleanup()

Cleanup resources. Should be called when this SpawnManager is no longer needed.

[Source]

         # File lib/phusion_passenger/spawn_manager.rb, line 215
    215:         def cleanup
    216:                 @spawners.cleanup
    217:         end

reload(app_root = nil)

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. 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 AbstractServer::SpawnError if something went wrong.

[Source]

         # File lib/phusion_passenger/spawn_manager.rb, line 182
    182:         def reload(app_root = nil)
    183:                 if app_root
    184:                         begin
    185:                                 app_root = normalize_path(app_root)
    186:                         rescue InvalidPath
    187:                         end
    188:                 end
    189:                 @spawners.synchronize do
    190:                         if app_root
    191:                                 # Delete associated ApplicationSpawner.
    192:                                 @spawners.delete("app:#{app_root}")
    193:                         else
    194:                                 # Delete all ApplicationSpawners.
    195:                                 keys_to_delete = []
    196:                                 @spawners.each_pair do |key, spawner|
    197:                                         if spawner.is_a?(Railz::ApplicationSpawner)
    198:                                                 keys_to_delete << key
    199:                                         end
    200:                                 end
    201:                                 keys_to_delete.each do |key|
    202:                                         @spawners.delete(key)
    203:                                 end
    204:                         end
    205:                         @spawners.each do |spawner|
    206:                                 # Reload all FrameworkSpawners.
    207:                                 if spawner.respond_to?(:reload)
    208:                                         spawner.reload(app_root)
    209:                                 end
    210:                         end
    211:                 end
    212:         end

spawn_application(options)

Spawn an application with the given spawn options. When successful, an Application object will be returned, which represents the spawned application. At least one option must be given: `app_root`. This is the application‘s root folder.

Other options are:

‘lower_privilege’, ‘lowest_user’ and ‘environment‘
  See Railz::ApplicationSpawner.new for an explanation of these options.
‘app_type‘
  What kind of application is being spawned. Either "rails" (default), "rack" or "wsgi".
‘spawn_method‘
  May be one of "smart", "smart-lv2" or "conservative". When "smart" is specified, SpawnManager will internally cache the code of Rails 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 SpawnManager by calling AbstractServer#stop, then AbstractServer#start.
  - Reload the application by calling reload with the correct app_root argument.

  "smart" caches the Rails framework code in a framework spawner server, and application code in an application spawner server. Sometimes it is desirable to skip the framework spawning and going directly for the application spawner instead. The "smart-lv2" method allows you to do that.

  Caching however can be incompatible with some applications. The "conservative" spawning method does not involve any caching at all. Spawning will be slower, but is guaranteed to be compatible with all applications.

  The default spawn method is "smart-lv2".

‘framework_spawner_timeout’ and ‘app_spawner_timeout‘
  These options allow you to specify the maximum idle timeout, in seconds, of the framework spawner servers and application spawner servers that will be started under the hood. These options are only used if `app_type` equals "rails".

  A timeout of 0 means that the spawner server should never idle timeout. A timeout of -1 means that the default timeout value should be used. The default value is -1.

Exceptions:

- InvalidPath: `app_root` doesn‘t appear to be a valid Ruby on Rails application root.
- VersionNotFound: The Ruby on Rails framework version that the given application requires is not installed.
- AbstractServer::ServerError: One of the server processes exited unexpectedly.
- FrameworkInitError: The Ruby on Rails framework that the application requires could not be loaded.
- AppInitError: The application raised an exception or called exit() during startup.

[Source]

         # File lib/phusion_passenger/spawn_manager.rb, line 136
    136:         def spawn_application(options)
    137:                 if !options["app_root"]
    138:                         raise ArgumentError, "The 'app_root' option must be given."
    139:                 end
    140:                 options = sanitize_spawn_options(options)
    141:
    142:                 if options["app_type"] == "rails"
    143:                         if !defined?(Railz::FrameworkSpawner)
    144:                                 require 'phusion_passenger/application'
    145:                                 require 'phusion_passenger/railz/framework_spawner'
    146:                                 require 'phusion_passenger/railz/application_spawner'
    147:                         end
    148:                         return spawn_rails_application(options)
    149:                 elsif options["app_type"] == "rack"
    150:                         if !defined?(Rack::ApplicationSpawner)
    151:                                 require 'phusion_passenger/rack/application_spawner'
    152:                         end
    153:                         return Rack::ApplicationSpawner.spawn_application(
    154:                                 options["app_root"], options
    155:                         )
    156:                 elsif options["app_type"] == "wsgi"
    157:                         require 'phusion_passenger/wsgi/application_spawner'
    158:                         return WSGI::ApplicationSpawner.spawn_application(
    159:                                 options["app_root"],
    160:                                 options["lower_privilege"],
    161:                                 options["lowest_user"],
    162:                                 options["environment"]
    163:                         )
    164:                 else
    165:                         raise ArgumentError, "Unknown 'app_type' value '#{options["app_type"]}'."
    166:                 end
    167:         end

[Validate]