Class: ProcessExecuter::Result

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/process_executer/result.rb

Overview

A decorator for Process::Status that adds the following attributes:

  • command: the command that was used to spawn the process
  • options: the options that were used to spawn the process
  • elapsed_time: the seconds the command ran
  • timed_out?: true if the process timed out

In the rare case that the timeout fires after the process was already reaped, its status is lost: the result delegates to a nil status and timed_out? is true. #success? and #to_s still work, but methods forwarded to the status (like exitstatus or signaled?) will raise NoMethodError.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(status, command:, options:, timed_out:, elapsed_time:) ⇒ Result

Create a new Result object

Examples:

command = ['sleep 1']
options = ProcessExecuter::Options::SpawnOptions.new
pid = Process.spawn(*command, **options.spawn_options)
_pid, status = Process.wait2(pid)
timed_out = false
elapsed_time = 0.01

ProcessExecuter::Result.new(status, command:, options:, timed_out:, elapsed_time:)

Parameters:

  • status (Process::Status, nil)

    the status to delegate to (nil when the timeout raced the wait for the process and the status was lost)

  • command (Array)

    the command that was used to spawn the process

  • options (ProcessExecuter::Options::Base)

    the options that were used to spawn the process

  • timed_out (Boolean)

    true if the process timed out

  • elapsed_time (Numeric)

    the seconds the command ran



45
46
47
48
49
50
51
# File 'lib/process_executer/result.rb', line 45

def initialize(status, command:, options:, timed_out:, elapsed_time:)
  super(status)
  @command = command
  @options = options
  @timed_out = timed_out
  @elapsed_time = elapsed_time
end

Instance Attribute Details

#commandArray (readonly)

The command that was used to spawn the process

Examples:

result.command #=> [{ 'GIT_DIR' => '/path/to/repo' }, 'git', 'status']

Returns:

  • (Array)

See Also:

  • Process.spawn


58
59
60
# File 'lib/process_executer/result.rb', line 58

def command
  @command
end

#elapsed_timeNumeric (readonly)

The seconds the command ran

Examples:

result.elapsed_time #=> 10.0

Returns:

  • (Numeric)


77
78
79
# File 'lib/process_executer/result.rb', line 77

def elapsed_time
  @elapsed_time
end

#optionsProcessExecuter::Options::Base (readonly)

The options that were used to spawn the process

Examples:

# Looks like a hash, but is actually an object that derives from
# ProcessExecuter::Options::Base
result.options #=> { chdir: '/path/to/repo', timeout_after: 0.5 }

Returns:

See Also:

  • Process.spawn


71
72
73
# File 'lib/process_executer/result.rb', line 71

def options
  @options
end

#timed_outBoolean (readonly) Also known as: timed_out?

True if the wait for the process was cut short by timeout_after elapsing

A timed out process is sent the SIGKILL signal, unless it had already exited in the moment between the timeout firing and the kill (the raced-timeout corner case described above).

Examples:

result = ProcessExecuter.spawn_with_timeout('sleep 10', timeout_after: 0.01)
result.timed_out? # => true

Returns:

  • (Boolean)


90
91
92
# File 'lib/process_executer/result.rb', line 90

def timed_out
  @timed_out
end

Instance Method Details

#success?true, ...

Overrides the default success? method to return nil if the process timed out

This is because when a timeout occurs, Windows will still return true.

Examples:

result = ProcessExecuter.spawn_with_timeout('sleep 10', timeout_after: 0.01)
result.success? # => nil

Returns:

  • (true, false, nil)


102
103
104
105
106
# File 'lib/process_executer/result.rb', line 102

def success?
  return nil if timed_out? # rubocop:disable Style/ReturnNilInPredicateMethodDefinition

  super
end

#to_sString

Return a string representation of the result

Examples:

result = ProcessExecuter.spawn_with_timeout('sleep 10', timeout_after: 1)
# This message is platform dependent, but will look like this on Linux:
result.to_s #=> "pid 70144 SIGKILL (signal 9) timed out after 1s"

Returns:

  • (String)


115
116
117
# File 'lib/process_executer/result.rb', line 115

def to_s
  "#{super}#{" timed out after #{options.timeout_after}s" if timed_out?}"
end