diff --git a/config/puma.rb b/config/puma.rb index a2fa75ec..42887675 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -14,14 +14,9 @@ min_threads_count = ENV.fetch('RAILS_MIN_THREADS', max_threads_count) threads min_threads_count, max_threads_count # Specifies that the worker count should equal the number of processors in production. -# Workers are forked web server processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -if ENV['RAILS_ENV'] == 'production' - require 'concurrent' - - worker_count = Integer(ENV.fetch('WEB_CONCURRENCY', Concurrent.physical_processor_count)) +if %w[production staging].include? ENV['RAILS_ENV'] + require 'concurrent-ruby' + worker_count = Integer(ENV.fetch('WEB_CONCURRENCY') { Concurrent.physical_processor_count }) workers worker_count if worker_count > 1 end @@ -30,7 +25,7 @@ end worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development' # Specifies the `port` that Puma will listen on to receive requests; default is 7000. -port ENV.fetch('PORT', 7000) +port ENV.fetch('PORT', 7000) # Specifies the `environment` that Puma will run in. environment ENV.fetch('RAILS_ENV', 'development') @@ -38,12 +33,50 @@ environment ENV.fetch('RAILS_ENV', 'development') # Specifies the `pidfile` that Puma will use. pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid') -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. -# +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart + +########################## +##### CUSTOM OPTIONS ##### +########################## + +# Specifies the `state_path` that Pumactl will use. +state_path 'tmp/pids/puma.state' + +# Activate control app for Pumactl. +activate_control_app 'unix://tmp/sockets/pumactl.sock' + +# Only bind to systemd activated sockets, ignoring other binds. +# If no systemd activated sockets are given, regular binds apply. +bind_to_activated_sockets 'only' + +# Refresh Gemfile during phased-restarts. +prune_bundler + +# Fork all workers from worker 0 to reduce memory footprint and allow phased restarts. +# For successful phased restarts, we need at least 3 workers (see doc). +# See https://github.com/puma/puma/blob/master/docs/fork_worker.md. +fork_worker + +# Disable explicit preloading of our app. +# With `fork_worker`, we will have an implicit preloading. # preload_app! -# Allow puma to be restarted by `rails restart` command. -plugin :tmp_restart +# Disable automatic tagging of the service. +tag '' + +# Specifies the output redirection that Puma will use. +# Params: stdout, stderr, append? +stdout_redirect 'log/puma_access.log', 'log/puma_error.log', true if %w[production staging].include? ENV['RAILS_ENV'] + +# Before performing a hot restart (not on phased restarts), send another watchdog message +# TODO: Consider `on_booted` as well, which currently breaks with Pumactl. +on_restart do + require 'puma/sd_notify' + Puma::SdNotify.watchdog +end + +# Note on Phased Restarts: +# - Phased Restarts are only supported in cluster mode with multiple workers (i.e., not in development). +# - The Puma binary won't be upgraded on phased restarts, but since we have the unattended-upgrades, this is not a major issue. +# - See https://github.com/casperisfine/puma/blob/master/docs/restart.md. diff --git a/docs/environment_variables.md b/docs/environment_variables.md index d045cc39..d378e486 100644 --- a/docs/environment_variables.md +++ b/docs/environment_variables.md @@ -6,6 +6,11 @@ The following environment variables are specifically support in CodeOcean and ar |- |- |- | | `RAILS_ENV` | `development` | Specifies the Rails environment which can be configured using the files in `config/environments` | | `RAILS_RELATIVE_URL_ROOT` | `/` | Specifies the subpath of the application, used for links and assets | +| `WEB_CONCURRENCY` | Number of physical CPU cores | Puma worker count in production or staging for cluster mode | +| `RAILS_MAX_THREADS` | `5` | Maximum Puma thread count per worker | +| `RAILS_MIN_THREADS` | `$RAILS_MIN_THREADS` | Minimum Puma thread count per worker | +| `PORT` | `7000` | Default port for the web server | +| `PIDFILE` | `tmp/pids/server.pid` | Location of the file to store the Puma process ID | | `SENTRY_DSN` | ` ` | Specifies the [Sentry error reporting](https://sentry.io) endpoint for the Rails server | | `SENTRY_JAVASCRIPT_DSN` | ` ` | Specifies the [Sentry error reporting](https://sentry.io) endpoint for the frontend used by browsers | | `SENTRY_CURRENT_ENV` | ` ` | Specifies the [Sentry](https://sentry.io) environment used for error reporting |