Class: OpenC3::OperatorProcess
- Defined in:
- lib/openc3/operators/operator.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#env ⇒ Object
Returns the value of attribute env.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#new_temp_dir ⇒ Object
Returns the value of attribute new_temp_dir.
-
#process_definition ⇒ Object
Returns the value of attribute process_definition.
-
#scope ⇒ Object
readonly
Returns the value of attribute scope.
-
#temp_dir ⇒ Object
readonly
Returns the value of attribute temp_dir.
-
#work_dir ⇒ Object
Returns the value of attribute work_dir.
Class Method Summary collapse
Instance Method Summary collapse
- #alive? ⇒ Boolean
- #cmd_line ⇒ Object
- #exit_code ⇒ Object
-
#extract_output ⇒ Object
This is method is used in here and in ProcessManager.
- #hard_stop ⇒ Object
-
#initialize(process_definition, work_dir: '/openc3/lib/openc3/microservices', temp_dir: nil, env: {}, scope:, container: nil, config: nil) ⇒ OperatorProcess
constructor
container is not used, it’s just here for Enterprise.
- #output_increment ⇒ Object
- #soft_stop ⇒ Object
- #start ⇒ Object
- #stderr ⇒ Object
- #stdout ⇒ Object
Constructor Details
#initialize(process_definition, work_dir: '/openc3/lib/openc3/microservices', temp_dir: nil, env: {}, scope:, container: nil, config: nil) ⇒ OperatorProcess
container is not used, it’s just here for Enterprise
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/openc3/operators/operator.rb', line 93 def initialize(process_definition, work_dir: '/openc3/lib/openc3/microservices', temp_dir: nil, env: {}, scope:, container: nil, config: nil) @process = nil @process_definition = process_definition @work_dir = work_dir @temp_dir = temp_dir @new_temp_dir = temp_dir @env = env @scope = scope # @config only used in start to help print a better Logger message @config = config end |
Instance Attribute Details
#env ⇒ Object
Returns the value of attribute env.
82 83 84 |
# File 'lib/openc3/operators/operator.rb', line 82 def env @env end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
86 87 88 |
# File 'lib/openc3/operators/operator.rb', line 86 def name @name end |
#new_temp_dir ⇒ Object
Returns the value of attribute new_temp_dir.
83 84 85 |
# File 'lib/openc3/operators/operator.rb', line 83 def new_temp_dir @new_temp_dir end |
#process_definition ⇒ Object
Returns the value of attribute process_definition.
80 81 82 |
# File 'lib/openc3/operators/operator.rb', line 80 def process_definition @process_definition end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
85 86 87 |
# File 'lib/openc3/operators/operator.rb', line 85 def scope @scope end |
#temp_dir ⇒ Object (readonly)
Returns the value of attribute temp_dir.
84 85 86 |
# File 'lib/openc3/operators/operator.rb', line 84 def temp_dir @temp_dir end |
#work_dir ⇒ Object
Returns the value of attribute work_dir.
81 82 83 |
# File 'lib/openc3/operators/operator.rb', line 81 def work_dir @work_dir end |
Class Method Details
.setup ⇒ Object
88 89 90 |
# File 'lib/openc3/operators/operator.rb', line 88 def self.setup # Perform any setup steps necessary end |
Instance Method Details
#alive? ⇒ Boolean
146 147 148 149 150 151 152 |
# File 'lib/openc3/operators/operator.rb', line 146 def alive? if @process @process.alive? else false end end |
#cmd_line ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/openc3/operators/operator.rb', line 105 def cmd_line # In ProcessManager processes, the process_definition is the actual thing run # e.g. OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "load", ...]) # However, if the MicroserviceOperator is spawning the processes it sets # process_definition = ["ruby", "plugin_microservice.rb"] # which then calls exec(*@config["cmd"]) to actually run # So check if the @config['cmd'] is defined to give the user more info in the log cmd_line_text = @process_definition.join(' ') if @config && @config['cmd'] cmd_line_text = @config['cmd'].join(' ') end return cmd_line_text end |
#exit_code ⇒ Object
154 155 156 157 158 159 160 |
# File 'lib/openc3/operators/operator.rb', line 154 def exit_code if @process @process.exit_code else nil end end |
#extract_output ⇒ Object
This is method is used in here and in ProcessManager
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/openc3/operators/operator.rb', line 212 def extract_output output = '' if @process stdout = @process.io.stdout.finalize stderr = @process.io.stderr.finalize # Always include the Stdout header for consistency and to show the option output << "Stdout:\n" output << stdout # Always include the nStderr header for consistency and to show the option output << "\nStderr:\n" output << stderr end output end |
#hard_stop ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/openc3/operators/operator.rb', line 173 def hard_stop if @process and !@process.exited? # Redis may be down at this point so just catch any Logger errors begin Logger.info("Hard shutting down process: #{cmd_line()}", scope: @scope) rescue Exception end @process.stop end FileUtils.remove_entry(@temp_dir) if @temp_dir and File.exist?(@temp_dir) @process = nil end |
#output_increment ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/openc3/operators/operator.rb', line 194 def output_increment if @process stdout = @process.io.stdout.extract if stdout.length > 0 = "STDOUT #{stdout.length} bytes from #{cmd_line()}:" STDOUT.puts Logger.build_log_data(Logger::INFO_LEVEL, , user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true) STDOUT.puts stdout end stderr = @process.io.stderr.extract if stderr.length > 0 = "STDERR #{stderr.length} bytes from #{cmd_line()}:" STDERR.puts Logger.build_log_data(Logger::ERROR_LEVEL, , user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true) STDERR.puts stderr end end end |
#soft_stop ⇒ Object
162 163 164 165 166 167 168 169 170 171 |
# File 'lib/openc3/operators/operator.rb', line 162 def soft_stop Thread.new do Logger.info("Soft shutting down process: #{cmd_line()}", scope: @scope) begin Process.kill("SIGINT", @process.pid) if @process # Signal the process to stop rescue Errno::ESRCH # Process already gone end end end |
#start ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/openc3/operators/operator.rb', line 119 def start @temp_dir = @new_temp_dir @new_temp_dir = nil Logger.info("Starting: #{cmd_line()}", scope: @scope) @process = ChildProcess.build(*@process_definition) # This lets the ChildProcess use the parent IO ... but it breaks unit tests # @process.io.inherit! @process.cwd = @work_dir # Spawned process should not be controlled by same Bundler constraints as spawning process ENV.each do |key, _value| if key =~ /^BUNDLER/ @process.environment[key] = nil end end @env['RUBYOPT'] = nil # Removes loading bundler setup @env.each do |key, value| @process.environment[key] = value end @process.environment['OPENC3_SCOPE'] = @scope @process.io.stdout = OperatorProcessIO.new('microservice-stdout') @process.io.stderr = OperatorProcessIO.new('microservice-stderr') @process.start @name = "#{Socket.gethostname}__#{@process.pid}" end |
#stderr ⇒ Object
190 191 192 |
# File 'lib/openc3/operators/operator.rb', line 190 def stderr @process.io.stderr end |
#stdout ⇒ Object
186 187 188 |
# File 'lib/openc3/operators/operator.rb', line 186 def stdout @process.io.stdout end |