Class: FontProcessor::ExternalJSONProgram
- Inherits:
-
Object
- Object
- FontProcessor::ExternalJSONProgram
- Defined in:
- lib/fontprocessor/external_execution.rb
Class Method Summary collapse
-
.run(program, parameters) ⇒ Object
Public: Executes a command in a blocking manner that expects it’s input to be json and will return it’s output as json.
Class Method Details
.run(program, parameters) ⇒ Object
Public: Executes a command in a blocking manner that expects it’s input to be json and will return it’s output as json.
program - The command to execute. parameters - A ruby object that can be safely transformed into
JSON that will be passed to the given program on
standard input.
parameters - A special parameter which determines how long the
command should run. It is removed from the
parameters hash before being passed to the
command.
Returns a Ruby Object representing the returned json output if no error occurred. Otherwise a Hash is returned with “status” set to “Failure” and a message key explaining why.
Raises ExternalProgramError if the command times out.
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 109 110 111 112 113 114 |
# File 'lib/fontprocessor/external_execution.rb', line 71 def self.run(program, parameters) timeout = parameters.delete(:timeout) || 10 parsed = {} Open4::popen4(program) do |pid, stdin, stdout, stderr| stdin.write(parameters.to_json+"\n") stdin.close # Grab stdout or stderr. If stderr comes up first capture it until stdout is ready result = nil loop do result,_,_ = select([stdout,stderr], nil, nil, timeout) if result and result[0].eof? break elsif result and result[0] == stderr parsed['stderr'] = "" unless parsed.has_key? 'stderr' parsed['stderr'] += stderr.readpartial(4096) else break end end if result begin parsed = JSON.parse(stdout.read()) if stderr parsed['stderr'] = "" unless parsed.has_key? 'stderr' parsed['stderr'] += stderr.read() end rescue raise Exception, stderr.read() if stderr end else parsed = {'status' => 'Failure', 'message' => "Took longer than #{timeout} seconds to respond"} end Process.kill "TERM", pid end raise ExternalProgramError, "#{program}: #{parsed['message']}" if parsed['status'] == 'Failure' return parsed end |