rsense-server 0.5.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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +14 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +1 -0
- data/README.md +51 -0
- data/Rakefile +9 -0
- data/bin/_rsense.rb +115 -0
- data/config/puma.rb +2 -0
- data/lib/rsense/server/code.rb +38 -0
- data/lib/rsense/server/command/completion_result.rb +11 -0
- data/lib/rsense/server/command/special_meth.rb +18 -0
- data/lib/rsense/server/command/type_inference_method.rb +24 -0
- data/lib/rsense/server/command.rb +239 -0
- data/lib/rsense/server/config.rb +70 -0
- data/lib/rsense/server/gem_path.rb +18 -0
- data/lib/rsense/server/listeners/find_definition_event_listener.rb +91 -0
- data/lib/rsense/server/listeners/where_event_listener.rb +39 -0
- data/lib/rsense/server/load_path.rb +62 -0
- data/lib/rsense/server/options.rb +85 -0
- data/lib/rsense/server/parser.rb +17 -0
- data/lib/rsense/server/path_info.rb +17 -0
- data/lib/rsense/server/project.rb +24 -0
- data/lib/rsense/server/version.rb +5 -0
- data/lib/rsense/server.rb +18 -0
- data/rsense-server.gemspec +35 -0
- data/spec/fixtures/config_fixture/.rsense +4 -0
- data/spec/fixtures/deeply/nested/thing.rb +0 -0
- data/spec/fixtures/find_def_sample.json +10 -0
- data/spec/fixtures/sample.json +10 -0
- data/spec/fixtures/test_gem/.gitignore +22 -0
- data/spec/fixtures/test_gem/Gemfile +4 -0
- data/spec/fixtures/test_gem/LICENSE.txt +22 -0
- data/spec/fixtures/test_gem/README.md +29 -0
- data/spec/fixtures/test_gem/Rakefile +2 -0
- data/spec/fixtures/test_gem/lib/sample/version.rb +3 -0
- data/spec/fixtures/test_gem/lib/sample.rb +16 -0
- data/spec/fixtures/test_gem/sample.gemspec +23 -0
- data/spec/fixtures/test_gem/test.json +10 -0
- data/spec/rsense/server/code_spec.rb +44 -0
- data/spec/rsense/server/command/special_meth_spec.rb +23 -0
- data/spec/rsense/server/command_spec.rb +108 -0
- data/spec/rsense/server/config_spec.rb +27 -0
- data/spec/rsense/server/gem_path_spec.rb +16 -0
- data/spec/rsense/server/load_path_spec.rb +63 -0
- data/spec/rsense/server/options_spec.rb +33 -0
- data/spec/rsense/server/path_info_spec.rb +11 -0
- data/spec/rsense/server/project_spec.rb +18 -0
- data/spec/rsense/server_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/vendor/gems/puma-2.8.2-java/COPYING +55 -0
- data/vendor/gems/puma-2.8.2-java/DEPLOYMENT.md +92 -0
- data/vendor/gems/puma-2.8.2-java/Gemfile +17 -0
- data/vendor/gems/puma-2.8.2-java/History.txt +532 -0
- data/vendor/gems/puma-2.8.2-java/LICENSE +26 -0
- data/vendor/gems/puma-2.8.2-java/Manifest.txt +68 -0
- data/vendor/gems/puma-2.8.2-java/README.md +251 -0
- data/vendor/gems/puma-2.8.2-java/Rakefile +158 -0
- data/vendor/gems/puma-2.8.2-java/bin/puma +10 -0
- data/vendor/gems/puma-2.8.2-java/bin/puma-wild +17 -0
- data/vendor/gems/puma-2.8.2-java/bin/pumactl +12 -0
- data/vendor/gems/puma-2.8.2-java/docs/config.md +0 -0
- data/vendor/gems/puma-2.8.2-java/docs/nginx.md +80 -0
- data/vendor/gems/puma-2.8.2-java/docs/signals.md +42 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/PumaHttp11Service.java +17 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/ext_help.h +15 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/extconf.rb +8 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.c +1225 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.h +64 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.java.rl +161 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.rl +146 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser_common.rl +54 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/io_buffer.c +155 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/mini_ssl.c +195 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11.java +225 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11Parser.java +488 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/MiniSSL.java +289 -0
- data/vendor/gems/puma-2.8.2-java/ext/puma_http11/puma_http11.c +491 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/accept_nonblock.rb +23 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/app/status.rb +59 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/binder.rb +298 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/capistrano.rb +86 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/cli.rb +587 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/client.rb +289 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/cluster.rb +389 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/compat.rb +18 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/configuration.rb +377 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/const.rb +165 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/control_cli.rb +251 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/daemon_ext.rb +25 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/delegation.rb +11 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/detect.rb +4 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/events.rb +130 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/io_buffer.rb +7 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/java_io_buffer.rb +45 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/jruby_restart.rb +83 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/minissl.rb +148 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/null_io.rb +34 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/puma_http11.jar +0 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/rack_default.rb +7 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/rack_patch.rb +45 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/reactor.rb +183 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/runner.rb +146 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/server.rb +801 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/single.rb +102 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/tcp_logger.rb +32 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/thread_pool.rb +185 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma/util.rb +9 -0
- data/vendor/gems/puma-2.8.2-java/lib/puma.rb +14 -0
- data/vendor/gems/puma-2.8.2-java/lib/rack/handler/puma.rb +66 -0
- data/vendor/gems/puma-2.8.2-java/puma.gemspec +55 -0
- data/vendor/gems/puma-2.8.2-java/test/test_app_status.rb +92 -0
- data/vendor/gems/puma-2.8.2-java/test/test_cli.rb +173 -0
- data/vendor/gems/puma-2.8.2-java/test/test_config.rb +26 -0
- data/vendor/gems/puma-2.8.2-java/test/test_http10.rb +27 -0
- data/vendor/gems/puma-2.8.2-java/test/test_http11.rb +144 -0
- data/vendor/gems/puma-2.8.2-java/test/test_integration.rb +165 -0
- data/vendor/gems/puma-2.8.2-java/test/test_iobuffer.rb +38 -0
- data/vendor/gems/puma-2.8.2-java/test/test_minissl.rb +25 -0
- data/vendor/gems/puma-2.8.2-java/test/test_null_io.rb +31 -0
- data/vendor/gems/puma-2.8.2-java/test/test_persistent.rb +238 -0
- data/vendor/gems/puma-2.8.2-java/test/test_puma_server.rb +323 -0
- data/vendor/gems/puma-2.8.2-java/test/test_rack_handler.rb +10 -0
- data/vendor/gems/puma-2.8.2-java/test/test_rack_server.rb +141 -0
- data/vendor/gems/puma-2.8.2-java/test/test_tcp_rack.rb +42 -0
- data/vendor/gems/puma-2.8.2-java/test/test_thread_pool.rb +156 -0
- data/vendor/gems/puma-2.8.2-java/test/test_unix_socket.rb +39 -0
- data/vendor/gems/puma-2.8.2-java/test/test_ws.rb +89 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/README.md +9 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/README.md +54 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/puma +332 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/run-puma +3 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/README.md +61 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma-manager.conf +31 -0
- data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma.conf +63 -0
- data/vendor/gems/puma-2.8.2-java/tools/trickletest.rb +45 -0
- metadata +389 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'puma/runner'
|
|
2
|
+
|
|
3
|
+
module Puma
|
|
4
|
+
class Single < Runner
|
|
5
|
+
def stats
|
|
6
|
+
b = @server.backlog
|
|
7
|
+
r = @server.running
|
|
8
|
+
%Q!{ "backlog": #{b}, "running": #{r} }!
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def restart
|
|
12
|
+
@server.begin_restart
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def stop
|
|
16
|
+
@server.stop false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def halt
|
|
20
|
+
@server.halt
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def stop_blocked
|
|
24
|
+
log "- Gracefully stopping, waiting for requests to finish"
|
|
25
|
+
@control.stop(true) if @control
|
|
26
|
+
@server.stop(true)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def jruby_daemon?
|
|
30
|
+
daemon? and @cli.jruby?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def run
|
|
34
|
+
already_daemon = false
|
|
35
|
+
|
|
36
|
+
if jruby_daemon?
|
|
37
|
+
require 'puma/jruby_restart'
|
|
38
|
+
|
|
39
|
+
if JRubyRestart.daemon?
|
|
40
|
+
# load and bind before redirecting IO so errors show up on stdout/stderr
|
|
41
|
+
load_and_bind
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
already_daemon = JRubyRestart.daemon_init
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
output_header "single"
|
|
48
|
+
|
|
49
|
+
if jruby_daemon?
|
|
50
|
+
if already_daemon
|
|
51
|
+
JRubyRestart.perm_daemonize
|
|
52
|
+
else
|
|
53
|
+
pid = nil
|
|
54
|
+
|
|
55
|
+
Signal.trap "SIGUSR2" do
|
|
56
|
+
log "* Started new process #{pid} as daemon..."
|
|
57
|
+
|
|
58
|
+
# Must use exit! so we don't unwind and run the ensures
|
|
59
|
+
# that will be run by the new child (such as deleting the
|
|
60
|
+
# pidfile)
|
|
61
|
+
exit!(true)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
Signal.trap "SIGCHLD" do
|
|
65
|
+
log "! Error starting new process as daemon, exitting"
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
pid = @cli.jruby_daemon_start
|
|
70
|
+
sleep
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
load_and_bind
|
|
74
|
+
|
|
75
|
+
if daemon?
|
|
76
|
+
log "* Daemonizing..."
|
|
77
|
+
Process.daemon(true)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
@cli.write_state
|
|
82
|
+
|
|
83
|
+
start_control
|
|
84
|
+
|
|
85
|
+
@server = server = start_server
|
|
86
|
+
|
|
87
|
+
unless @options[:daemon]
|
|
88
|
+
log "Use Ctrl-C to stop"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
redirect_io
|
|
92
|
+
|
|
93
|
+
@cli.events.fire_on_booted!
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
server.run.join
|
|
97
|
+
rescue Interrupt
|
|
98
|
+
# Swallow it
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Puma
|
|
2
|
+
class TCPLogger
|
|
3
|
+
def initialize(logger, app, quiet=false)
|
|
4
|
+
@logger = logger
|
|
5
|
+
@app = app
|
|
6
|
+
@quiet = quiet
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
FORMAT = "%s - %s"
|
|
10
|
+
|
|
11
|
+
def log(who, str)
|
|
12
|
+
now = Time.now.strftime("%d/%b/%Y %H:%M:%S")
|
|
13
|
+
|
|
14
|
+
@logger.puts "#{now} - #{who} - #{str}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(env, socket)
|
|
18
|
+
who = env[Const::REMOTE_ADDR]
|
|
19
|
+
log who, "connected" unless @quiet
|
|
20
|
+
|
|
21
|
+
env['log'] = lambda { |str| log(who, str) }
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
@app.call env, socket
|
|
25
|
+
rescue Object => e
|
|
26
|
+
log who, "exception: #{e.message} (#{e.class})"
|
|
27
|
+
else
|
|
28
|
+
log who, "disconnected" unless @quiet
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Puma
|
|
4
|
+
# A simple thread pool management object.
|
|
5
|
+
#
|
|
6
|
+
class ThreadPool
|
|
7
|
+
|
|
8
|
+
# Maintain a minimum of +min+ and maximum of +max+ threads
|
|
9
|
+
# in the pool.
|
|
10
|
+
#
|
|
11
|
+
# The block passed is the work that will be performed in each
|
|
12
|
+
# thread.
|
|
13
|
+
#
|
|
14
|
+
def initialize(min, max, *extra, &block)
|
|
15
|
+
@cond = ConditionVariable.new
|
|
16
|
+
@mutex = Mutex.new
|
|
17
|
+
|
|
18
|
+
@todo = []
|
|
19
|
+
|
|
20
|
+
@spawned = 0
|
|
21
|
+
@waiting = 0
|
|
22
|
+
|
|
23
|
+
@min = Integer(min)
|
|
24
|
+
@max = Integer(max)
|
|
25
|
+
@block = block
|
|
26
|
+
@extra = extra
|
|
27
|
+
|
|
28
|
+
@shutdown = false
|
|
29
|
+
|
|
30
|
+
@trim_requested = 0
|
|
31
|
+
|
|
32
|
+
@workers = []
|
|
33
|
+
|
|
34
|
+
@auto_trim = nil
|
|
35
|
+
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
@min.times { spawn_thread }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
attr_reader :spawned, :trim_requested
|
|
42
|
+
|
|
43
|
+
# How many objects have yet to be processed by the pool?
|
|
44
|
+
#
|
|
45
|
+
def backlog
|
|
46
|
+
@mutex.synchronize { @todo.size }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# :nodoc:
|
|
50
|
+
#
|
|
51
|
+
# Must be called with @mutex held!
|
|
52
|
+
#
|
|
53
|
+
def spawn_thread
|
|
54
|
+
@spawned += 1
|
|
55
|
+
|
|
56
|
+
th = Thread.new do
|
|
57
|
+
todo = @todo
|
|
58
|
+
block = @block
|
|
59
|
+
mutex = @mutex
|
|
60
|
+
cond = @cond
|
|
61
|
+
|
|
62
|
+
extra = @extra.map { |i| i.new }
|
|
63
|
+
|
|
64
|
+
while true
|
|
65
|
+
work = nil
|
|
66
|
+
|
|
67
|
+
continue = true
|
|
68
|
+
|
|
69
|
+
mutex.synchronize do
|
|
70
|
+
while todo.empty?
|
|
71
|
+
if @trim_requested > 0
|
|
72
|
+
@trim_requested -= 1
|
|
73
|
+
continue = false
|
|
74
|
+
break
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if @shutdown
|
|
78
|
+
continue = false
|
|
79
|
+
break
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
@waiting += 1
|
|
83
|
+
cond.wait mutex
|
|
84
|
+
@waiting -= 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
work = todo.shift if continue
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
break unless continue
|
|
91
|
+
|
|
92
|
+
block.call(work, *extra)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
mutex.synchronize do
|
|
96
|
+
@spawned -= 1
|
|
97
|
+
@workers.delete th
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
@workers << th
|
|
102
|
+
|
|
103
|
+
th
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private :spawn_thread
|
|
107
|
+
|
|
108
|
+
# Add +work+ to the todo list for a Thread to pickup and process.
|
|
109
|
+
def <<(work)
|
|
110
|
+
@mutex.synchronize do
|
|
111
|
+
if @shutdown
|
|
112
|
+
raise "Unable to add work while shutting down"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
@todo << work
|
|
116
|
+
|
|
117
|
+
if @waiting == 0 and @spawned < @max
|
|
118
|
+
spawn_thread
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
@cond.signal
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# If too many threads are in the pool, tell one to finish go ahead
|
|
126
|
+
# and exit. If +force+ is true, then a trim request is requested
|
|
127
|
+
# even if all threads are being utilized.
|
|
128
|
+
#
|
|
129
|
+
def trim(force=false)
|
|
130
|
+
@mutex.synchronize do
|
|
131
|
+
if (force or @waiting > 0) and @spawned - @trim_requested > @min
|
|
132
|
+
@trim_requested += 1
|
|
133
|
+
@cond.signal
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class AutoTrim
|
|
139
|
+
def initialize(pool, timeout)
|
|
140
|
+
@pool = pool
|
|
141
|
+
@timeout = timeout
|
|
142
|
+
@running = false
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def start!
|
|
146
|
+
@running = true
|
|
147
|
+
|
|
148
|
+
@thread = Thread.new do
|
|
149
|
+
while @running
|
|
150
|
+
@pool.trim
|
|
151
|
+
sleep @timeout
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def stop
|
|
157
|
+
@running = false
|
|
158
|
+
@thread.wakeup
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def auto_trim!(timeout=5)
|
|
163
|
+
@auto_trim = AutoTrim.new(self, timeout)
|
|
164
|
+
@auto_trim.start!
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Tell all threads in the pool to exit and wait for them to finish.
|
|
168
|
+
#
|
|
169
|
+
def shutdown
|
|
170
|
+
@mutex.synchronize do
|
|
171
|
+
@shutdown = true
|
|
172
|
+
@cond.broadcast
|
|
173
|
+
|
|
174
|
+
@auto_trim.stop if @auto_trim
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Use this instead of #each so that we don't stop in the middle
|
|
178
|
+
# of each and see a mutated object mid #each
|
|
179
|
+
@workers.first.join until @workers.empty?
|
|
180
|
+
|
|
181
|
+
@spawned = 0
|
|
182
|
+
@workers = []
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'rack/handler'
|
|
2
|
+
require 'puma'
|
|
3
|
+
|
|
4
|
+
module Rack
|
|
5
|
+
module Handler
|
|
6
|
+
module Puma
|
|
7
|
+
DEFAULT_OPTIONS = {
|
|
8
|
+
:Host => '0.0.0.0',
|
|
9
|
+
:Port => 8080,
|
|
10
|
+
:Threads => '0:16',
|
|
11
|
+
:Verbose => false
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def self.run(app, options = {})
|
|
15
|
+
options = DEFAULT_OPTIONS.merge(options)
|
|
16
|
+
|
|
17
|
+
if options[:Verbose]
|
|
18
|
+
app = Rack::CommonLogger.new(app, STDOUT)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if options[:environment]
|
|
22
|
+
ENV['RACK_ENV'] = options[:environment].to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
server = ::Puma::Server.new(app)
|
|
26
|
+
min, max = options[:Threads].split(':', 2)
|
|
27
|
+
|
|
28
|
+
puts "Puma #{::Puma::Const::PUMA_VERSION} starting..."
|
|
29
|
+
puts "* Min threads: #{min}, max threads: #{max}"
|
|
30
|
+
puts "* Environment: #{ENV['RACK_ENV']}"
|
|
31
|
+
puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
|
|
32
|
+
|
|
33
|
+
server.add_tcp_listener options[:Host], options[:Port]
|
|
34
|
+
server.min_threads = min
|
|
35
|
+
server.max_threads = max
|
|
36
|
+
yield server if block_given?
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
server.run.join
|
|
40
|
+
rescue Interrupt
|
|
41
|
+
puts "* Gracefully stopping, waiting for requests to finish"
|
|
42
|
+
server.stop(true)
|
|
43
|
+
puts "* Goodbye!"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.valid_options
|
|
49
|
+
{
|
|
50
|
+
"Host=HOST" => "Hostname to listen on (default: localhost)",
|
|
51
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
52
|
+
"Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
|
|
53
|
+
"Quiet" => "Don't report each request"
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
register :puma, Puma
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# This is to trick newrelic into enabling the agent automatically.
|
|
63
|
+
module Mongrel
|
|
64
|
+
class HttpServer
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# This is only used when puma is a git dep from Bundler, so it's a little
|
|
4
|
+
# weird.
|
|
5
|
+
|
|
6
|
+
d = File.read(File.expand_path("../lib/puma/const.rb", __FILE__))
|
|
7
|
+
if d =~ /VERSION = "(\d+\.\d+\.\d+)"/
|
|
8
|
+
version = $1
|
|
9
|
+
else
|
|
10
|
+
version = "0.0.1"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Gem::Specification.new do |s|
|
|
14
|
+
s.name = "puma"
|
|
15
|
+
s.version = version
|
|
16
|
+
|
|
17
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
18
|
+
s.authors = ["Evan Phoenix"]
|
|
19
|
+
s.date = `git log --pretty="%ai" -n 1`.split(" ").first
|
|
20
|
+
s.description = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby."
|
|
21
|
+
s.email = ["evan@phx.io"]
|
|
22
|
+
s.executables = ["puma", "pumactl"]
|
|
23
|
+
s.extensions = ["ext/puma_http11/extconf.rb"]
|
|
24
|
+
s.files = `git ls-files`.split($/)
|
|
25
|
+
s.homepage = "http://puma.io"
|
|
26
|
+
s.license = "BSD"
|
|
27
|
+
s.rdoc_options = ["--main", "README.md"]
|
|
28
|
+
s.require_paths = ["lib"]
|
|
29
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
|
30
|
+
s.rubyforge_project = "puma"
|
|
31
|
+
s.rubygems_version = "1.8.25"
|
|
32
|
+
s.summary = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications"
|
|
33
|
+
s.test_files = s.files.grep(/^test/)
|
|
34
|
+
|
|
35
|
+
if s.respond_to? :specification_version then
|
|
36
|
+
s.specification_version = 3
|
|
37
|
+
|
|
38
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
39
|
+
s.add_runtime_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
|
|
40
|
+
s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
|
|
41
|
+
s.add_development_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
|
42
|
+
s.add_development_dependency(%q<hoe>, ["~> 3.6"])
|
|
43
|
+
else
|
|
44
|
+
s.add_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
|
|
45
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
|
46
|
+
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
|
47
|
+
s.add_dependency(%q<hoe>, ["~> 3.6"])
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
s.add_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
|
|
51
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
|
52
|
+
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
|
53
|
+
s.add_dependency(%q<hoe>, ["~> 3.6"])
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'rack'
|
|
3
|
+
require 'puma/app/status'
|
|
4
|
+
|
|
5
|
+
class TestAppStatus < Test::Unit::TestCase
|
|
6
|
+
class FakeServer
|
|
7
|
+
def initialize
|
|
8
|
+
@status = :running
|
|
9
|
+
@backlog = 0
|
|
10
|
+
@running = 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :status
|
|
14
|
+
attr_accessor :backlog, :running
|
|
15
|
+
|
|
16
|
+
def stop
|
|
17
|
+
@status = :stop
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def halt
|
|
21
|
+
@status = :halt
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def stats
|
|
25
|
+
"{}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def setup
|
|
30
|
+
@server = FakeServer.new
|
|
31
|
+
@app = Puma::App::Status.new(@server)
|
|
32
|
+
@app.auth_token = nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def lint(uri)
|
|
36
|
+
app = Rack::Lint.new @app
|
|
37
|
+
mock_env = Rack::MockRequest.env_for uri
|
|
38
|
+
app.call mock_env
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_bad_token
|
|
42
|
+
@app.auth_token = "abcdef"
|
|
43
|
+
|
|
44
|
+
status, _, _ = lint('/whatever')
|
|
45
|
+
|
|
46
|
+
assert_equal 403, status
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_good_token
|
|
50
|
+
@app.auth_token = "abcdef"
|
|
51
|
+
|
|
52
|
+
status, _, _ = lint('/whatever?token=abcdef')
|
|
53
|
+
|
|
54
|
+
assert_equal 404, status
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_unsupported
|
|
58
|
+
status, _, _ = lint('/not-real')
|
|
59
|
+
|
|
60
|
+
assert_equal 404, status
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_stop
|
|
64
|
+
status, _ , app = lint('/stop')
|
|
65
|
+
|
|
66
|
+
assert_equal :stop, @server.status
|
|
67
|
+
assert_equal 200, status
|
|
68
|
+
assert_equal ['{ "status": "ok" }'], app.enum_for.to_a
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_halt
|
|
72
|
+
status, _ , app = lint('/halt')
|
|
73
|
+
|
|
74
|
+
assert_equal :halt, @server.status
|
|
75
|
+
assert_equal 200, status
|
|
76
|
+
assert_equal ['{ "status": "ok" }'], app.enum_for.to_a
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_stats
|
|
80
|
+
@server.backlog = 1
|
|
81
|
+
@server.running = 9
|
|
82
|
+
status, _ , app = lint('/stats')
|
|
83
|
+
|
|
84
|
+
assert_equal 200, status
|
|
85
|
+
assert_equal ['{}'], app.enum_for.to_a
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_alternate_location
|
|
89
|
+
status, _ , _ = lint('__alternatE_location_/stats')
|
|
90
|
+
assert_equal 200, status
|
|
91
|
+
end
|
|
92
|
+
end
|