tracks 0.1.0 → 0.2.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/lib/tracks.rb +35 -30
- metadata +6 -6
data/lib/tracks.rb
CHANGED
@@ -169,18 +169,21 @@ class Tracks
|
|
169
169
|
# responding to #call. options should be a hash, with the following optional
|
170
170
|
# keys, as symbols
|
171
171
|
#
|
172
|
-
# [:host]
|
173
|
-
# [:port]
|
174
|
-
# [:read_timeout]
|
175
|
-
#
|
172
|
+
# [:host] the host to listen on, defaults to 0.0.0.0
|
173
|
+
# [:port] the port to listen on, defaults to 9292
|
174
|
+
# [:read_timeout] the maximum amount of time, in seconds, to wait on idle
|
175
|
+
# connections, defaults to 30
|
176
|
+
# [:shutdown_timeout] the maximum amount of time, in seconds, to wait for
|
177
|
+
# in process requests to complete when signalled to shut
|
178
|
+
# down, defaults to 30
|
176
179
|
#
|
177
180
|
def initialize(app, options={})
|
178
181
|
@host = options[:host] || options[:Host] || "0.0.0.0"
|
179
182
|
@port = (options[:port] || options[:Port] || "9292").to_s
|
180
183
|
@read_timeout = options[:read_timeout] || 30
|
184
|
+
@shutdown_timeout = options[:shutdown_timeout] || 30
|
181
185
|
@app = app
|
182
186
|
@shutdown_signal, @signal_shutdown = IO.pipe
|
183
|
-
@threads = ThreadGroup.new
|
184
187
|
end
|
185
188
|
|
186
189
|
# :call-seq: Tracks.run(rack_app[, options]) -> nil
|
@@ -191,36 +194,25 @@ class Tracks
|
|
191
194
|
new(app, options).listen
|
192
195
|
end
|
193
196
|
|
194
|
-
# :call-seq: Tracks.shutdown
|
197
|
+
# :call-seq: Tracks.shutdown -> nil
|
195
198
|
#
|
196
|
-
#
|
197
|
-
# each to gracefully shutdown. See #shutdown for more.
|
199
|
+
# Signal all running Tracks servers to shutdown.
|
198
200
|
#
|
199
|
-
def self.shutdown
|
200
|
-
running.dup.
|
201
|
+
def self.shutdown
|
202
|
+
running.dup.each {|s| s.shutdown} && nil
|
201
203
|
end
|
202
204
|
|
203
|
-
# :call-seq: server.shutdown
|
205
|
+
# :call-seq: server.shutdown -> nil
|
204
206
|
#
|
205
|
-
#
|
206
|
-
# shutdown. Returns true on graceful shutdown, false otherwise.
|
207
|
+
# Signal the server to shut down.
|
207
208
|
#
|
208
|
-
|
209
|
-
#
|
210
|
-
# A return value of false indicates there were threads left running after
|
211
|
-
# wait_time had expired which were forcibly killed. This may leave resources
|
212
|
-
# in an inconsistant state, and it is advised you exit the process in this
|
213
|
-
# case (likely what you were planning anyway).
|
214
|
-
#
|
215
|
-
def shutdown(wait=30)
|
209
|
+
def shutdown
|
216
210
|
@shutdown = true
|
217
211
|
self.class.running.delete(self)
|
218
|
-
@signal_shutdown << "x"
|
219
|
-
wait -= sleep 1 until @threads.list.empty? || wait <= 0
|
220
|
-
@threads.list.each {|thread| thread.kill}.empty?
|
212
|
+
@signal_shutdown << "x" && nil
|
221
213
|
end
|
222
214
|
|
223
|
-
# :call-seq: server.listen([socket_server]) ->
|
215
|
+
# :call-seq: server.listen([socket_server]) -> bool
|
224
216
|
#
|
225
217
|
# Start listening for/accepting connections on socket_server. socket_server
|
226
218
|
# defaults to a TCP server listening on the host and port supplied to ::new.
|
@@ -231,19 +223,27 @@ class Tracks
|
|
231
223
|
# This method will block until #shutdown is called. The socket_server will
|
232
224
|
# be closed when this method returns.
|
233
225
|
#
|
226
|
+
# A return value of false indicates there were threads left running after
|
227
|
+
# shutdown_timeout had expired which were forcibly killed. This may leave
|
228
|
+
# resources in an inconsistant state, and it is advised you exit the process
|
229
|
+
# in this case (likely what you were planning anyway).
|
230
|
+
#
|
234
231
|
def listen(server=TCPServer.new(@host, @port))
|
235
232
|
@shutdown = false
|
236
233
|
server.listen(1024) if server.respond_to?(:listen)
|
237
234
|
@port, @host = server.addr[1,2].map{|e| e.to_s} if server.respond_to?(:addr)
|
238
235
|
servers = [server, @shutdown_signal]
|
236
|
+
threads = ThreadGroup.new
|
239
237
|
self.class.running << self
|
240
238
|
puts "Tracks HTTP server available at #{@host}:#{@port}"
|
241
239
|
while select(servers, nil, nil) && !@shutdown
|
242
|
-
|
240
|
+
threads.add(Thread.new(server.accept) {|sock| on_connection(sock)})
|
243
241
|
end
|
244
|
-
@shutdown_signal.sysread(1) && nil
|
245
|
-
ensure
|
246
242
|
server.close
|
243
|
+
wait = @shutdown_timeout
|
244
|
+
wait -= sleep 1 until threads.list.empty? || wait <= 0
|
245
|
+
@shutdown_signal.sysread(1)
|
246
|
+
threads.list.each {|thread| thread.kill}.empty?
|
247
247
|
end
|
248
248
|
|
249
249
|
# :call-seq: server.on_connection(socket) -> nil
|
@@ -260,10 +260,14 @@ class Tracks
|
|
260
260
|
def on_connection(socket)
|
261
261
|
parser = HTTPTools::Parser.new
|
262
262
|
buffer = ""
|
263
|
-
sockets = [socket]
|
263
|
+
sockets = [socket, @shutdown_signal]
|
264
|
+
idle = false
|
264
265
|
reader = Proc.new do
|
265
266
|
readable, = select(sockets, nil, nil, @read_timeout)
|
266
267
|
return unless readable
|
268
|
+
sockets.delete(@shutdown_signal) if @shutdown
|
269
|
+
return if idle && @shutdown
|
270
|
+
idle = false
|
267
271
|
begin
|
268
272
|
socket.sysread(16384, buffer)
|
269
273
|
parser << buffer
|
@@ -301,11 +305,12 @@ class Tracks
|
|
301
305
|
body.each {|chunk| socket << chunk}
|
302
306
|
body.close if body.respond_to?(:close)
|
303
307
|
|
304
|
-
if keep_alive
|
308
|
+
if keep_alive && !@shutdown
|
305
309
|
reader.call until parser.finished?
|
306
310
|
input.reset
|
307
311
|
remainder = parser.rest.lstrip
|
308
312
|
parser.reset << remainder
|
313
|
+
idle = true
|
309
314
|
else
|
310
315
|
break
|
311
316
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-26 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
|
-
requirement: &
|
16
|
+
requirement: &70193797609180 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70193797609180
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: http_tools
|
27
|
-
requirement: &
|
27
|
+
requirement: &70193797608700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 0.4.1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70193797608700
|
36
36
|
description: A bare-bones Ruby HTTP server that talks Rack and uses a thread per connection
|
37
37
|
model of concurrency.
|
38
38
|
email: mat@sourcetagsandcodes.com
|