puma 5.6.4 → 6.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +275 -4
  3. data/LICENSE +0 -0
  4. data/README.md +60 -20
  5. data/bin/puma-wild +1 -1
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +34 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +1 -3
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +1 -1
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +0 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +1 -2
  24. data/docs/testing_benchmarks_local_files.md +150 -0
  25. data/docs/testing_test_rackup_ci_files.md +36 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +18 -10
  29. data/ext/puma_http11/http11_parser.c +1 -1
  30. data/ext/puma_http11/http11_parser.h +1 -1
  31. data/ext/puma_http11/http11_parser.java.rl +2 -2
  32. data/ext/puma_http11/http11_parser.rl +2 -2
  33. data/ext/puma_http11/http11_parser_common.rl +2 -2
  34. data/ext/puma_http11/mini_ssl.c +93 -26
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +166 -65
  39. data/ext/puma_http11/puma_http11.c +17 -9
  40. data/lib/puma/app/status.rb +7 -4
  41. data/lib/puma/binder.rb +49 -52
  42. data/lib/puma/cli.rb +12 -18
  43. data/lib/puma/client.rb +69 -23
  44. data/lib/puma/cluster/worker.rb +18 -11
  45. data/lib/puma/cluster/worker_handle.rb +4 -1
  46. data/lib/puma/cluster.rb +33 -30
  47. data/lib/puma/commonlogger.rb +21 -14
  48. data/lib/puma/configuration.rb +76 -58
  49. data/lib/puma/const.rb +129 -92
  50. data/lib/puma/control_cli.rb +21 -18
  51. data/lib/puma/detect.rb +4 -0
  52. data/lib/puma/dsl.rb +187 -49
  53. data/lib/puma/error_logger.rb +18 -9
  54. data/lib/puma/events.rb +6 -126
  55. data/lib/puma/io_buffer.rb +39 -4
  56. data/lib/puma/jruby_restart.rb +2 -1
  57. data/lib/puma/json_serialization.rb +0 -0
  58. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  59. data/lib/puma/launcher.rb +113 -175
  60. data/lib/puma/log_writer.rb +147 -0
  61. data/lib/puma/minissl/context_builder.rb +24 -12
  62. data/lib/puma/minissl.rb +108 -15
  63. data/lib/puma/null_io.rb +5 -0
  64. data/lib/puma/plugin/systemd.rb +90 -0
  65. data/lib/puma/plugin/tmp_restart.rb +1 -1
  66. data/lib/puma/plugin.rb +0 -0
  67. data/lib/puma/rack/builder.rb +6 -6
  68. data/lib/puma/rack/urlmap.rb +0 -0
  69. data/lib/puma/rack_default.rb +19 -4
  70. data/lib/puma/reactor.rb +19 -10
  71. data/lib/puma/request.rb +365 -166
  72. data/lib/puma/runner.rb +52 -20
  73. data/lib/puma/sd_notify.rb +149 -0
  74. data/lib/puma/server.rb +73 -73
  75. data/lib/puma/single.rb +13 -11
  76. data/lib/puma/state_file.rb +2 -4
  77. data/lib/puma/thread_pool.rb +23 -19
  78. data/lib/puma/util.rb +12 -14
  79. data/lib/puma.rb +12 -11
  80. data/lib/rack/handler/puma.rb +113 -86
  81. data/tools/Dockerfile +0 -0
  82. data/tools/trickletest.rb +0 -0
  83. metadata +10 -5
  84. data/lib/puma/queue_close.rb +0 -26
  85. data/lib/puma/systemd.rb +0 -46
@@ -2,27 +2,29 @@
2
2
 
3
3
  module Puma
4
4
  class Cluster < Puma::Runner
5
+ #—————————————————————— DO NOT USE — this class is for internal use only ———
6
+
7
+
5
8
  # This class is instantiated by the `Puma::Cluster` and represents a single
6
9
  # worker process.
7
10
  #
8
11
  # At the core of this class is running an instance of `Puma::Server` which
9
12
  # gets created via the `start_server` method from the `Puma::Runner` class
10
13
  # that this inherits from.
11
- class Worker < Puma::Runner
14
+ class Worker < Puma::Runner # :nodoc:
12
15
  attr_reader :index, :master
13
16
 
