File: result.rb

package info (click to toggle)
ruby-process-executer 4.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 408 kB
  • sloc: ruby: 873; makefile: 4
file content (108 lines) | stat: -rw-r--r-- 3,444 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# frozen_string_literal: true

require 'delegate'

module ProcessExecuter
  # 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
  #
  # @api public
  #
  class Result < SimpleDelegator
    # Create a new Result object
    #
    # @example
    #   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:)
    #
    # @param status [Process::Status] the status to delegate to
    #
    # @param command [Array] the command that was used to spawn the process
    #
    # @param options [ProcessExecuter::Options::Base] the options that were used to spawn the process
    #
    # @param timed_out [Boolean] true if the process timed out
    #
    # @param elapsed_time [Numeric] the seconds the command ran
    #
    def initialize(status, command:, options:, timed_out:, elapsed_time:)
      super(status)
      @command = command
      @options = options
      @timed_out = timed_out
      @elapsed_time = elapsed_time
    end

    # The command that was used to spawn the process
    # @see Process.spawn
    # @example
    #   result.command #=> [{ 'GIT_DIR' => '/path/to/repo' }, 'git', 'status']
    # @return [Array]
    attr_reader :command

    # The options that were used to spawn the process
    #
    # @see Process.spawn
    #
    # @example
    #   # 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 }
    #
    # @return [ProcessExecuter::Options::Base]
    #
    attr_reader :options

    # The seconds the command ran
    # @example
    #   result.elapsed_time #=> 10.0
    # @return [Numeric]
    attr_reader :elapsed_time

    # @!attribute [r] timed_out?
    # True if the process timed out and was sent the SIGKILL signal
    # @example
    #   result = ProcessExecuter.spawn_with_timeout('sleep 10', timeout_after: 0.01)
    #   result.timed_out? # => true
    # @return [Boolean]
    #
    attr_reader :timed_out
    alias timed_out? timed_out

    # 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.
    #
    # @example
    #   result = ProcessExecuter.spawn_with_timeout('sleep 10', timeout_after: 0.01)
    #   result.success? # => nil
    # @return [true, false, nil]
    #
    def success?
      return nil if timed_out? # rubocop:disable Style/ReturnNilInPredicateMethodDefinition

      super
    end

    # Return a string representation of the result
    # @example
    #   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"
    # @return [String]
    #
    def to_s
      "#{super}#{" timed out after #{options.timeout_after}s" if timed_out?}"
    end
  end
end