thin 1.8.0 → 2.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/.gitignore +9 -0
- data/CHANGELOG +29 -107
- data/Gemfile +8 -0
- data/README.md +44 -78
- data/Rakefile +28 -18
- data/bin/thin +4 -4
- data/examples/async.ru +21 -0
- data/examples/thin.conf.rb +39 -0
- data/lib/thin.rb +2 -44
- data/lib/thin/async.rb +108 -0
- data/lib/thin/backends/prefork.rb +44 -0
- data/lib/thin/backends/single_process.rb +28 -0
- data/lib/thin/chunked_body.rb +28 -0
- data/lib/thin/configurator.rb +118 -0
- data/lib/thin/connection.rb +246 -172
- data/lib/thin/listener.rb +114 -0
- data/lib/thin/request.rb +94 -76
- data/lib/thin/response.rb +112 -45
- data/lib/thin/runner.rb +134 -197
- data/lib/thin/server.rb +203 -252
- data/lib/thin/system.rb +49 -0
- data/lib/thin/version.rb +11 -26
- data/man/index.txt +3 -0
- data/man/thin-conf.5.ronn +121 -0
- data/man/thin.1.ronn +105 -0
- data/site/.gitignore +2 -0
- data/site/README.md +21 -0
- data/site/Rakefile +20 -0
- data/site/config.ru +4 -0
- data/site/public/images/grid.png +0 -0
- data/site/public/javascripts/dd_belatedpng.js +13 -0
- data/site/public/javascripts/modernizr-1.6.min.js +30 -0
- data/site/public/man/thin-conf.5.html +220 -0
- data/site/public/man/thin.1.html +177 -0
- data/site/site/assets/javascripts/main.coffee +2 -0
- data/site/site/assets/stylesheets/_config.scss +55 -0
- data/site/site/assets/stylesheets/main.scss +24 -0
- data/site/site/helpers.rb +17 -0
- data/site/site/layouts/base.erb +55 -0
- data/site/site/layouts/default.erb +17 -0
- data/site/site/pages/about.md +5 -0
- data/site/site/pages/index.erb +10 -0
- data/site/site/partials/.gitkeep +0 -0
- data/test/fixtures/big.txt +1 -0
- data/test/fixtures/small.txt +1 -0
- data/test/fixtures/thin.conf.rb +15 -0
- data/test/integration/async_test.rb +35 -0
- data/test/integration/big_request_test.rb +30 -0
- data/test/integration/config.ru +57 -0
- data/test/integration/daemonize_test.rb +26 -0
- data/test/integration/env_test.rb +44 -0
- data/test/integration/error_test.rb +37 -0
- data/test/integration/file_sending_test.rb +24 -0
- data/test/integration/keep_alive_test.rb +35 -0
- data/test/integration/robustness_test.rb +37 -0
- data/test/integration/single_process_test.rb +15 -0
- data/test/integration/socket_family_test.rb +38 -0
- data/test/integration/worker_test.rb +22 -0
- data/test/test_helper.rb +195 -0
- data/test/unit/configurator_test.rb +43 -0
- data/test/unit/connection_test.rb +94 -0
- data/test/unit/listener_test.rb +74 -0
- data/test/unit/request_test.rb +74 -0
- data/test/unit/response_test.rb +90 -0
- data/test/unit/server_test.rb +29 -0
- data/test/unit/system_test.rb +17 -0
- data/thin.gemspec +26 -0
- data/v2.todo +21 -0
- metadata +138 -93
- checksums.yaml +0 -7
- data/example/adapter.rb +0 -32
- data/example/async_app.ru +0 -126
- data/example/async_chat.ru +0 -247
- data/example/async_tailer.ru +0 -100
- data/example/config.ru +0 -22
- data/example/monit_sockets +0 -20
- data/example/monit_unixsock +0 -20
- data/example/myapp.rb +0 -1
- data/example/ramaze.ru +0 -12
- data/example/thin.god +0 -80
- data/example/thin_solaris_smf.erb +0 -36
- data/example/thin_solaris_smf.readme.txt +0 -150
- data/example/vlad.rake +0 -72
- data/ext/thin_parser/common.rl +0 -59
- data/ext/thin_parser/ext_help.h +0 -14
- data/ext/thin_parser/extconf.rb +0 -6
- data/ext/thin_parser/parser.c +0 -1447
- data/ext/thin_parser/parser.h +0 -49
- data/ext/thin_parser/parser.rl +0 -152
- data/ext/thin_parser/thin.c +0 -435
- data/lib/rack/adapter/loader.rb +0 -75
- data/lib/rack/adapter/rails.rb +0 -178
- data/lib/rack/handler/thin.rb +0 -38
- data/lib/thin/backends/base.rb +0 -169
- data/lib/thin/backends/swiftiply_client.rb +0 -56
- data/lib/thin/backends/tcp_server.rb +0 -34
- data/lib/thin/backends/unix_server.rb +0 -56
- data/lib/thin/command.rb +0 -53
- data/lib/thin/controllers/cluster.rb +0 -178
- data/lib/thin/controllers/controller.rb +0 -189
- data/lib/thin/controllers/service.rb +0 -76
- data/lib/thin/controllers/service.sh.erb +0 -39
- data/lib/thin/daemonizing.rb +0 -199
- data/lib/thin/headers.rb +0 -40
- data/lib/thin/logging.rb +0 -174
- data/lib/thin/stats.html.erb +0 -216
- data/lib/thin/stats.rb +0 -52
- data/lib/thin/statuses.rb +0 -48
data/example/async_chat.ru
DELETED
@@ -1,247 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rackup -s thin
|
2
|
-
#
|
3
|
-
# async_chat.ru
|
4
|
-
# raggi/thin
|
5
|
-
#
|
6
|
-
# Created by James Tucker on 2008-06-19.
|
7
|
-
# Copyright 2008 James Tucker <raggi@rubyforge.org>.
|
8
|
-
|
9
|
-
# Uncomment if appropriate for you..
|
10
|
-
EM.epoll
|
11
|
-
# EM.kqueue # bug on OS X in 0.12?
|
12
|
-
|
13
|
-
class DeferrableBody
|
14
|
-
include EventMachine::Deferrable
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@queue = []
|
18
|
-
end
|
19
|
-
|
20
|
-
def schedule_dequeue
|
21
|
-
return unless @body_callback
|
22
|
-
EventMachine::next_tick do
|
23
|
-
next unless body = @queue.shift
|
24
|
-
body.each do |chunk|
|
25
|
-
@body_callback.call(chunk)
|
26
|
-
end
|
27
|
-
schedule_dequeue unless @queue.empty?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def call(body)
|
32
|
-
@queue << body
|
33
|
-
schedule_dequeue
|
34
|
-
end
|
35
|
-
|
36
|
-
def each &blk
|
37
|
-
@body_callback = blk
|
38
|
-
schedule_dequeue
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
class Chat
|
44
|
-
|
45
|
-
module UserBody
|
46
|
-
attr_accessor :username
|
47
|
-
end
|
48
|
-
|
49
|
-
def initialize
|
50
|
-
@users = {}
|
51
|
-
end
|
52
|
-
|
53
|
-
def render_page
|
54
|
-
[] << <<-EOPAGE
|
55
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
56
|
-
<html>
|
57
|
-
<head>
|
58
|
-
<style>
|
59
|
-
body {
|
60
|
-
font-family: sans-serif;
|
61
|
-
margin: 0;
|
62
|
-
padding: 0;
|
63
|
-
margin-top: 4em;
|
64
|
-
margin-bottom: 1em;
|
65
|
-
}
|
66
|
-
#header {
|
67
|
-
background: silver;
|
68
|
-
height: 4em;
|
69
|
-
width: 100%;
|
70
|
-
position: fixed;
|
71
|
-
top: 0px;
|
72
|
-
border-bottom: 1px solid black;
|
73
|
-
padding-left: 0.5em;
|
74
|
-
}
|
75
|
-
#messages {
|
76
|
-
width: 100%;
|
77
|
-
height: 100%;
|
78
|
-
}
|
79
|
-
.message {
|
80
|
-
margin-left: 1em;
|
81
|
-
}
|
82
|
-
#send_form {
|
83
|
-
position: fixed;
|
84
|
-
bottom: 0px;
|
85
|
-
height: 1em;
|
86
|
-
width: 100%;
|
87
|
-
}
|
88
|
-
#message_box {
|
89
|
-
background: silver;
|
90
|
-
width: 100%;
|
91
|
-
border: 0px;
|
92
|
-
border-top: 1px solid black;
|
93
|
-
}
|
94
|
-
.gray {
|
95
|
-
color: gray;
|
96
|
-
}
|
97
|
-
</style>
|
98
|
-
<script type="text/javascript" src="http://ra66i.org/tmp/jquery-1.2.6.min.js"></script>
|
99
|
-
<script type="text/javascript">
|
100
|
-
XHR = function() {
|
101
|
-
var request = false;
|
102
|
-
try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {
|
103
|
-
try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch(e1) {
|
104
|
-
try { request = new XMLHttpRequest(); } catch(e2) {
|
105
|
-
return false;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
}
|
109
|
-
return request;
|
110
|
-
}
|
111
|
-
scroll = function() {
|
112
|
-
window.scrollBy(0,50);
|
113
|
-
setTimeout('scroll()',100);
|
114
|
-
}
|
115
|
-
focus = function() {
|
116
|
-
$('#message_box').focus();
|
117
|
-
}
|
118
|
-
send_message = function(message_box) {
|
119
|
-
xhr = XHR();
|
120
|
-
xhr.open("POST", "/", true);
|
121
|
-
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
122
|
-
xhr.setRequestHeader("X_REQUESTED_WITH", "XMLHttpRequest");
|
123
|
-
xhr.send("message="+escape(message_box.value));
|
124
|
-
scroll();
|
125
|
-
message_box.value = '';
|
126
|
-
focus();
|
127
|
-
return false;
|
128
|
-
}
|
129
|
-
new_message = function(username, message) {
|
130
|
-
// TODO html escape message
|
131
|
-
formatted_message = "<div class='message'>" + username + ": " + message + "</div>";
|
132
|
-
messages_div = $('#messages');
|
133
|
-
$(formatted_message).appendTo(messages_div);
|
134
|
-
scroll();
|
135
|
-
return true;
|
136
|
-
}
|
137
|
-
</script>
|
138
|
-
<title>Async Chat</title>
|
139
|
-
</head>
|
140
|
-
<body>
|
141
|
-
<div id="header">
|
142
|
-
<h1>Async Chat</h1>
|
143
|
-
</div>
|
144
|
-
<div id="messages" onclick="focus();">
|
145
|
-
<span class="gray">Your first message will become your nickname!</span>
|
146
|
-
<span>Users: #{@users.map{|k,u|u.username}.join(', ')}</span>
|
147
|
-
</div>
|
148
|
-
<form id="send_form" onSubmit="return send_message(this.message)">
|
149
|
-
<input type="text" id="message_box" name="message"></input>
|
150
|
-
</form>
|
151
|
-
<script type="text/javascript">focus();</script>
|
152
|
-
</body>
|
153
|
-
</html>
|
154
|
-
EOPAGE
|
155
|
-
end
|
156
|
-
|
157
|
-
def register_user(user_id, renderer)
|
158
|
-
body = create_user(user_id)
|
159
|
-
body.call render_page
|
160
|
-
body.errback { delete_user user_id }
|
161
|
-
body.callback { delete_user user_id }
|
162
|
-
|
163
|
-
EventMachine::next_tick do
|
164
|
-
renderer.call [200, {'Content-Type' => 'text/html'}, body]
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def new_message(user_id, message)
|
169
|
-
return unless @users[user_id]
|
170
|
-
if @users[user_id].username == :anonymous
|
171
|
-
username = unique_username(message)
|
172
|
-
log "User: #{user_id} is #{username}"
|
173
|
-
@users[user_id].username = message
|
174
|
-
message = "<span class='gray'>-> #{username} signed on.</span>"
|
175
|
-
end
|
176
|
-
username ||= @users[user_id].username
|
177
|
-
log "User: #{username} sent: #{message}"
|
178
|
-
@users.each do |id, body|
|
179
|
-
EventMachine::next_tick { body.call [js_message(username, message)] }
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
private
|
184
|
-
def unique_username(name)
|
185
|
-
name.concat('_') while @users.any? { |id,u| name == u.username }
|
186
|
-
name
|
187
|
-
end
|
188
|
-
|
189
|
-
def log(str)
|
190
|
-
print str, "\n"
|
191
|
-
end
|
192
|
-
|
193
|
-
def add_user(id, body)
|
194
|
-
@users[id] = body
|
195
|
-
end
|
196
|
-
|
197
|
-
def delete_user(id)
|
198
|
-
message = "User: #{id} - #{@users[id].username if @users[id]} disconnected."
|
199
|
-
log message
|
200
|
-
new_message(id, message)
|
201
|
-
@users.delete id
|
202
|
-
end
|
203
|
-
|
204
|
-
def js_message(username, message)
|
205
|
-
%(<script type="text/javascript">new_message("#{username}","#{message}");</script>)
|
206
|
-
end
|
207
|
-
|
208
|
-
def create_user(id)
|
209
|
-
message = "User: #{id} connected."
|
210
|
-
log message
|
211
|
-
new_message(id, message)
|
212
|
-
body = DeferrableBody.new
|
213
|
-
body.extend UserBody
|
214
|
-
body.username = :anonymous
|
215
|
-
add_user(id, body)
|
216
|
-
body
|
217
|
-
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
class AsyncChat
|
222
|
-
|
223
|
-
AsyncResponse = [-1, {}, []].freeze
|
224
|
-
AjaxResponse = [200, {}, []].freeze
|
225
|
-
|
226
|
-
def initialize
|
227
|
-
@chat = Chat.new
|
228
|
-
end
|
229
|
-
|
230
|
-
def call(env)
|
231
|
-
request = Rack::Request.new(env)
|
232
|
-
# TODO - cookie me, baby
|
233
|
-
user_id = request.env['REMOTE_ADDR']
|
234
|
-
if request.xhr?
|
235
|
-
message = request['message']
|
236
|
-
@chat.new_message(user_id, Rack::Utils.escape_html(message))
|
237
|
-
AjaxResponse
|
238
|
-
else
|
239
|
-
renderer = request.env['async.callback']
|
240
|
-
@chat.register_user(user_id, renderer)
|
241
|
-
AsyncResponse
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
end
|
246
|
-
|
247
|
-
run AsyncChat.new
|
data/example/async_tailer.ru
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rackup -s thin
|
2
|
-
#
|
3
|
-
# async_tailer.ru
|
4
|
-
# raggi/thin
|
5
|
-
#
|
6
|
-
# Tested with 150 spawned tails on OS X
|
7
|
-
#
|
8
|
-
# Created by James Tucker on 2008-06-18.
|
9
|
-
# Copyright 2008 James Tucker <raggi@rubyforge.org>.
|
10
|
-
|
11
|
-
# Uncomment if appropriate for you..
|
12
|
-
# EM.epoll
|
13
|
-
# EM.kqueue
|
14
|
-
|
15
|
-
class DeferrableBody
|
16
|
-
include EventMachine::Deferrable
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@queue = []
|
20
|
-
# make sure to flush out the queue before closing the connection
|
21
|
-
callback{
|
22
|
-
until @queue.empty?
|
23
|
-
@queue.shift.each{|chunk| @body_callback.call(chunk) }
|
24
|
-
end
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def schedule_dequeue
|
29
|
-
return unless @body_callback
|
30
|
-
EventMachine::next_tick do
|
31
|
-
next unless body = @queue.shift
|
32
|
-
body.each do |chunk|
|
33
|
-
@body_callback.call(chunk)
|
34
|
-
end
|
35
|
-
schedule_dequeue unless @queue.empty?
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def call(body)
|
40
|
-
@queue << body
|
41
|
-
schedule_dequeue
|
42
|
-
end
|
43
|
-
|
44
|
-
def each &blk
|
45
|
-
@body_callback = blk
|
46
|
-
schedule_dequeue
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
module TailRenderer
|
52
|
-
attr_accessor :callback
|
53
|
-
|
54
|
-
def receive_data(data)
|
55
|
-
@callback.call([data])
|
56
|
-
end
|
57
|
-
|
58
|
-
def unbind
|
59
|
-
@callback.succeed
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class AsyncTailer
|
64
|
-
|
65
|
-
AsyncResponse = [-1, {}, []].freeze
|
66
|
-
|
67
|
-
def call(env)
|
68
|
-
|
69
|
-
body = DeferrableBody.new
|
70
|
-
|
71
|
-
EventMachine::next_tick do
|
72
|
-
|
73
|
-
env['async.callback'].call [200, {'Content-Type' => 'text/html'}, body]
|
74
|
-
|
75
|
-
body.call ["<h1>Async Tailer</h1><pre>"]
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
EventMachine::popen('tail -f /var/log/system.log', TailRenderer) do |t|
|
80
|
-
|
81
|
-
t.callback = body
|
82
|
-
|
83
|
-
# If for some reason we 'complete' body, close the tail.
|
84
|
-
body.callback do
|
85
|
-
t.close_connection
|
86
|
-
end
|
87
|
-
|
88
|
-
# If for some reason the client disconnects, close the tail.
|
89
|
-
body.errback do
|
90
|
-
t.close_connection
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
AsyncResponse
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
run AsyncTailer.new
|
data/example/config.ru
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# Run with: rackup -s thin
|
2
|
-
# then browse to http://localhost:9292
|
3
|
-
# Or with: thin start -R config.ru
|
4
|
-
# then browse to http://localhost:3000
|
5
|
-
#
|
6
|
-
# Check Rack::Builder doc for more details on this file format:
|
7
|
-
# http://rack.rubyforge.org/doc/classes/Rack/Builder.html
|
8
|
-
require 'thin'
|
9
|
-
|
10
|
-
app = proc do |env|
|
11
|
-
# Response body has to respond to each and yield strings
|
12
|
-
# See Rack specs for more info: http://rack.rubyforge.org/doc/files/SPEC.html
|
13
|
-
body = ['hi!']
|
14
|
-
|
15
|
-
[
|
16
|
-
200, # Status code
|
17
|
-
{ 'Content-Type' => 'text/html' }, # Reponse headers
|
18
|
-
body # Body of the response
|
19
|
-
]
|
20
|
-
end
|
21
|
-
|
22
|
-
run app
|
data/example/monit_sockets
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
check process blog1
|
2
|
-
with pidfile /u/apps/blog/shared/pids/thin.14000.pid
|
3
|
-
start program = "ruby thin start -d -e production -u nobody -g nobody -p 14000 -a 127.0.0.1 -P tmp/pids/thin.14000.pid -c /u/apps/blog/current"
|
4
|
-
stop program = "ruby thin stop -P /u/apps/blog/shared/pids/thin.14000.pid"
|
5
|
-
if totalmem > 90.0 MB for 5 cycles then restart
|
6
|
-
if failed port 14000 then restart
|
7
|
-
if cpu usage > 95% for 3 cycles then restart
|
8
|
-
if 5 restarts within 5 cycles then timeout
|
9
|
-
group blog
|
10
|
-
|
11
|
-
check process blog2
|
12
|
-
with pidfile /u/apps/blog/shared/pids/thin.14001.pid
|
13
|
-
start program = "ruby thin start -d -e production -u nobody -g nobody -p 14001 -a 127.0.0.1 -P tmp/pids/thin.14001.pid -c /u/apps/blog/current"
|
14
|
-
stop program = "ruby thin stop -P /u/apps/blog/shared/pids/thin.14001.pid"
|
15
|
-
if totalmem > 90.0 MB for 5 cycles then restart
|
16
|
-
if failed port 14001 then restart
|
17
|
-
if cpu usage > 95% for 3 cycles then restart
|
18
|
-
if 5 restarts within 5 cycles then timeout
|
19
|
-
group blog
|
20
|
-
|
data/example/monit_unixsock
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
check process blog1
|
2
|
-
with pidfile /u/apps/blog/shared/pids/thin.1.pid
|
3
|
-
start program = "ruby thin start -d -e production -S /u/apps/blog/shared/pids/thin.1.sock -P tmp/pids/thin.1.pid -c /u/apps/blog/current"
|
4
|
-
stop program = "ruby thin stop -P /u/apps/blog/shared/pids/thin.1.pid"
|
5
|
-
if totalmem > 90.0 MB for 5 cycles then restart
|
6
|
-
if failed unixsocket /u/apps/blog/shared/pids/thin.1.sock then restart
|
7
|
-
if cpu usage > 95% for 3 cycles then restart
|
8
|
-
if 5 restarts within 5 cycles then timeout
|
9
|
-
group blog
|
10
|
-
|
11
|
-
check process blog2
|
12
|
-
with pidfile /u/apps/blog/shared/pids/thin.2.pid
|
13
|
-
start program = "ruby thin start -d -e production -S /u/apps/blog/shared/pids/thin.2.sock -P tmp/pids/thin.2.pid -c /u/apps/blog/current"
|
14
|
-
stop program = "ruby thin stop -P /u/apps/blog/shared/pids/thin.2.pid"
|
15
|
-
if totalmem > 90.0 MB for 5 cycles then restart
|
16
|
-
if failed unixsocket /u/apps/blog/shared/pids/thin.2.sock then restart
|
17
|
-
if cpu usage > 95% for 3 cycles then restart
|
18
|
-
if 5 restarts within 5 cycles then timeout
|
19
|
-
group blog
|
20
|
-
|
data/example/myapp.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Myapp = lambda { |env| [200, {}, 'this is my app!'] }
|
data/example/ramaze.ru
DELETED
data/example/thin.god
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
# == God config file
|
2
|
-
# http://god.rubyforge.org/
|
3
|
-
# Authors: Gump and michael@glauche.de
|
4
|
-
#
|
5
|
-
# Config file for god that configures watches for each instance of a thin server for
|
6
|
-
# each thin configuration file found in /etc/thin.
|
7
|
-
# In order to get it working on Ubuntu, I had to make a change to god as noted at
|
8
|
-
# the following blog:
|
9
|
-
# http://blog.alexgirard.com/ruby-one-line-to-save-god/
|
10
|
-
#
|
11
|
-
require 'yaml'
|
12
|
-
|
13
|
-
config_path = "/etc/thin"
|
14
|
-
|
15
|
-
Dir[config_path + "/*.yml"].each do |file|
|
16
|
-
config = YAML.load_file(file)
|
17
|
-
num_servers = config["servers"] ||= 1
|
18
|
-
|
19
|
-
(0...num_servers).each do |i|
|
20
|
-
# UNIX socket cluster use number 0 to 2 (for 3 servers)
|
21
|
-
# and tcp cluster use port number 3000 to 3002.
|
22
|
-
number = config['socket'] ? i : (config['port'] + i)
|
23
|
-
|
24
|
-
God.watch do |w|
|
25
|
-
w.group = "thin-" + File.basename(file, ".yml")
|
26
|
-
w.name = w.group + "-#{number}"
|
27
|
-
|
28
|
-
w.interval = 30.seconds
|
29
|
-
|
30
|
-
w.uid = config["user"]
|
31
|
-
w.gid = config["group"]
|
32
|
-
|
33
|
-
w.start = "thin start -C #{file} -o #{number}"
|
34
|
-
w.start_grace = 10.seconds
|
35
|
-
|
36
|
-
w.stop = "thin stop -C #{file} -o #{number}"
|
37
|
-
w.stop_grace = 10.seconds
|
38
|
-
|
39
|
-
w.restart = "thin restart -C #{file} -o #{number}"
|
40
|
-
|
41
|
-
pid_path = config["chdir"] + "/" + config["pid"]
|
42
|
-
ext = File.extname(pid_path)
|
43
|
-
|
44
|
-
w.pid_file = pid_path.gsub(/#{ext}$/, ".#{number}#{ext}")
|
45
|
-
|
46
|
-
w.behavior(:clean_pid_file)
|
47
|
-
|
48
|
-
w.start_if do |start|
|
49
|
-
start.condition(:process_running) do |c|
|
50
|
-
c.interval = 5.seconds
|
51
|
-
c.running = false
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
w.restart_if do |restart|
|
56
|
-
restart.condition(:memory_usage) do |c|
|
57
|
-
c.above = 150.megabytes
|
58
|
-
c.times = [3,5] # 3 out of 5 intervals
|
59
|
-
end
|
60
|
-
|
61
|
-
restart.condition(:cpu_usage) do |c|
|
62
|
-
c.above = 50.percent
|
63
|
-
c.times = 5
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
w.lifecycle do |on|
|
68
|
-
on.condition(:flapping) do |c|
|
69
|
-
c.to_state = [:start, :restart]
|
70
|
-
c.times = 5
|
71
|
-
c.within = 5.minutes
|
72
|
-
c.transition = :unmonitored
|
73
|
-
c.retry_in = 10.minutes
|
74
|
-
c.retry_times = 5
|
75
|
-
c.retry_within = 2.hours
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|