14
17
  def initialize(index:, master:, launcher:, pipes:, server: nil)
15
- super launcher, launcher.events
18
+ super(launcher)
16
19
 
17
20
  @index = index
18
21
  @master = master
19
- @launcher = launcher
20
- @options = launcher.options
21
22
  @check_pipe = pipes[:check_pipe]
22
23
  @worker_write = pipes[:worker_write]
23
24
  @fork_pipe = pipes[:fork_pipe]
24
25
  @wakeup = pipes[:wakeup]
25
26
  @server = server
27
+ @hook_data = {}
26
28
  end
27
29
 
28
30
  def run
@@ -52,13 +54,14 @@ module Puma
52
54
 
53
55
  # Invoke any worker boot hooks so they can get
54
56
  # things in shape before booting the app.
55
- @launcher.config.run_hooks :before_worker_boot, index, @launcher.events
57
+ @config.run_hooks(:before_worker_boot, index, @log_writer, @hook_data)
56
58
 
57
59
  begin
58
60
  server = @server ||= start_server
59
61
  rescue Exception => e
60
62
  log "! Unable to start worker"
61
- log e.backtrace[0]
63
+ log e
64
+ log e.backtrace.join("\n ")
62
65
  exit 1
63
66
  end
64
67
 
@@ -83,8 +86,7 @@ module Puma
83
86
  if restart_server.length > 0
84
87
  restart_server.clear
85
88
  server.begin_restart(true)
86
- @launcher.config.run_hooks :before_refork, nil, @launcher.events
87
- Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
89
+ @config.run_hooks(:before_refork, nil, @log_writer, @hook_data)
88
90
  end
89
91
  elsif idx == 0 # restart server
90
92
  restart_server << true << false
@@ -113,6 +115,11 @@ module Puma
113
115
 
114
116
  while restart_server.pop
115
117
  server_thread = server.run
118
+
119
+ if @log_writer.debug? && index == 0
120
+ debug_loaded_extensions "Loaded Extensions - worker 0:"
121
+ end
122
+
116
123
  stat_thread ||= Thread.new(@worker_write) do |io|
117
124
  Puma.set_thread_name "stat pld"
118
125
  base_payload = "p#{Process.pid}"
@@ -138,7 +145,7 @@ module Puma
138
145
 
139
146
  # Invoke any worker shutdown hooks so they can prevent the worker
140
147
  # exiting until any background operations are completed
141
- @launcher.config.run_hooks :before_worker_shutdown, index, @launcher.events
148
+ @config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
142
149
  ensure
143
150
  @worker_write << "t#{Process.pid}\n" rescue nil
144
151
  @worker_write.close
@@ -147,7 +154,7 @@ module Puma
147
154
  private
148
155
 
149
156
  def spawn_worker(idx)
150
- @launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
157
+ @config.run_hooks(:before_worker_fork, idx, @log_writer, @hook_data)
151
158
 
152
159
  pid = fork do
153
160
  new_worker = Worker.new index: idx,
@@ -165,7 +172,7 @@ module Puma
165
172
  exit! 1
166
173
  end
167
174
 
168
- @launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
175
+ @config.run_hooks(:after_worker_fork, idx, @log_writer, @hook_data)
169
176
  pid
170
177
  end
171
178
  end
@@ -2,12 +2,15 @@
2
2
 
3
3
  module Puma
4
4
  class Cluster < Runner
5
+ #—————————————————————— DO NOT USE — this class is for internal use only ———
6
+
7
+
5
8
  # This class represents a worker process from the perspective of the puma
6
9
  # master process. It contains information about the process and its health
7
10
  # and it exposes methods to control the process via IPC. It does not
8
11
  # include the actual logic executed by the worker process itself. For that,
9
12
  # see Puma::Cluster::Worker.
10
- class WorkerHandle
13
+ class WorkerHandle # :nodoc:
11
14
  def initialize(idx, pid, phase, options)
12
15
  @index = idx
13
16
  @pid = pid
data/lib/puma/cluster.rb CHANGED
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'puma/runner'
4
- require 'puma/util'
5
- require 'puma/plugin'
6
- require 'puma/cluster/worker_handle'
7
- require 'puma/cluster/worker'
8
-
9
- require 'time'
3
+ require_relative 'runner'
4
+ require_relative 'util'
5
+ require_relative 'plugin'
6
+ require_relative 'cluster/worker_handle'
7
+ require_relative 'cluster/worker'
10
8
 
