class Desi::ProcessManager

The ProcessManager will start, stop and restart a local Elastic Search node instance, in addition to reporting its status

@example Start up the instance and check its status

Desi::ProcessManager.new.start.status #=> "OK. Elastic Search cluster 'elasticsearch' (v0.19.9) is running on 1 node(s) with status green"

@example Retrieve the currently running cluster’s version

Desi::ProcessManager.new.running_version #=> "0.19.9"

@example Retrieve a distant cluster’s version

Desi::ProcessManager.new(host: "http://somewhere.com:9200").running_version #=> "0.18.5"

Public Class Methods

new(opts = {}) click to toggle source
# File lib/desi/process_manager.rb, line 26
def initialize(opts = {})
  @host = opts.fetch(:host) { Desi.configuration.server }
  @verbose = opts[:verbose]
  @foreground = opts[:foreground]
  @local_install = LocalInstall.new
  @client = opts.fetch(:http_client_factory, Desi::HttpClient).new(@host)

  @tail_after_start = opts[:tail]

  if @tail_after_start && @foreground
    $stderr.puts "Cannot tail logs when starting ES in foreground mode"
    exit 1
  end
end

Public Instance Methods

has_pid?() click to toggle source

Whether the pidfile actually holds a PID

@return [Boolean]

# File lib/desi/process_manager.rb, line 122
def has_pid?
  pid && !pid.empty?
end
pid() click to toggle source

PID as retrieved from the pidfile

@return [String]

# File lib/desi/process_manager.rb, line 129
def pid
  @pid ||= File.read(pidfile) if pidfile.exist?
end
restart() click to toggle source

Restart the cluster

Stop the cluster (if its up) and start it again.

@note We use the pidfile to determine if the cluster is up. If a node was

started with another tool, you may end up with more than 1 node
running.

@note This method will also output its result on STDOUT if +@verbose+ is

true

@return [self]

@api public

# File lib/desi/process_manager.rb, line 74
def restart
  puts " * (Re)starting cluster" if @verbose
  stop if has_pid?
  puts " * Elastic Search #{running_version} started" if start_cluster && @verbose
  self
end
running_version() click to toggle source

Release number of the currently running cluster

@example

Desi::ProcessManager.new.running_version #=> "0.19.9"

@return [String,nil]

# File lib/desi/process_manager.rb, line 140
def running_version
  begin
    JSON.parse(@client.get('/').body)["version"]["number"]
  rescue
    nil
  end
end
show_tail(options = {}) click to toggle source
# File lib/desi/process_manager.rb, line 148
def show_tail(options = {})
  puts "Will tail ES logs…" if @verbose
  executable = "tail"
  lines = Integer(options.fetch(:lines, 10))

  system "#{executable} -n #{lines} -f #{logfile}"
end
start() click to toggle source

Start the cluster

This will be a no-op if the cluster is already started.

@note This method will also output its result on STDOUT if +@verbose+ is

true

@return [self]

@api public

# File lib/desi/process_manager.rb, line 51
def start
  if cluster_ready?
    puts "ES cluster is already running" if @verbose
  else
    puts " * Elastic Search #{running_version} started" if start_cluster && @verbose
  end
  self
end
status() click to toggle source

Get information about the cluster’s status

Desi::ProcessManager.new.status #=> "OK. Elastic Search cluster 'elasticsearch' (v0.19.9) is running on 1 node(s) with status green"

@note This method will also output its result on STDOUT if +@verbose+ is

true

@return [String]

@api public

# File lib/desi/process_manager.rb, line 109
def status
  if version = running_version
    msg = "OK. Elastic Search cluster '#{cluster_health.cluster_name}' (v#{version}) is running on #{cluster_health.number_of_nodes} node(s) with status #{cluster_health.status}"
  else
    msg = "KO. No Elastic Search instance was found running on #{@host}"
  end
  puts msg if @verbose
  msg
end
stop() click to toggle source

Stop the cluster

@note This method will also output its result on STDOUT if +@verbose+ is

true

@return [self]

@api public

# File lib/desi/process_manager.rb, line 89
def stop
  if pid
    puts " * Will stop instance with pid #{pid}" if @verbose
    stop_cluster
  else
    puts " * No pidfile detected!. Won't stop" if @verbose
  end
  self
end

Protected Instance Methods

cluster_health() click to toggle source

Return cluster health data straight from the cluster

see www.elasticsearch.org/guide/reference/api/admin-cluster-health.html for further information on the response’s structure

