summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Vosmaer <jacob@gitlab.com>2018-10-23 16:37:08 +0200
committerJacob Vosmaer <jacob@gitlab.com>2018-10-23 16:37:08 +0200
commit63d8505d2ce3909493272f446026786a011bd86e (patch)
tree9e0faaad19ed2f0af647a11a6ddbe13445d7b482
parentfc0776cc4ee205d25b56884e679d67e8918638ed (diff)
downloadgitlab-ce-63d8505d2ce3909493272f446026786a011bd86e.tar.gz
My version of what the lifecycle events mean
-rw-r--r--lib/gitlab/cluster/lifecycle_events.rb143
1 files changed, 76 insertions, 67 deletions
diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb
index 97aeed2fa9f..b31d2ba5861 100644
--- a/lib/gitlab/cluster/lifecycle_events.rb
+++ b/lib/gitlab/cluster/lifecycle_events.rb
@@ -2,92 +2,101 @@
module Gitlab
module Cluster
- # This class abstracts various lifecycle events for different runtime environments
- # This allows handlers for various events to be registered and executed regardless
- # of the environment. Possible environments considered while building this class
- # include Unicorn, Puma Single, Puma Clustered, Sidekiq Multithreaded Process, Ruby,
- # Rake, rails-console etc
+ #
+ # LifecycleEvents lets Rails initializers register application startup hooks
+ # that are sensitive to forking. For example, to defer the creation of
+ # watchdog threads. This lets us abstract away the Unix process
+ # lifecycles of Unicorn, Sidekiq, Puma, Puma Cluster, etc.
+ #
+ # We have three lifecycle events.
+ #
+ # - before_fork (only in forking processes)
+ # - worker_start
+ # - before_master_restart (only in forking processes)
#
# Blocks will be executed in the order in which they are registered.
+ #
class LifecycleEvents
- # Initialization lifecycle event. Any block registered can expect to be
- # executed once per process. In the event of single process environments,
- # the block is executed immediately
- def self.on_worker_start(&block)
- if in_clustered_environment?
- (@worker_start_listeners ||= []) << block
- else
- block.call
+ class << self
+ #
+ # Hook registration methods (called from initializers)
+ #
+ def on_worker_start(&block)
+ if in_clustered_environment?
+ # Defer block execution
+ (@worker_start_listeners ||= []) << block
+ else
+ block.call
+ end
end
- end
- # Lifecycle event in the master process to signal that a child is about to be
- # forked
- def self.on_before_fork(&block)
- (@before_fork_listeners ||= []) << block
- end
+ def on_before_fork(&block)
+ if in_clustered_environment?
+ # Defer block execution
+ (@before_fork_listeners ||= []) << block
+ else
+ # Discard block
+ end
+ end
- # Lifecycle event for main process restart. Signals that the main process should
- # restart.
- def self.on_master_restart(&block)
- (@master_restart_listeners ||= []) << block
- end
+ def on_master_restart(&block)
+ if in_clustered_environment?
+ # Defer block execution
+ (@master_restart_listeners ||= []) << block
+ else
+ # Discard block
+ end
+ end
- # Signal worker_start event
- # This should be called from unicorn/puma/etc lifecycle hooks
- def self.signal_worker_start
- @worker_start_listeners&.each do |block|
- block.call
+ #
+ # Lifecycle integration methods (called from unicorn.rb, puma.rb, etc.)
+ #
+ def do_worker_start
+ @worker_start_listeners&.each do |block|
+ block.call
+ end
end
- end
- # Signal before_fork event
- # This should be called from unicorn/puma/etc lifecycle hooks
- def self.signal_before_fork
- @before_fork_listeners&.each do |block|
- block.call
+ def do_before_fork
+ @before_fork_listeners&.each do |block|
+ block.call
+ end
end
- end
- # Signal master_restart event
- # This should be called from unicorn/puma/etc lifecycle hooks
- def self.signal_master_restart
- @master_restart_listeners && @master_restart_listeners.each do |block|
- block.call
+ def do_master_restart
+ @master_restart_listeners && @master_restart_listeners.each do |block|
+ block.call
+ end
end
- end
- # Returns true when running in environments which fork worker processes
- # from a main process. Noteably Puma, when running in clustered mode,
- # and Unicorn. Sidekiq and plain Ruby do not fork workers, so return false
- def self.in_clustered_environment?
- # Sidekiq doesn't fork
- return false if Sidekiq.server?
+ # Puma doesn't use singletons (which is good) but
+ # this means we need to pass through whether the
+ # puma server is running in single mode or cluster mode
+ def set_puma_options(options)
+ @puma_options = options
+ end
- # Unicorn always forks
- return true if defined?(::Unicorn)
+ private
- # Puma sometimes forks
- return true if in_clustered_puma?
+ def in_clustered_environment?
+ # Sidekiq doesn't fork
+ return false if Sidekiq.server?
- # Default assumption is that we don't fork
- false
- end
- private_class_method :in_clustered_environment?
+ # Unicorn always forks
+ return true if defined?(::Unicorn)
- # Returns true when running in Puma in clustered mode
- def self.in_clustered_puma?
- return false unless defined?(::Puma)
+ # Puma sometimes forks
+ return true if in_clustered_puma?
- @puma_options && @puma_options[:workers] && @puma_options[:workers] > 0
- end
- private_class_method :in_clustered_puma?
+ # Default assumption is that we don't fork
+ false
+ end
- # Puma doesn't use singletons (which is good) but
- # this means we need to pass through whether the
- # puma server is running in single mode or cluster mode
- def self.set_puma_options(options)
- @puma_options = options
+ def in_clustered_puma?
+ return false unless defined?(::Puma)
+
+ @puma_options && @puma_options[:workers] && @puma_options[:workers] > 0
+ end
end
end
end