11
9
  module Puma
12
10
  # This class is instantiated by the `Puma::Launcher` and used
@@ -17,8 +15,8 @@ module Puma
17
15
  # via the `spawn_workers` method call. Each worker will have it's own
18
16
  # instance of a `Puma::Server`.
19
17
  class Cluster < Runner
20
- def initialize(cli, events)
21
- super cli, events
18
+ def initialize(launcher)
19
+ super(launcher)
22
20
 
23
21
  @phase = 0
24
22
  @workers = []
@@ -27,6 +25,10 @@ module Puma
27
25
  @phased_restart = false
28
26
  end
29
27
 
28
+ # Returns the list of cluster worker handles.
29
+ # @return [Array<Puma::Cluster::WorkerHandle>]
30
+ attr_reader :workers
31
+
30
32
  def stop_workers
31
33
  log "- Gracefully shutting down workers..."
32
34
  @workers.each { |x| x.term }
@@ -92,7 +94,7 @@ module Puma
92
94
 
93
95
  # @version 5.0.0
94
96
  def spawn_worker(idx, master)
95
- @launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
97
+ @config.run_hooks(:before_worker_fork, idx, @log_writer)
96
98
 
97
99
  pid = fork { worker(idx, master) }
98
100
  if !pid
@@ -101,7 +103,7 @@ module Puma
101
103
  exit! 1
102
104
  end
103
105
 
104
- @launcher.config.run_hooks :after_worker_fork, idx, @launcher.events
106
+ @config.run_hooks(:after_worker_fork, idx, @log_writer)
105
107
  pid
106
108
  end
107
109
 
@@ -176,10 +178,10 @@ module Puma
176
178
  end
177
179
  end
178
180
 
179
- @next_check = [
180
- @workers.reject(&:term?).map(&:ping_timeout).min,
181
- @next_check
182
- ].compact.min
181
+ t = @workers.reject(&:term?)
182
+ t.map!(&:ping_timeout)
183
+
184
+ @next_check = [t.min, @next_check].compact.min
183
185
  end
184
186
 
185
187
  def worker(index, master)
@@ -209,8 +211,8 @@ module Puma
209
211
  stop
210
212
  end
211
213
 
212
- def phased_restart
213
- return false if @options[:preload_app]
214
+ def phased_restart(refork = false)
215
+ return false if @options[:preload_app] && !refork
214
216
 
215
217
  @phased_restart = true
216
218
  wakeup!
@@ -226,7 +228,7 @@ module Puma
226
228
  def stop_blocked
227
229
  @status = :stop if @status == :run
228
230
  wakeup!
229
- @control.stop(true) if @control
231
+ @control&.stop true
230
232
  Process.waitall
231
233
  end
232
234
 
@@ -248,24 +250,24 @@ module Puma
248
250
  old_worker_count = @workers.count { |w| w.phase != @phase }
249
251
  worker_status = @workers.map do |w|
250
252
  {
251
- started_at: w.started_at.utc.iso8601,
253
+ started_at: utc_iso8601(w.started_at),
252
254
  pid: w.pid,
253
255
  index: w.index,
254
256
  phase: w.phase,
255
257
  booted: w.booted?,
256
- last_checkin: w.last_checkin.utc.iso8601,
258
+ last_checkin: utc_iso8601(w.last_checkin),
257
259
  last_status: w.last_status,
258
260
  }
259
261
  end
260
262
 
261
263
  {
262
- started_at: @started_at.utc.iso8601,
264
+ started_at: utc_iso8601(@started_at),
263
265
  workers: @workers.size,
264
266
  phase: @phase,
265
267
  booted_workers: worker_status.count { |w| w[:booted] },
266
268
  old_workers: old_worker_count,
267
269
  worker_status: worker_status,
268
- }
270
+ }.merge(super)
269
271
  end
270
272
 
271
273
  def preload?
@@ -277,7 +279,7 @@ module Puma
277
279
  if (worker = @workers.find { |w| w.index == 0 })
278
280
  worker.phase += 1
279
281
  end
280
- phased_restart
282
+ phased_restart(true)
281
283
  end
