ruby-style 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +54 -52
- data/lib/style/adapter/rails.rb +37 -0
- data/lib/style/adapter/ramaze.rb +14 -0
- data/lib/style/handler/evented_mongrel.rb +3 -0
- data/lib/style/handler/eventmachine.rb +43 -0
- data/lib/style/handler/mongrel.rb +20 -0
- data/lib/{RailsSCGIStyle.rb → style/handler/scgi.rb} +26 -5
- data/lib/style.rb +78 -33
- metadata +8 -4
- data/lib/RailsMongrelStyle.rb +0 -61
data/README
CHANGED
@@ -28,7 +28,8 @@ Subversion access is available at svn://code.jeremyevans.net/ruby-style/.
|
|
28
28
|
the fly
|
29
29
|
* Supports both command line and yaml config file configuration
|
30
30
|
* Is easily extensible to support running other frameworks and protocols other
|
31
|
-
than the included ones (
|
31
|
+
than the included ones (Rails and Ramaze; SCGI, Mongrel, and Evented
|
32
|
+
Mongrel)
|
32
33
|
|
33
34
|
== Running and configuration
|
34
35
|
|
@@ -37,16 +38,18 @@ just run the program without any arguments:
|
|
37
38
|
|
38
39
|
style [option value, ...] (decrement|halt|increment|restart|start|stop)
|
39
40
|
Options:
|
41
|
+
-a, --adapter Adapter/Framework to use [rails]
|
40
42
|
-b, --bind IP address to bind to [127.0.0.1]
|
41
43
|
-c, --config Location of config file [config/style.yaml]
|
42
44
|
-d, --directory Working directory [.]
|
45
|
+
-D, --debug Run the program in the foreground without forking [No]
|
43
46
|
-f, --fork Number of listners on each port [1]
|
47
|
+
-h, --handler Handler/Server to use [mongrel]
|
44
48
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
45
49
|
-l, --logfile Where to redirect STDOUT and STDERR [log/style.log]
|
46
50
|
-n, --number Number of ports to which to bind [1]
|
47
51
|
-p, --port Starting port to which to bind [9999]
|
48
52
|
-P, --pidfile Location of pid file [log/style.pid]
|
49
|
-
-s, --style Type of style to use [RailsMongrel]
|
50
53
|
-u, --unsupervised Whether to run unsupervised [No]
|
51
54
|
|
52
55
|
Here's what the various commands do:
|
@@ -66,9 +69,15 @@ process, so the -c, -l, and -P options are relative to that.
|
|
66
69
|
|
67
70
|
Here's a longer explanation of the options:
|
68
71
|
|
72
|
+
-a, --adapter Adapter/Framework to use [rails]
|
73
|
+
|
74
|
+
This is the adapter/framework to use. Support for Rails and Ramaze is
|
75
|
+
included in the distribution, support for other frameworks should be fairly
|
76
|
+
easy to add.
|
77
|
+
|
69
78
|
-b, --bind IP address to bind to [127.0.0.1]
|
70
79
|
|
71
|
-
This is the TCP/IP networking
|
80
|
+
This is the TCP/IP networking socket to bind to. It defaults to the
|
72
81
|
loopback address because generally the web application runs on the same
|
73
82
|
physical server as the web server. If this is not the case, change it to an
|
74
83
|
externally available IP, and make sure to lock down access to the port via a
|
@@ -89,6 +98,11 @@ Here's a longer explanation of the options:
|
|
89
98
|
root of the application before hand and then not use this option. This option
|
90
99
|
is not configurable from the configuration file.
|
91
100
|
|
101
|
+
-D, --debug Run the program in the foreground without forking [No]
|
102
|
+
|
103
|
+
This runs the program in the program without forking, aiding in debugging a
|
104
|
+
problematic configuration.
|
105
|
+
|
92
106
|
-f, --fork Number of listners on each port [1]
|
93
107
|
|
94
108
|
This enables multiple child processes listening on each port. It is
|
@@ -100,6 +114,13 @@ Here's a longer explanation of the options:
|
|
100
114
|
are killed, so it is possibly to have multiple processes listening on a port
|
101
115
|
even if this is left at one.
|
102
116
|
|
117
|
+
-h, --handler Handler/Server to use [mongrel]
|
118
|
+
|
119
|
+
This is the handler/server to use. Support for Mongrel, Evented Mongrel,
|
120
|
+
and SCGI is included in the distribution. Support for other servers is
|
121
|
+
easy to add as long as the servers can be modified to use the socket
|
122
|
+
created by style ($STYLE_SOCKET).
|
123
|
+
|
103
124
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
104
125
|
|
105
126
|
This sets the time that style between sending shutdown signals to child
|
@@ -134,15 +155,6 @@ Here's a longer explanation of the options:
|
|
134
155
|
they should be, and you will probably won't be able to start new processes
|
135
156
|
(because the ports will still be in use).
|
136
157
|
|
137
|
-
-s, --style Type of style to use [RailsMongrel]
|
138
|
-
|
139
|
-
This is the type of style to use. It defaults to RailsMongrel, as that is
|
140
|
-
most common configuration these days. The other style included with style is
|
141
|
-
RailsSCGI. Adding other styles is fairly easy, just make the style is in a
|
142
|
-
file named XXXXXStyle.rb (where XXXXX is in the name of the style), and that
|
143
|
-
file is located in ruby's library path ($:, e.g. via the RUBYLIB environment
|
144
|
-
variable). See the included styles for an example.
|
145
|
-
|
146
158
|
-u, --unsupervised Whether to run unsupervised [No]
|
147
159
|
|
148
160
|
This starts child processes without using a supervisor process. It is not
|
@@ -152,24 +164,15 @@ Here's a longer explanation of the options:
|
|
152
164
|
restarted when they die, and you may lose connections during restarts.
|
153
165
|
|
154
166
|
Every one of the long options can also be specified in the config file. Also,
|
155
|
-
the
|
156
|
-
being used (such as modifying the Rails environment setting).
|
157
|
-
|
158
|
-
== Included styles and config files
|
159
|
-
|
160
|
-
style current comes with support for the following styles: RailsMongrelStyle
|
161
|
-
(the default, which requires rails and mongrel), and RailsSCGIStyle (which
|
162
|
-
requires rails and ruby-scgi).
|
167
|
+
the config file must be used if you want to specify any settings specific to
|
168
|
+
adapter being used (such as modifying the Rails environment setting). See
|
169
|
+
below for information on the adapter_config config file variable.
|
163
170
|
|
164
|
-
The
|
165
|
-
be deployed behind a front end webserver, such as Apache, Lighttpd, or Nginx.
|
166
|
-
The RailsSCGI style supports running Rails over SCGI, which is supported by
|
167
|
-
both Apache and Lighttpd. Both default to running Rails in production mode,
|
168
|
-
as style is designed as a production tool.
|
171
|
+
== The config file
|
169
172
|
|
170
|
-
Example
|
171
|
-
interface, with three listeners per port. Note how the :
|
172
|
-
used to set up settings specific to the
|
173
|
+
Example Rails+Mongrel style.yaml that listens on ports 8912 and 8193 on any
|
174
|
+
interface, with three listeners per port. Note how the :adapter_config entry
|
175
|
+
is used to set up settings specific to the Rails adapter, such as placing
|
173
176
|
Rails in development mode.
|
174
177
|
|
175
178
|
---
|
@@ -178,32 +181,36 @@ Rails in development mode.
|
|
178
181
|
:fork: 3
|
179
182
|
:number: 2
|
180
183
|
:killtime: 1
|
181
|
-
:
|
182
|
-
:
|
184
|
+
:adapter: rails
|
185
|
+
:handler: mongrel
|
186
|
+
:adapter_config:
|
183
187
|
:environment: development
|
184
188
|
:log_file: log/rails-mongrel.log
|
185
189
|
:docroot: public
|
186
190
|
:num_processors: 99
|
187
191
|
:timeout: 100
|
188
192
|
|
189
|
-
Example
|
193
|
+
Example Rails+SCGI style.yaml that has four listeners on port 8912:
|
190
194
|
|
191
195
|
---
|
192
196
|
:port: 8912
|
193
197
|
:fork: 4
|
194
198
|
:number: 1
|
195
|
-
:
|
196
|
-
:
|
199
|
+
:adapter: rails
|
200
|
+
:handler: scgi
|
201
|
+
:adapter_config:
|
197
202
|
:logfile: log/railsscgi.log
|
198
203
|
:maxconns: 10
|
199
204
|
:environment: production
|
200
205
|
|
201
|
-
Very simple configuration that runs
|
202
|
-
port 3000.
|
206
|
+
Very simple configuration that runs Ramaze+Evented Mongrel in unsupervised
|
207
|
+
mode on port 3000.
|
203
208
|
|
204
209
|
---
|
205
210
|
:port: 3000
|
206
211
|
:unsupervised: 1
|
212
|
+
:adapter: ramaze
|
213
|
+
:handler: evented_mongrel
|
207
214
|
|
208
215
|
== How restarting works
|
209
216
|
|
@@ -261,25 +268,20 @@ Thu Sep 6 12:01:59 PDT 2007
|
|
261
268
|
Result, three brand new listening processes, total time to restart is about 12
|
262
269
|
seconds (2 * (2 killtime * 1 number * 3 fork)).
|
263
270
|
|
264
|
-
== Other
|
271
|
+
== Other handlers and adapter
|
265
272
|
|
266
|
-
|
267
|
-
|
273
|
+
To add support for another handler, make sure the instead of creating a socket,
|
274
|
+
it uses the socket provided by style, available in the global variable
|
275
|
+
$STYLE_SOCKET. See existing handler code to see how Mongrel, SCGI, and Event
|
276
|
+
Machine were modified to support this.
|
268
277
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
def initialize(options)
|
273
|
-
#options is a Hash
|
274
|
-
end
|
275
|
-
|
276
|
-
def listen(socket)
|
277
|
-
# socket is a TCPServer
|
278
|
-
end
|
279
|
-
end
|
278
|
+
Support for other adapters is easily added by adding the run method to the
|
279
|
+
Style class. This can be easy (as it is with Ramaze), or more difficult (as it
|
280
|
+
is with Rails). If the adapter uses Rack, it should be fairly simple.
|
280
281
|
|
281
|
-
|
282
|
-
|
282
|
+
Style loads adapters and handlers from style/{adapter,handler} relative to the
|
283
|
+
load path, so you can add your own adapters and handlers without modifying the
|
284
|
+
program, as long as you place the files somewhere in the load path.
|
283
285
|
|
284
286
|
== FAQ
|
285
287
|
|
@@ -289,4 +291,4 @@ A: No. Among other things, style uses fork, which is not available on Windows.
|
|
289
291
|
|
290
292
|
Q: Does it work with Capistrano yet?
|
291
293
|
|
292
|
-
A: I haven't tried.
|
294
|
+
A: I haven't tried. It probably can, but it will take a little custom work.
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
# This hooks the HTTP request into Ruby on Rails and Mongrel.
|
4
|
+
class Style
|
5
|
+
# Initialzes Rails and Mongrel with the appropriate environment and settings.
|
6
|
+
def run
|
7
|
+
config[:handler] == 'scgi' ? run_rails_scgi : run_rails_mongrel
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_rails_scgi
|
11
|
+
RailsSCGIProcessor.new(config[:adapter_config]).listen
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_rails_mongrel
|
15
|
+
require 'mongrel/rails'
|
16
|
+
settings = {:cwd => Dir.pwd, :log_file => 'log/rails-mongrel.log',
|
17
|
+
:environment => 'production', :docroot => 'public',
|
18
|
+
:mime_map => nil, :debug => false, :includes => ["mongrel"],
|
19
|
+
:config_script => nil, :num_processors => 1024, :timeout => 0,
|
20
|
+
:user => nil, :group => nil, :prefix => nil}.merge(config[:adapter_config])
|
21
|
+
ENV['RAILS_ENV'] = settings[:environment]
|
22
|
+
$0 += " environment:#{ENV['RAILS_ENV']}"
|
23
|
+
mongrel = Mongrel::Rails::RailsConfigurator.new(settings) do
|
24
|
+
listener do
|
25
|
+
mime = defaults[:mime_map] ? load_mime_map(defaults[:mime_map], mime) : {}
|
26
|
+
debug "/" if defaults[:debug]
|
27
|
+
uri defaults[:prefix] || "/", :handler => rails(:mime => mime, :prefix => defaults[:prefix])
|
28
|
+
load_plugins
|
29
|
+
run_config(defaults[:config_script]) if defaults[:config_script]
|
30
|
+
trap("INT") { @log.info("SIGTERM, forced shutdown."); shutdown(force=true) }
|
31
|
+
setup_rails_signals
|
32
|
+
end
|
33
|
+
end
|
34
|
+
mongrel.run
|
35
|
+
mongrel.join
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ramaze'
|
3
|
+
|
4
|
+
class Style
|
5
|
+
# Run Ramaze with the mongrel adapter and start.rb runner
|
6
|
+
def run
|
7
|
+
settings = {:adapter=>config[:handler].to_sym, :test_connections=>false,
|
8
|
+
:force=>true, :runner =>'start.rb', :host=>config[:bind],
|
9
|
+
:port=>config[:sockets][$STYLE_SOCKET]}.merge(config[:adapter_config])
|
10
|
+
require settings[:runner].to_s
|
11
|
+
Ramaze.start(settings)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
$eventmachine_library = :pure_ruby
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
module EventMachine
|
6
|
+
class StreamObject < Selectable
|
7
|
+
# Delete this when EventMachine fixes typo bug (Rubyforge bug #17461), see
|
8
|
+
# https://rubyforge.org/tracker/index.php?func=detail&aid=17461&group_id=1555&atid=6060
|
9
|
+
def eventable_write
|
10
|
+
# coalesce the outbound array here, perhaps
|
11
|
+
@last_activity = Reactor.instance.current_loop_time
|
12
|
+
while data = @outbound_q.shift do
|
13
|
+
begin
|
14
|
+
data = data.to_s
|
15
|
+
w = if io.respond_to?(:write_nonblock)
|
16
|
+
io.write_nonblock data
|
17
|
+
else
|
18
|
+
io.syswrite data
|
19
|
+
end
|
20
|
+
|
21
|
+
if w < data.length
|
22
|
+
@outbound_q.unshift data[w..-1]
|
23
|
+
break
|
24
|
+
end
|
25
|
+
rescue Errno::EAGAIN
|
26
|
+
@outbound_q.unshift data
|
27
|
+
rescue EOFError, Errno::ECONNRESET, Errno::ECONNREFUSED
|
28
|
+
@close_scheduled = true
|
29
|
+
@outbound_q.clear
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EvmaTCPServer < Selectable
|
36
|
+
class << self
|
37
|
+
# Use $STYLE_SOCKET instead of creating a socket with the host and port
|
38
|
+
def start_server(host, port)
|
39
|
+
EvmaTCPServer.new $STYLE_SOCKET
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mongrel'
|
3
|
+
|
4
|
+
module Mongrel
|
5
|
+
class HttpServer
|
6
|
+
# Keep the interface the same, but ignore the host and port and use the
|
7
|
+
# socket provided by style
|
8
|
+
def initialize(host, port, num_processors=950, throttle=0, timeout=60)
|
9
|
+
tries = 0
|
10
|
+
@socket = $STYLE_SOCKET
|
11
|
+
@classifier = URIClassifier.new
|
12
|
+
@host = host
|
13
|
+
@port = port
|
14
|
+
@workers = ThreadGroup.new
|
15
|
+
@throttle = throttle
|
16
|
+
@num_processors = num_processors
|
17
|
+
@timeout = timeout
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,13 +1,34 @@
|
|
1
|
-
|
1
|
+
require 'rubygems'
|
2
2
|
require 'scgi'
|
3
3
|
|
4
|
+
class SCGI::Processor
|
5
|
+
# Use the standard error as the output logger, and use $STYLE_SOCKET as the
|
6
|
+
# socket on which to listen
|
7
|
+
def initialize(settings = {})
|
8
|
+
@socket ||= $STYLE_SOCKET
|
9
|
+
@total_conns ||= 0
|
10
|
+
@shutdown ||= false
|
11
|
+
@dead ||= false
|
12
|
+
@threads ||= Queue.new
|
13
|
+
@log = Object.new
|
14
|
+
def @log.info(msg)
|
15
|
+
STDERR.puts("[INF][#{@pid ||= Process.pid}] #{msg}")
|
16
|
+
end
|
17
|
+
def @log.error(msg, exc=nil)
|
18
|
+
STDERR.puts("[ERR][#{@pid ||= Process.pid}] #{msg}#{": #{exc}\n#{exc.backtrace.join("\n")}" if exc}")
|
19
|
+
end
|
20
|
+
@maxconns ||= settings[:maxconns] || 2**30-1
|
21
|
+
super()
|
22
|
+
setup_signals
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
4
26
|
# This SCGI::Processor subclass hooks the SCGI request into Ruby on Rails.
|
5
|
-
class
|
27
|
+
class RailsSCGIProcessor < SCGI::Processor
|
6
28
|
# Initialzes Rails with the appropriate environment and settings
|
7
29
|
def initialize(settings)
|
8
|
-
ENV['RAILS_ENV'] = settings[:environment] || 'production'
|
9
|
-
|
10
|
-
require "config/environment"
|
30
|
+
$0 += " environment:#{ENV['RAILS_ENV'] = settings[:environment] || 'production'}"
|
31
|
+
require 'config/environment'
|
11
32
|
ActiveRecord::Base.allow_concurrency = false
|
12
33
|
require 'dispatcher'
|
13
34
|
super(settings)
|
data/lib/style.rb
CHANGED
@@ -16,16 +16,15 @@ require 'yaml'
|
|
16
16
|
# trees.
|
17
17
|
class Style
|
18
18
|
attr_reader :config, :mutex
|
19
|
-
VALID_STYLE_RE = /\A[A-Z][A-ZA-z0-9]*\z/
|
20
19
|
|
21
20
|
# Configure style
|
22
21
|
def initialize
|
23
|
-
super
|
24
22
|
@config = {:pidfile=>'log/style.pid', :number=>1, :port=>9999,
|
25
23
|
:style=>'RailsMongrel', :fork=>1, :bind=>'127.0.0.1',
|
26
24
|
:cliconfig=>{}, :killtime=>2, :config=>'config/style.yaml',
|
27
25
|
:logfile=>'log/style.log', :children=>{},:sockets=>{},
|
28
|
-
:
|
26
|
+
:adapter_config=>{}, :directory=>'.', :debug=>false,
|
27
|
+
:unsupervised=> false, :adapter=>'rails', :handler=>'mongrel'}
|
29
28
|
@mutex = Mutex.new
|
30
29
|
begin
|
31
30
|
parse_options
|
@@ -58,6 +57,12 @@ class Style
|
|
58
57
|
conf
|
59
58
|
end
|
60
59
|
|
60
|
+
def create_socket(bind, port)
|
61
|
+
socket = TCPServer.new(bind, port)
|
62
|
+
socket.listen(50)
|
63
|
+
socket
|
64
|
+
end
|
65
|
+
|
61
66
|
# Detach the process from the controlling terminal, exit otherwise
|
62
67
|
def detach
|
63
68
|
unless Process.setsid
|
@@ -66,13 +71,12 @@ class Style
|
|
66
71
|
end
|
67
72
|
trap(:HUP, 'IGNORE')
|
68
73
|
end
|
69
|
-
|
70
|
-
#
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
eval(style)
|
74
|
+
|
75
|
+
# Print the error message and the usage, then exit
|
76
|
+
def exit_with_error(error_message)
|
77
|
+
puts error_message
|
78
|
+
puts usage
|
79
|
+
exit(1)
|
76
80
|
end
|
77
81
|
|
78
82
|
# Kill each of the given pids in order
|
@@ -92,6 +96,16 @@ class Style
|
|
92
96
|
return nil
|
93
97
|
end
|
94
98
|
end
|
99
|
+
|
100
|
+
# Load the revelent style adapter/framework
|
101
|
+
def load_adapter
|
102
|
+
require "style/adapter/#{config[:adapter]}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# Load the revelent style handler/server
|
106
|
+
def load_handler
|
107
|
+
require "style/handler/#{config[:handler]}"
|
108
|
+
end
|
95
109
|
|
96
110
|
# Parse the command line options, and merge them with the default options and
|
97
111
|
# the config file options. Config file options take precendence over the
|
@@ -99,27 +113,35 @@ class Style
|
|
99
113
|
def parse_options
|
100
114
|
cliconfig = config[:cliconfig]
|
101
115
|
GetoptLong.new(
|
116
|
+
[ '--adapter', '-a', GetoptLong::REQUIRED_ARGUMENT ],
|
102
117
|
[ '--bind', '-b', GetoptLong::REQUIRED_ARGUMENT ],
|
103
118
|
[ '--config', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
104
119
|
[ '--directory', '-d', GetoptLong::REQUIRED_ARGUMENT ],
|
120
|
+
[ '--debug', '-D', GetoptLong::NO_ARGUMENT],
|
105
121
|
[ '--fork', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
122
|
+
[ '--handler', '-h', GetoptLong::REQUIRED_ARGUMENT ],
|
106
123
|
[ '--killtime', '-k', GetoptLong::REQUIRED_ARGUMENT ],
|
107
124
|
[ '--logfile', '-l', GetoptLong::REQUIRED_ARGUMENT ],
|
108
125
|
[ '--number', '-n', GetoptLong::REQUIRED_ARGUMENT ],
|
109
126
|
[ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
110
127
|
[ '--pidfile', '-P', GetoptLong::REQUIRED_ARGUMENT ],
|
111
|
-
[ '--style', '-s', GetoptLong::REQUIRED_ARGUMENT ],
|
112
128
|
[ '--unsupervised', '-u', GetoptLong::NO_ARGUMENT]
|
113
129
|
).each do |opt, arg|
|
114
130
|
case opt
|
131
|
+
when '--adapter'
|
132
|
+
cliconfig[:adapter] = arg
|
115
133
|
when '--bind'
|
116
134
|
cliconfig[:bind] = arg
|
117
135
|
when '--config'
|
118
136
|
config[:config] = cliconfig[:config] = arg
|
119
137
|
when '--directory'
|
120
138
|
config[:directory] = arg
|
139
|
+
when '--debug'
|
140
|
+
cliconfig[:debug] = true
|
121
141
|
when '--fork'
|
122
142
|
cliconfig[:fork] = arg.to_i
|
143
|
+
when '--handler'
|
144
|
+
cliconfig[:handler] = arg
|
123
145
|
when '--killtime'
|
124
146
|
cliconfig[:killtime] = arg.to_i
|
125
147
|
when '--logfile'
|
@@ -130,8 +152,6 @@ class Style
|
|
130
152
|
cliconfig[:port] = arg.to_i
|
131
153
|
when '--pidfile'
|
132
154
|
cliconfig[:pidfile] = arg
|
133
|
-
when '--style'
|
134
|
-
cliconfig[:style] = arg
|
135
155
|
when '--unsupervised'
|
136
156
|
cliconfig[:unsupervised] = true
|
137
157
|
end
|
@@ -144,24 +164,24 @@ class Style
|
|
144
164
|
config[:config] = File.expand_path(config[:config])
|
145
165
|
reload_config
|
146
166
|
|
147
|
-
[:
|
148
|
-
|
149
|
-
|
150
|
-
|
167
|
+
unless config[:debug]
|
168
|
+
[:logfile, :pidfile].each do |opt|
|
169
|
+
cliconfig[opt] = File.expand_path(cliconfig[opt]) if cliconfig[opt]
|
170
|
+
config[opt] = File.expand_path(config[opt])
|
171
|
+
config[opt] = check_dir(config[opt])
|
172
|
+
end
|
151
173
|
end
|
152
|
-
exit_with_error("#{config[:style]} is not a valid style!") unless VALID_STYLE_RE.match(config[:style])
|
153
|
-
end
|
154
|
-
|
155
|
-
# Print the error message and the usage, then exit
|
156
|
-
def exit_with_error(error_message)
|
157
|
-
puts error_message
|
158
|
-
puts usage
|
159
|
-
exit(1)
|
160
174
|
end
|
161
175
|
|
162
176
|
# Process the command given
|
163
177
|
def process(command)
|
164
|
-
config[:
|
178
|
+
if config[:debug]
|
179
|
+
run_in_foreground
|
180
|
+
elsif config[:unsupervised]
|
181
|
+
process_unsupervised_command(command)
|
182
|
+
else
|
183
|
+
process_supervised_command(command)
|
184
|
+
end
|
165
185
|
end
|
166
186
|
|
167
187
|
# Process the command given in supervised mode. All commands except start just send
|
@@ -220,7 +240,8 @@ class Style
|
|
220
240
|
end
|
221
241
|
|
222
242
|
# Reload the configuration, used when restarting. Only the following options
|
223
|
-
# take effect when reloading: config, killtime, pidfile,
|
243
|
+
# take effect when reloading: config, killtime, pidfile, adapter, handler,
|
244
|
+
# and adapter_config.
|
224
245
|
def reload_config
|
225
246
|
config.merge!(config_file_options(config[:config]))
|
226
247
|
config.merge!(config[:cliconfig])
|
@@ -241,6 +262,21 @@ class Style
|
|
241
262
|
end rescue nil
|
242
263
|
end
|
243
264
|
|
265
|
+
# Load the relevant handler and adapter and run the server
|
266
|
+
def run_child
|
267
|
+
load_handler
|
268
|
+
load_adapter
|
269
|
+
run
|
270
|
+
end
|
271
|
+
|
272
|
+
# Run the program in the foreground instead of daemonizing. Only runs on one
|
273
|
+
# port, and obviously doesn't fork.
|
274
|
+
def run_in_foreground
|
275
|
+
$STYLE_SOCKET = create_socket(config[:bind], config[:port])
|
276
|
+
config[:sockets][$STYLE_SOCKET] = config[:port]
|
277
|
+
run_child
|
278
|
+
end
|
279
|
+
|
244
280
|
# Setup the necessary signals used in supervisory mode:
|
245
281
|
#
|
246
282
|
# * CLD - Restart any dead children
|
@@ -318,10 +354,11 @@ class Style
|
|
318
354
|
def start_child(socket)
|
319
355
|
return if config[:shutdown]
|
320
356
|
pid = fork do
|
357
|
+
$STYLE_SOCKET = socket
|
321
358
|
[:HUP, :INT, :TERM, :USR1, :USR2].each{|signal| trap(signal, 'DEFAULT')}
|
322
359
|
config[:sockets].keys.each{|sock| sock.close unless sock == socket}
|
323
|
-
$0 = "#{
|
324
|
-
|
360
|
+
$0 = "#{process_name} port:#{config[:sockets][socket]}"
|
361
|
+
run_child
|
325
362
|
end
|
326
363
|
#puts "started pid #{pid}"
|
327
364
|
config[:children][pid] = socket
|
@@ -334,7 +371,7 @@ class Style
|
|
334
371
|
redirect_io
|
335
372
|
config[:number].times do |i|
|
336
373
|
port = config[:port]+i
|
337
|
-
socket =
|
374
|
+
socket = create_socket(config[:bind], port)
|
338
375
|
config[:sockets][socket] = port
|
339
376
|
config[:fork].times{start_child(socket)}
|
340
377
|
end
|
@@ -354,11 +391,17 @@ class Style
|
|
354
391
|
end
|
355
392
|
end
|
356
393
|
|
394
|
+
# Name of the Style
|
395
|
+
def process_name
|
396
|
+
"style-#{config[:adapter]}-#{config[:handler]} #{Dir.pwd}"
|
397
|
+
end
|
398
|
+
|
399
|
+
|
357
400
|
# Start all necessary children of the supervisor process (number * fork)
|
358
401
|
def supervisor_children_start
|
359
402
|
config[:number].times do |i|
|
360
403
|
port = config[:port]+i
|
361
|
-
socket =
|
404
|
+
socket = create_socket(config[:bind], port)
|
362
405
|
config[:sockets][socket] = port
|
363
406
|
config[:fork].times{start_child(socket)}
|
364
407
|
end
|
@@ -372,7 +415,7 @@ class Style
|
|
372
415
|
|
373
416
|
# Do the final setup of the supervisor process, and then loop indefinitely
|
374
417
|
def supervisor_loop
|
375
|
-
$0 = "#{
|
418
|
+
$0 = "#{process_name} supervisor"
|
376
419
|
redirect_io
|
377
420
|
supervisor_children_start
|
378
421
|
setup_supervisor_signals
|
@@ -407,16 +450,18 @@ class Style
|
|
407
450
|
<<-END
|
408
451
|
style [option value, ...] (decrement|halt|increment|restart|start|stop)
|
409
452
|
Options:
|
453
|
+
-a, --adapter Adapter/Framework to use [rails]
|
410
454
|
-b, --bind IP address to bind to [127.0.0.1]
|
411
455
|
-c, --config Location of config file [config/style.yaml]
|
412
456
|
-d, --directory Working directory [.]
|
457
|
+
-D, --debug Run the program in the foreground without forking [No]
|
413
458
|
-f, --fork Number of listners on each port [1]
|
459
|
+
-h, --handler Handler/Server to use [mongrel]
|
414
460
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
415
461
|
-l, --logfile Where to redirect STDOUT and STDERR [log/style.log]
|
416
462
|
-n, --number Number of ports to which to bind [1]
|
417
463
|
-p, --port Starting port to which to bind [9999]
|
418
464
|
-P, --pidfile Location of pid file [log/style.pid]
|
419
|
-
-s, --style Type of style to use [RailsMongrel]
|
420
465
|
-u, --unsupervised Whether to run unsupervised [No]
|
421
466
|
END
|
422
467
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-style
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2008-01-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2008-01-27 00:00:00 -08:00
|
8
8
|
summary: Supervised TCPServer, Yielding Listeners Easily
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -32,8 +32,12 @@ files:
|
|
32
32
|
- LICENSE
|
33
33
|
- README
|
34
34
|
- lib/style.rb
|
35
|
-
- lib/
|
36
|
-
- lib/
|
35
|
+
- lib/style/handler/mongrel.rb
|
36
|
+
- lib/style/handler/scgi.rb
|
37
|
+
- lib/style/handler/eventmachine.rb
|
38
|
+
- lib/style/handler/evented_mongrel.rb
|
39
|
+
- lib/style/adapter/ramaze.rb
|
40
|
+
- lib/style/adapter/rails.rb
|
37
41
|
test_files: []
|
38
42
|
|
39
43
|
rdoc_options:
|
data/lib/RailsMongrelStyle.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'yaml'
|
3
|
-
require 'mongrel'
|
4
|
-
require 'mongrel/rails'
|
5
|
-
require 'etc'
|
6
|
-
require 'cgi_multipart_eof_fix' rescue nil
|
7
|
-
|
8
|
-
module Mongrel
|
9
|
-
# Patch the Mongrel HttpServer to add a socket= method
|
10
|
-
class HttpServer
|
11
|
-
attr_writer :socket
|
12
|
-
|
13
|
-
# Keep the interface the same, but ignore the host and port and don't
|
14
|
-
# create a socket (one will be provided later)
|
15
|
-
def initialize(host, port, num_processors=950, throttle=0, timeout=60)
|
16
|
-
tries = 0
|
17
|
-
@classifier = URIClassifier.new
|
18
|
-
@host = host
|
19
|
-
@port = port
|
20
|
-
@workers = ThreadGroup.new
|
21
|
-
@throttle = throttle
|
22
|
-
@num_processors = num_processors
|
23
|
-
@timeout = timeout
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# This hooks the HTTP request into Ruby on Rails and Mongrel.
|
29
|
-
class RailsMongrelStyle
|
30
|
-
attr_reader :mongrel
|
31
|
-
|
32
|
-
# Initialzes Rails and Mongrel with the appropriate environment and settings.
|
33
|
-
def initialize(settings)
|
34
|
-
settings = {:cwd => Dir.pwd, :log_file => 'log/rails-mongrel.log',
|
35
|
-
:environment => 'production', :docroot => 'public',
|
36
|
-
:mime_map => nil, :debug => false, :includes => ["mongrel"],
|
37
|
-
:config_script => nil, :num_processors => 1024, :timeout => 0,
|
38
|
-
:user => nil, :group => nil, :prefix => nil}.merge(settings)
|
39
|
-
ENV['RAILS_ENV'] = settings[:environment]
|
40
|
-
$0 += " environment:#{ENV['RAILS_ENV']}"
|
41
|
-
@mongrel = Mongrel::Rails::RailsConfigurator.new(settings) do
|
42
|
-
listener do
|
43
|
-
mime = defaults[:mime_map] ? load_mime_map(defaults[:mime_map], mime) : {}
|
44
|
-
debug "/" if defaults[:debug]
|
45
|
-
uri defaults[:prefix] || "/", :handler => rails(:mime => mime, :prefix => defaults[:prefix])
|
46
|
-
load_plugins
|
47
|
-
run_config(defaults[:config_script]) if defaults[:config_script]
|
48
|
-
setup_rails_signals
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Set the HttpServer to the correct socket and start running the mongrel event loop.
|
54
|
-
def listen(socket)
|
55
|
-
mongrel.instance_variable_get('@rails_handler').instance_variable_get('@listener').socket = socket
|
56
|
-
mongrel.run
|
57
|
-
mongrel.join
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
|