class MultiProcess::Process

Describes a single process that can be configured and run.

{Process} basically is just a thin wrapper around {ChildProcess}.

Attributes

childprocess[R]

ChildProcess object.

command[R]

Command as full string.

dir[R]

Working directory for child process.

receiver[R]

Current receiver. Defaults to `MultiProcess::Logger.global`.

title[R]

Process title used in e.g. logger

Public Class Methods

new(*args) click to toggle source
# File lib/multi_process/process.rb, line 21
def initialize(*args)
  args.flatten!
  opts = (Hash === args.last ? args.pop : {})

  @title        = opts[:title].to_s || args.first.to_s.strip.split(/\s+/, 2)[0]
  @command      = args.map { |arg| (arg =~ /\A[\s"']+\z/ ? arg.inspect : arg).gsub '"', '\"' }.join(' ')
  @childprocess = create_childprocess *args

  @env          = opts[:env] if Hash === opts[:env]
  @env_clean    = opts[:clean_env].nil? ? true : !!opts[:clean_env]

  self.receiver = opts[:receiver] || MultiProcess::Logger.global

  self.dir      = Dir.pwd
  self.dir      = opts[:dir].to_s if opts[:dir]
end

Public Instance Methods

available!(opts = {}) click to toggle source

Wait until process is available. See {#available?}.

@param opts [Hash] Options. @option opts [Integer] :timeout Timeout in seconds. Will raise

Timeout::Error if timeout is reached.
# File lib/multi_process/process.rb, line 94
def available!(opts = {})
  timeout = opts[:timeout] ? opts[:timeout].to_i : MultiProcess::DEFAULT_TIMEOUT

  Timeout.timeout timeout do
    sleep 0.2 until available?
  end
rescue Timeout::Error => ex
  raise Timeout::Error.new "Server #{id.inspect} on port #{port} didn't get up after #{timeout} seconds..."
end
available?() click to toggle source

Check if server is available. What available means can be defined by subclasses e.g. a server process can check if server port is reachable.

By default is process if available if alive? returns true.

# File lib/multi_process/process.rb, line 84
def available?
  alive?
end
clean_env?() click to toggle source

Check if environment will be cleaned up for process.

Currently that includes wrapping the process start in `Bundler.with_clean_env` to remove bundler environment variables.

# File lib/multi_process/process.rb, line 140
def clean_env?
  !!@env_clean
end
dir=(dir) click to toggle source

Set process working directory. Only affect process if set before starting.

# File lib/multi_process/process.rb, line 127
def dir=(dir)
  @dir = ::File.expand_path(dir.to_s)
  env['PWD'] = @dir
end
env() click to toggle source

Return current environment.

# File lib/multi_process/process.rb, line 146
def env
  @env ||= {}
end
env=(env) click to toggle source

Set environment.

# File lib/multi_process/process.rb, line 152
def env=(env)
  fail ArgumentError.new 'Environment must be a Hash.' unless hash === env
  @env = env
end
receiver=(receiver) click to toggle source

Set receiver that should receive process output.

# File lib/multi_process/process.rb, line 165
def receiver=(receiver)
  if @receiver
    childprocess.io.stdout.close
    childprocess.io.stderr.close
  end

  childprocess.io.stdout = receiver.pipe(self, :out) if receiver
  childprocess.io.stderr = receiver.pipe(self, :err) if receiver
  @receiver = receiver
end
run(opts = {}) click to toggle source

Start process and wait until it's finished.

Given arguments will be passed to {#wait}.

# File lib/multi_process/process.rb, line 114
def run(opts = {})
  start
  wait opts
end
start() click to toggle source

Start process.

Started processes will be stopped when ruby VM exists by hooking into `at_exit`.

# File lib/multi_process/process.rb, line 62
def start
  return false if started?

  at_exit { stop }
  receiver.message(self, :sys, command) if receiver
  start_childprocess
  @started = true
end
started?() click to toggle source

Check if process was started.

# File lib/multi_process/process.rb, line 106
def started?
  !!@started
end
stop(*args) click to toggle source

Stop process.

Will call `ChildProcess#stop`.

# File lib/multi_process/process.rb, line 75
def stop(*args)
  childprocess.stop *args if started?
end
wait(opts = {}) click to toggle source

Wait until process finished.

If no timeout is given it will wait definitely.

@param opts [Hash] Options. @option opts [Integer] :timeout Timeout to wait in seconds.

# File lib/multi_process/process.rb, line 49
def wait(opts = {})
  if opts[:timeout]
    childprocess.wait_for_exit opts[:timeout]
  else
    childprocess.wait
  end
end

Private Instance Methods

create_childprocess(*args) click to toggle source

Create child process.

# File lib/multi_process/process.rb, line 180
def create_childprocess(*args)
  ChildProcess.new *args.flatten
end
start_childprocess() click to toggle source

Start child process.

Can be used to hook in subclasses and modules.

# File lib/multi_process/process.rb, line 188
def start_childprocess
  env.each { |k, v| childprocess.environment[k.to_s] = v.to_s }
  childprocess.cwd = dir

  if clean_env?
    Bundler.with_original_env { childprocess.start }
  else
    childprocess.start
  end
end