282
284
 
283
285
  # We do this in a separate method to keep the lambda scope
@@ -290,7 +292,7 @@ module Puma
290
292
 
291
293
  # Auto-fork after the specified number of requests.
292
294
  if (fork_requests = @options[:fork_worker].to_i) > 0
293
- @launcher.events.register(:ping!) do |w|
295
+ @events.register(:ping!) do |w|
294
296
  fork_worker! if w.index == 0 &&
295
297
  w.phase == 0 &&
296
298
  w.last_status[:requests_count] >= fork_requests
@@ -372,12 +374,12 @@ module Puma
372
374
  else
373
375
  log "* Restarts: (\u2714) hot (\u2714) phased"
374
376
 
375
- unless @launcher.config.app_configured?
377
+ unless @config.app_configured?
376
378
  error "No application configured, nothing to run"
377
379
  exit 1
378
380
  end
379
381
 
380
- @launcher.binder.parse @options[:binds], self
382
+ @launcher.binder.parse @options[:binds]
381
383
  end
382
384
 
383
385
  read, @wakeup = Puma::Util.pipe
@@ -409,8 +411,7 @@ module Puma
409
411
 
410
412
  @master_read, @worker_write = read, @wakeup
411
413
 
412
- @launcher.config.run_hooks :before_fork, nil, @launcher.events
413
- Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
414
+ @config.run_hooks(:before_fork, nil, @log_writer)
414
415
 
415
416
  spawn_workers
416
417
 
@@ -463,9 +464,10 @@ module Puma
463
464
  w.term unless w.term?
464
465
  when "p"
465
466
  w.ping!(result.sub(/^\d+/,'').chomp)
466
- @launcher.events.fire(:ping!, w)
467
+ @events.fire(:ping!, w)
467
468
  if !booted && @workers.none? {|worker| worker.last_status.empty?}
468
- @launcher.events.fire_on_booted!
469
+ @events.fire_on_booted!
470
+ debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
469
471
  booted = true
470
472
  end
471
473
  end
@@ -475,6 +477,7 @@ module Puma
475
477
  end
476
478
  if in_phased_restart && workers_not_booted.zero?
477
479
  @events.fire_on_booted!
480
+ debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
478
481
  in_phased_restart = false
479
482
  end
480
483
 
@@ -3,7 +3,7 @@
3
3
  module Puma
4
4
  # Rack::CommonLogger forwards every request to the given +app+, and
5
5
  # logs a line in the
6
- # {Apache common log format}[https://httpd.apache.org/docs/1.3/logs.html#common]
6
+ # {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
7
7
  # to the +logger+.
8
8
  #
9
9
  # If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
@@ -16,7 +16,7 @@ module Puma
16
16
  # (which is called without arguments in order to make the error appear for
17
17
  # sure)
18
18
  class CommonLogger
19
- # Common Log Format: https://httpd.apache.org/docs/1.3/logs.html#common
19
+ # Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
20
20
  #
21
21
  # lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
22
22
  #
@@ -25,10 +25,17 @@ module Puma
25
25
 
26
26
  HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
27
27
 
28
- CONTENT_LENGTH = 'Content-Length'.freeze
29
- PATH_INFO = 'PATH_INFO'.freeze
30
- QUERY_STRING = 'QUERY_STRING'.freeze
31
- REQUEST_METHOD = 'REQUEST_METHOD'.freeze
28
+ LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
29
+
30
+ CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
31
+ # Util::HeaderHash allows mixed
32
+ HTTP_VERSION = Const::HTTP_VERSION
33
+ HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
34
+ PATH_INFO = Const::PATH_INFO
35
+ QUERY_STRING = Const::QUERY_STRING
36
+ REMOTE_ADDR = Const::REMOTE_ADDR
37
+ REMOTE_USER = 'REMOTE_USER'
38
+ REQUEST_METHOD = Const::REQUEST_METHOD
32
39
 
33
40
  def initialize(app, logger=nil)
34
41
  @app = app
@@ -57,13 +64,13 @@ module Puma
57
64
  now = Time.now
58
65
 
