Class: PhusionPassenger::SpawnManager

Inherits:
AbstractServer show all
Includes:
Utils
Defined in:
lib/phusion_passenger/spawn_manager.rb

Overview

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 ClassicRails::FrameworkSpawner to preload and cache Ruby on Rails frameworks. ClassicRails::FrameworkSpawner, in turn, uses ClassicRails::ApplicationSpawner to preload and cache application code.

In case you’re wondering why the namespace is “ClassicRails” and not “Rails”: it’s to work around an obscure bug in ActiveSupport’s Dispatcher.

Instance Attribute Summary

Attributes inherited from AbstractServer

#ignore_password_errors, #max_idle_time, #next_cleaning_time, #password

Instance Method Summary collapse

Methods included from Utils

process_is_alive?

Methods inherited from AbstractServer

#connect, #server_pid, #start, #start_synchronously, #started?, #stop

Constructor Details

#initialize(options = {}) ⇒ SpawnManager

Returns a new instance of SpawnManager.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/phusion_passenger/spawn_manager.rb', line 62

def initialize(options = {})
	super("", "")
	@options = options
	@spawners = AbstractServerCollection.new
	define_message_handler(:spawn_application, :handle_spawn_application)
	define_message_handler(:reload, :handle_reload)
	define_signal_handler('SIGHUP', :reload)
	
	# Start garbage collector in order to free up some existing
	# heap slots. This prevents the heap from growing unnecessarily
	# during the startup phase.
	GC.start
	if GC.copy_on_write_friendly?
		# Preload libraries for copy-on-write semantics.
		require 'base64'
		require 'phusion_passenger/app_process'
		require 'phusion_passenger/classic_rails/framework_spawner'
		require 'phusion_passenger/classic_rails/application_spawner'
		require 'phusion_passenger/rack/application_spawner'
		require 'phusion_passenger/html_template'
		require 'phusion_passenger/platform_info'
		require 'phusion_passenger/exceptions'
	end
end

Instance Method Details

#cleanupObject

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



180
181
182
# File 'lib/phusion_passenger/spawn_manager.rb', line 180

def cleanup
	@spawners.cleanup
end

#reload(app_group_name = nil) ⇒ Object

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. 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.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/phusion_passenger/spawn_manager.rb', line 161

def reload(app_group_name = nil)
	@spawners.synchronize do
		if app_group_name
			# Stop and delete associated ApplicationSpawner.
			@spawners.delete("app:#{app_group_name}")
			# Propagate reload command to associated FrameworkSpawner.
			@spawners.each do |spawner|
				if spawner.respond_to?(:reload)
					spawner.reload(app_group_name)
				end
			end
		else
			# Stop and delete all spawners.
			@spawners.clear
		end
	end
end

#spawn_application(options) ⇒ Object

Spawns an application with the given spawn options. When successful, an AppProcess object will be returned, which represents the spawned application process.

Most options are explained in PoolOptions.h.

Mandatory options:

  • ‘app_root’

Optional options:

  • ‘app_type’

  • ‘environment’

  • ‘spawn_method’

  • ‘user’,

  • ‘group’

  • ‘default_user’

  • ‘default_group’

  • ‘framework_spawner_timeout’

  • ‘app_spawner_timeout’

  • ‘environment_variables’: Environment variables which should be passed to the spawned application process. This is NULL-seperated string of key-value pairs, encoded in base64. The last byte in the unencoded data must be a NULL.

  • ‘base_uri’

  • ‘print_exceptions’

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.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/phusion_passenger/spawn_manager.rb', line 120

def spawn_application(options)
	if !options["app_root"]
		raise ArgumentError, "The 'app_root' option must be given."
	end
	options = sanitize_spawn_options(options)
	
	case options["app_type"]
	when "rails"
		if !defined?(ClassicRails::FrameworkSpawner)
			require 'phusion_passenger/classic_rails/framework_spawner'
			require 'phusion_passenger/classic_rails/application_spawner'
		end
		return spawn_rails_application(options)
	when "rack"
		if !defined?(Rack::ApplicationSpawner)
			require 'phusion_passenger/rack/application_spawner'
		end
		return spawn_rack_application(options)
	when "wsgi"
		if !defined?(WSGI::ApplicationSpawner)
			require 'phusion_passenger/wsgi/application_spawner'
		end
		return WSGI::ApplicationSpawner.spawn_application(options)
	else
		raise ArgumentError, "Unknown 'app_type' value '#{options["app_type"]}'."
	end
end