diff --git a/.gitignore b/.gitignore index 5dc4571d8501c1ec7f1aaae4d00036c5f07ed64c..4bebf3fd047902df6d0d129ddfe157bdcf769321 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ eslint-report.html /config/redis.shared_state.yml /config/unicorn.rb /config/puma.rb +/config/puma_actioncable.rb /config/secrets.yml /config/sidekiq.yml /config/registry.key diff --git a/bin/actioncable b/bin/actioncable new file mode 100755 index 0000000000000000000000000000000000000000..0aacb19e070cd061b1a74a49887a1ee7bfc0f7d6 --- /dev/null +++ b/bin/actioncable @@ -0,0 +1,63 @@ +#!/bin/sh + +set -e + +cd $(dirname $0)/.. +app_root=$(pwd) + +puma_pidfile="$app_root/tmp/pids/puma_actioncable.pid" +puma_config="$app_root/config/puma_actioncable.rb" + +spawn_puma() +{ + exec bundle exec puma --config "${puma_config}" --environment "$RAILS_ENV" "$@" +} + +get_puma_pid() +{ + pid=$(cat "${puma_pidfile}") + if [ -z "$pid" ] ; then + echo "Could not find a PID in $puma_pidfile" + exit 1 + fi + echo "${pid}" +} + +start() +{ + spawn_puma -d +} + +start_foreground() +{ + spawn_puma +} + +stop() +{ + get_puma_pid + kill -QUIT "$(get_puma_pid)" +} + +reload() +{ + kill -USR2 "$(get_puma_pid)" +} + +case "$1" in + start) + start + ;; + start_foreground) + start_foreground + ;; + stop) + stop + ;; + reload) + reload + ;; + *) + echo "Usage: RAILS_ENV=your_env $0 {start|start_foreground|stop|reload}" + ;; +esac diff --git a/cable/config.ru b/cable/config.ru new file mode 100644 index 0000000000000000000000000000000000000000..3b93c483ded1c1d4bf93fc53c656fb3101746e34 --- /dev/null +++ b/cable/config.ru @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require ::File.expand_path('../../config/environment', __FILE__) +Rails.application.eager_load! + +run ActionCable.server diff --git a/config/application.rb b/config/application.rb index ab104a1d97bc67e7f9b79886376be561119da756..14e92bf5905dca23a7ce942e155fc3073a5f5244 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,6 +8,7 @@ require 'action_controller/railtie' require 'action_view/railtie' require 'action_mailer/railtie' +require 'action_cable/engine' require 'rails/test_unit/railtie' Bundler.require(*Rails.groups) diff --git a/config/initializers/actioncable.rb b/config/initializers/actioncable.rb new file mode 100644 index 0000000000000000000000000000000000000000..ed96f965150a5969bc5f364af1b8a5d188bb2091 --- /dev/null +++ b/config/initializers/actioncable.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Prevents the default engine from being mounted because + # we're running ActionCable as a standalone server + config.action_cable.mount_path = nil + config.action_cable.url = Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/-/cable') +end diff --git a/config/puma_actioncable.example.development.rb b/config/puma_actioncable.example.development.rb new file mode 100644 index 0000000000000000000000000000000000000000..aef15da54f9a85a75fedb6f118e574a949580732 --- /dev/null +++ b/config/puma_actioncable.example.development.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +# ----------------------------------------------------------------------- +# This file is used by the GDK to generate a default config/puma_actioncable.rb file +# Note that `/home/git` will be substituted for the actual GDK root +# directory when this file is generated +# ----------------------------------------------------------------------- + +# Load "path" as a rackup file. +# +# The default is "cable/config.ru". +# +rackup 'cable/config.ru' +pidfile '/home/git/gitlab/tmp/pids/puma_actioncable.pid' +state_path '/home/git/gitlab/tmp/pids/puma_actioncable.state' + +## Uncomment the lines if you would like to write puma stdout & stderr streams +## to a different location than rails logs. +## When using GitLab Development Kit, by default, these logs will be consumed +## by runit and can be accessed using `gdk tail rails-actioncable` +# stdout_redirect '/home/git/gitlab/log/puma_actioncable.stdout.log', +# '/home/git/gitlab/log/puma_actioncable.stderr.log', +# true + +# Configure "min" to be the minimum number of threads to use to answer +# requests and "max" the maximum. +# +# The default is "0, 16". +# +threads 1, 4 + +# By default, workers accept all requests and queue them to pass to handlers. +# When false, workers accept the number of simultaneous requests configured. +# +# Queueing requests generally improves performance, but can cause deadlocks if +# the app is waiting on a request to itself. See https://github.com/puma/puma/issues/612 +# +# When set to false this may require a reverse proxy to handle slow clients and +# queue requests before they reach puma. This is due to disabling HTTP keepalive +queue_requests false + +# Bind the server to "url". "tcp://", "unix://" and "ssl://" are the only +# accepted protocols. +bind 'unix:///home/git/gitlab_actioncable.socket' + +workers 2 + +require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events" + +on_restart do + # Signal application hooks that we're about to restart + Gitlab::Cluster::LifecycleEvents.do_before_master_restart +end + +before_fork do + # Signal to the puma killer + Gitlab::Cluster::PumaWorkerKillerInitializer.start @config.options unless ENV['DISABLE_PUMA_WORKER_KILLER'] + + # Signal application hooks that we're about to fork + Gitlab::Cluster::LifecycleEvents.do_before_fork +end + +Gitlab::Cluster::LifecycleEvents.set_puma_options @config.options +on_worker_boot do + # Signal application hooks of worker start + Gitlab::Cluster::LifecycleEvents.do_worker_start +end + +# Preload the application before starting the workers; this conflicts with +# phased restart feature. (off by default) + +preload_app! + +tag 'gitlab-actioncable-puma-worker' + +# Verifies that all workers have checked in to the master process within +# the given timeout. If not the worker process will be restarted. Default +# value is 60 seconds. +# +worker_timeout 60 + +# Use json formatter +require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter" + +json_formatter = Gitlab::PumaLogging::JSONFormatter.new +log_formatter do |str| + json_formatter.call(str) +end