59
66
  msg = HIJACK_FORMAT % [
60
- env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
61
- env["REMOTE_USER"] || "-",
62
- now.strftime("%d/%b/%Y %H:%M:%S"),
67
+ env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
68
+ env[REMOTE_USER] || "-",
69
+ now.strftime(LOG_TIME_FORMAT),
63
70
  env[REQUEST_METHOD],
64
71
  env[PATH_INFO],
65
72
  env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
66
- env["HTTP_VERSION"],
73
+ env[HTTP_VERSION],
67
74
  now - began_at ]
68
75
 
69
76
  write(msg)
@@ -74,13 +81,13 @@ module Puma
74
81
  length = extract_content_length(header)
75
82
 
76
83
  msg = FORMAT % [
77
- env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
78
- env["REMOTE_USER"] || "-",
79
- now.strftime("%d/%b/%Y:%H:%M:%S %z"),
84
+ env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
85
+ env[REMOTE_USER] || "-",
86
+ now.strftime(LOG_TIME_FORMAT),
80
87
  env[REQUEST_METHOD],
81
88
  env[PATH_INFO],
82
89
  env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
83
- env["HTTP_VERSION"],
90
+ env[HTTP_VERSION],
84
91
  status.to_s[0..3],
85
92
  length,
86
93
  now - began_at ]
@@ -1,21 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'puma/rack/builder'
4
- require 'puma/plugin'
5
- require 'puma/const'
3
+ require_relative 'rack/builder'
4
+ require_relative 'plugin'
5
+ require_relative 'const'
6
+ # note that dsl is loaded at end of file, requires ConfigDefault constants
6
7
 
7
8
  module Puma
8
-
9
- module ConfigDefault
10
- DefaultRackup = "config.ru"
11
-
12
- DefaultTCPHost = "0.0.0.0"
13
- DefaultTCPPort = 9292
14
- DefaultWorkerCheckInterval = 5
15
- DefaultWorkerTimeout = 60
16
- DefaultWorkerShutdownTimeout = 30
17
- end
18
-
19
9
  # A class used for storing "leveled" configuration options.
20
10
  #
21
11
  # In this class any "user" specified options take precedence over any
@@ -136,7 +126,50 @@ module Puma
136
126
  # is done because an environment variable may have been modified while loading
137
127
  # configuration files.
138
128
  class Configuration
139
- include ConfigDefault
129
+ DEFAULTS = {
130
+ auto_trim_time: 30,
131
+ binds: ['tcp://0.0.0.0:9292'.freeze],
132
+ clean_thread_locals: false,
133
+ debug: false,
134
+ early_hints: nil,
135
+ environment: 'development'.freeze,
136
+ # Number of seconds to wait until we get the first data for the request
137
+ first_data_timeout: 30,
138
+ io_selector_backend: :auto,
139
+ log_requests: false,
140
+ logger: STDOUT,
141
+ # How many requests to attempt inline before sending a client back to
142
+ # the reactor to be subject to normal ordering. The idea here is that
143
+ # we amortize the cost of going back to the reactor for a well behaved
144
+ # but very "greedy" client across 10 requests. This prevents a not
145
+ # well behaved client from monopolizing the thread forever.
146
+ max_fast_inline: 10,
147
+ max_threads: Puma.mri? ? 5 : 16,
148
+ min_threads: 0,
149
+ mode: :http,
150
+ mutate_stdout_and_stderr_to_sync_on_write: true,
151
+ out_of_band: [],
152
+ # Number of seconds for another request within a persistent session.
153
+ persistent_timeout: 20,
154
+ queue_requests: true,
155
+ rackup: 'config.ru'.freeze,
156
+ raise_exception_on_sigterm: true,
157
+ reaping_time: 1,
158
+ remote_address: :socket,
159
+ silence_single_worker_warning: false,
160
+ silence_fork_callback_warning: false,
161
+ tag: File.basename(Dir.getwd),
162
+ tcp_host: '0.0.0.0'.freeze,
163
+ tcp_port: 9292,
164
+ wait_for_less_busy_worker: 0.005,
165
+ worker_boot_timeout: 60,
166
+ worker_check_interval: 5,
167
+ worker_culling_strategy: :youngest,
168
+ worker_shutdown_timeout: 30,
169
+ worker_timeout: 60,
170
+ workers: 0,
171
+ http_content_length_limit: nil
172
+ }
140
173
 
141
174
  def initialize(user_options={}, default_options = {}, &block)
