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
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/openc3/operators/operator.rb', line 90 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.
79 80 81 |
# File 'lib/openc3/operators/operator.rb', line 79 def env @env end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
83 84 85 |
# File 'lib/openc3/operators/operator.rb', line 83 def name @name end |
#new_temp_dir ⇒ Object
Returns the value of attribute new_temp_dir.
80 81 82 |
# File 'lib/openc3/operators/operator.rb', line 80 def new_temp_dir @new_temp_dir end |
#process_definition ⇒ Object
Returns the value of attribute process_definition.
77 78 79 |
# File 'lib/openc3/operators/operator.rb', line 77 def process_definition @process_definition end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
82 83 84 |
# File 'lib/openc3/operators/operator.rb', line 82 def scope @scope end |
#temp_dir ⇒ Object (readonly)
Returns the value of attribute temp_dir.
81 82 83 |
# File 'lib/openc3/operators/operator.rb', line 81 def temp_dir @temp_dir end |
#work_dir ⇒ Object
Returns the value of attribute work_dir.
78 79 80 |
# File 'lib/openc3/operators/operator.rb', line 78 def work_dir @work_dir end |
Class Method Details
.setup ⇒ Object
85 86 87 |
# File 'lib/openc3/operators/operator.rb', line 85 def self.setup # Perform any setup steps necessary end |
Instance Method Details
#alive? ⇒ Boolean
143 144 145 146 147 148 149 |
# File 'lib/openc3/operators/operator.rb', line 143 def alive? if @process @process.alive? else false end end |
#cmd_line ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/openc3/operators/operator.rb', line 102 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
151 152 153 154 155 156 157 |
# File 'lib/openc3/operators/operator.rb', line 151 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
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/openc3/operators/operator.rb', line 209 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
170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/openc3/operators/operator.rb', line 170 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_secure(@temp_dir, true) if @temp_dir @process = nil end |
#output_increment ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/openc3/operators/operator.rb', line 191 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().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().to_json(allow_nan: true) STDERR.puts stderr end end end |
#soft_stop ⇒ Object
159 160 161 162 163 164 165 166 167 168 |
# File 'lib/openc3/operators/operator.rb', line 159 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
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/openc3/operators/operator.rb', line 116 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
187 188 189 |
# File 'lib/openc3/operators/operator.rb', line 187 def stderr @process.io.stderr end |
#stdout ⇒ Object
183 184 185 |
# File 'lib/openc3/operators/operator.rb', line 183 def stdout @process.io.stdout end |