lib/cognizant/process/actions/restart.rb
module Cognizant
class Process
module Actions
module Restart
# Environment variables for process during restart.
# @return [Hash] Defaults to {}
attr_accessor :restart_env
# The command to run before the process is restarted. The exit status
# of this command determines whether or not to proceed.
# @return [String] Defaults to nil
attr_accessor :restart_before_command
# The command to restart the process with. This command can optionally
# be similar in behavior to the stop command, since the process will
# anyways be automatically started again, if autostart is set to true.
# Also see restart_expect variable.
# @return [String] Defaults to nil
attr_accessor :restart_command
# The signals to pass to the process one by one attempting to restart
# it. Each signal is passed within the timeout period over equally
# divided intervals (min. 2 seconds). Override with signals without
# "KILL" to never force kill the process.
# Also see restart_expect variable.
# e.g. ["TERM", "INT"]
# @return [Array] Defaults to ["QUIT", "TERM", "INT"]
attr_accessor :restart_signals
# Whether or not the process is expected to stop itself after the
# restart action is executed. If, upon restart action, the process will
# stop but not start again by itself, it should be set to true. If the
# process will start again within the timeout period, it should be set
# to false. For convenience, it defaults to false, if restart_command
# or restart_signals are set, as the restart action is then expected to
# start itself after a stop.
# @return [true, false] Defaults to !restart_command.present? ||
# !restart_signals.present?
attr_accessor :restart_expect_stopped
# The grace time period in seconds for the process to stop within
# (for restart). Covers the time period for the restart command or
# signals. After the timeout is over, the process is checked for
# running status and if not stopped, it re-enters the auto start
# lifecycle based on conditions. Timeout of request has the same effect
# as :stopped setting :restart_expect.
# @return [String] Defaults to 30
attr_accessor :restart_timeout
# The command to run after the process is restarted.
# @return [String] Defaults to nil
attr_accessor :restart_after_command
def restart_expect_stopped!
self.restart_expect_stopped = true
end
def restart_expect_stopped
unless !!@restart_expect_stopped == @restart_expect_stopped
@restart_expect_stopped = !(self.restart_command.present? or self.restart_signals.present?)
end
@restart_expect_stopped
end
def reset_attributes!
self.restart_env = {}
self.restart_before_command = nil
self.restart_command = nil
self.restart_signals = nil
self.restart_expect_stopped = nil
self.restart_timeout = 30
self.restart_after_command = nil
super
end
def restart_process
# We skip so that we're not reinformed about the required transition by the tick.
skip_ticks_for(self.restart_timeout)
options = {
env: self.env.merge(self.restart_env),
before: self.restart_before_command,
command: self.restart_command,
signals: self.restart_signals || ["QUIT", "TERM", "INT"],
after: self.restart_after_command,
timeout: self.restart_timeout
}
handle_action('_restart_result_handler', options)
end
# @private
def _restart_result_handler(result, time_left = 0)
# If it is a boolean and value is true OR if it's an execution result and it succeeded.
if (!!result == result and result) or (result.respond_to?(:succeeded?) and result.succeeded?)
unlink_pid if not pid_running? and self.daemonize
# We are not resetting @process_pid here to give process a second of grace period.
unless self.restart_expect_stopped
while (time_left >= 0 and not process_running?) do
sleep 1
time_left -= 1
@process_pid = nil
end
end
else
@process_pid = nil
end
# Rollback the pending skips.
skip_ticks_for(-time_left) if time_left > 0
end
end
end
end
end