142
175
  default_options = self.puma_default_options.merge(default_options)
@@ -181,37 +214,22 @@ module Puma
181
214
  self
182
215
  end
183
216
 
184
- # @version 5.0.0
185
- def default_max_threads
186
- Puma.mri? ? 5 : 16
217
+ def puma_default_options
218
+ defaults = DEFAULTS.dup
219
+ puma_options_from_env.each { |k,v| defaults[k] = v if v }
220
+ defaults
187
221
  end
188
222
 
189
- def puma_default_options
223
+ def puma_options_from_env
224
+ min = ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS']
225
+ max = ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS']
226
+ workers = ENV['WEB_CONCURRENCY']
227
+
190
228
  {
191
- :min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
192
- :max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
193
- :log_requests => false,
194
- :debug => false,
195
- :binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
196
- :workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
197
- :silence_single_worker_warning => false,
198
- :mode => :http,
199
- :worker_check_interval => DefaultWorkerCheckInterval,
200
- :worker_timeout => DefaultWorkerTimeout,
201
- :worker_boot_timeout => DefaultWorkerTimeout,
202
- :worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
203
- :worker_culling_strategy => :youngest,
204
- :remote_address => :socket,
205
- :tag => method(:infer_tag),
206
- :environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
207
- :rackup => DefaultRackup,
208
- :logger => STDOUT,
209
- :persistent_timeout => Const::PERSISTENT_TIMEOUT,
210
- :first_data_timeout => Const::FIRST_DATA_TIMEOUT,
211
- :raise_exception_on_sigterm => true,
212
- :max_fast_inline => Const::MAX_FAST_INLINE,
213
- :io_selector_backend => :auto,
214
- :mutate_stdout_and_stderr_to_sync_on_write => true,
229
+ min_threads: min && Integer(min),
230
+ max_threads: max && Integer(max),
231
+ workers: workers && Integer(workers),
232
+ environment: ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'],
215
233
  }
216
234
  end
217
235
 
@@ -227,7 +245,7 @@ module Puma
227
245
  return [] if files == ['-']
228
246
  return files if files.any?
229
247
 
230
- first_default_file = %W(config/puma/#{environment_str}.rb config/puma.rb).find do |f|
248
+ first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
231
249
  File.exist?(f)
232
250
  end
233
251
 
@@ -270,7 +288,7 @@ module Puma
270
288
  found = options[:app] || load_rackup
271
289
 
272
290
  if @options[:log_requests]
273
- require 'puma/commonlogger'
291
+ require_relative 'commonlogger'
274
292
  logger = @options[:logger]
275
293
  found = CommonLogger.new(found, logger)
276
294
  end
@@ -283,21 +301,25 @@ module Puma
283
301
  @options[:environment]
284
302
  end
285
303
 
286
- def environment_str
287
- environment.respond_to?(:call) ? environment.call : environment
288
- end
289
-
290
304
  def load_plugin(name)
291
305
  @plugins.create name
292
306
  end
293
307
 
294
- def run_hooks(key, arg, events)
308
+ # @param key [:Symbol] hook to run
309
+ # @param arg [Launcher, Int] `:on_restart` passes Launcher
310
+ #
311
+ def run_hooks(key, arg, log_writer, hook_data = nil)
295
312
  @options.all_of(key).each do |b|
296
313
  begin
297
- b.call arg
314
+ if Array === b
315
+ hook_data[b[1]] ||= Hash.new
316
+ b[0].call arg, hook_data[b[1]]
317
+ else
318
+ b.call arg
319
+ end
298
320
  rescue => e
299
- events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
300
- events.debug e.backtrace.join("\n")
321
+ log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
322
+ log_writer.debug e.backtrace.join("\n")
301
323
  end
302
324
  end
303
325
  end
@@ -315,10 +337,6 @@ module Puma
315
337
 
316
338
  private
317
339
 
318
- def infer_tag
319
- File.basename(Dir.getwd)
320
- end
321
-
322
340
  # Load and use the normal Rack builder if we can, otherwise
323
341
  # fallback to our minimal version.
324
342
  def rack_builder
@@ -368,4 +386,4 @@ module Puma
368
386
  end
369
387
  end
370
388
 
371
- require 'puma/dsl'
389
+ require_relative 'dsl'