@return [Hash]

# File lib/desi/process_manager.rb, line 165
def cluster_health
  @cluster_health ||= OpenStruct.new(JSON.parse(@client.get('/_cluster/health').body))
end

Private Instance Methods

catch_manual_interruption!() click to toggle source
# File lib/desi/process_manager.rb, line 259
def catch_manual_interruption!
  if foreground?
    old_handler = trap(:INT) do
      $stderr.puts "Elastic Search interrupted!"
      if old_handler.respond_to?(:call)
        old_handler.call
      else
        exit 1
      end
    end
  end
end
check_java_presence!() click to toggle source
# File lib/desi/process_manager.rb, line 276
def check_java_presence!
  Cocaine::CommandLine.new("which java").run
rescue Cocaine::ExitStatusError
  warn "Could not find 'java' executable in your path. Are you sure it is installed on your system?"
  exit 1
end
cluster_ready?() click to toggle source
# File lib/desi/process_manager.rb, line 214
def cluster_ready?
  begin
    JSON.parse(@client.get('/').body)["status"] == 200
  rescue
    false
  end
end
foreground?() click to toggle source
# File lib/desi/process_manager.rb, line 251
def foreground?
  !! @foreground
end
foreground_or_background_flag() click to toggle source
# File lib/desi/process_manager.rb, line 243
def foreground_or_background_flag
  if legacy_release?
    foreground? ? '-f' : ''
  else
    foreground? ? '' : '-d'
  end
end
kill!() click to toggle source
# File lib/desi/process_manager.rb, line 206
def kill!
  Process.kill("HUP", Integer(pid)) if has_pid?
end
legacy_release?() click to toggle source
# File lib/desi/process_manager.rb, line 272
def legacy_release?
  @legacy_release ||= Desi::LocalInstall.current_release_is_pre_one_zero?
end
logfile() click to toggle source
# File lib/desi/process_manager.rb, line 171
def logfile
  @local_install.logfile
end
perform_start() click to toggle source
# File lib/desi/process_manager.rb, line 231
def perform_start
  check_java_presence!
  puts "ES will be launched in the foreground" if foreground?

  Cocaine::CommandLine.new(@local_install.launcher.to_s, *start_command_options).
    run(pidfile: pidfile.to_s)
end
pidfile() click to toggle source
# File lib/desi/process_manager.rb, line 210
def pidfile
  @pidfile ||= Pathname(@local_install.pidfile)
end
start_cluster(max_wait = 10, step = 0.5) click to toggle source
# File lib/desi/process_manager.rb, line 183
def start_cluster(max_wait = 10, step = 0.5)
  catch_manual_interruption!
  perform_start
  show_tail if tail_after_start?

  unless wait_until_cluster_becomes_ready(max_wait, step)
    raise "Cluster still not ready after #{max_wait} seconds!"
  end
rescue Cocaine::CommandNotFoundError
  warn "#{@local_install.launcher} could not be found! Are you sure that Elastic Search is already installed?"
  false
else
  true
end
start_command_options() click to toggle source
# File lib/desi/process_manager.rb, line 239
def start_command_options
  ['-p :pidfile', foreground_or_background_flag].compact.join(' ')
end
stop_cluster(max_wait = 5, step = 0.3) click to toggle source
# File lib/desi/process_manager.rb, line 198
def stop_cluster(max_wait = 5, step = 0.3)
  kill!

  unless wait_until_cluster_is_down(max_wait, step)
    raise "Strange. Cluster seems still up after #{max_wait} seconds!"
  end
end
tail_after_start?() click to toggle source
# File lib/desi/process_manager.rb, line 255
def tail_after_start?
  @tail_after_start
end
wait_for(max_wait = 10, step = 0.5, &condition) click to toggle source
# File lib/desi/process_manager.rb, line 222
def wait_for(max_wait = 10, step = 0.5, &condition)
  delay = 0
  until delay > max_wait || condition.call
    sleep step
    delay += step
  end
  delay < max_wait
end
wait_until_cluster_becomes_ready(max_wait, step) click to toggle source
# File lib/desi/process_manager.rb, line 175
def wait_until_cluster_becomes_ready(max_wait, step)
  wait_for(max_wait, step) { cluster_ready? }
end
wait_until_cluster_is_down(max_wait, step) click to toggle source
# File lib/desi/process_manager.rb, line 179
def wait_until_cluster_is_down(max_wait, step)
  wait_for(max_wait, step) { !cluster_ready? }
end