Class: Jets::PolyFun::BaseExecutor
- Inherits:
-
Object
- Object
- Jets::PolyFun::BaseExecutor
- Extended by:
- Memoist
- Defined in:
- lib/jets/poly_fun/base_executor.rb
Direct Known Subclasses
Instance Method Summary collapse
- #cleanup ⇒ Object
- #copy_src_to_temp ⇒ Object
-
#create_tmpdir ⇒ Object
Mimic Dir.mktmpdir randomness, not using Dir.mktmpdir because that generates the folder at the /tmp level only.
- #handler ⇒ Object
-
#initialize(task) ⇒ BaseExecutor
constructor
A new instance of BaseExecutor.
- #lambda_executor_script ⇒ Object
-
#run(event, context) ⇒ Object
Handler is in properties: 1.
-
#run_lambda_executor(event, context) ⇒ Object
When polymorphic method errors, this method reproduces an error in the lambda format Here’s some examples to help example:.
- #write(code) ⇒ Object
Constructor Details
#initialize(task) ⇒ BaseExecutor
Returns a new instance of BaseExecutor.
8 9 10 |
# File 'lib/jets/poly_fun/base_executor.rb', line 8 def initialize(task) @task = task end |
Instance Method Details
#cleanup ⇒ Object
112 113 114 |
# File 'lib/jets/poly_fun/base_executor.rb', line 112 def cleanup FileUtils.rm_rf(@temp_dir) unless ENV['KEEP_LAMBDA_WRAPPER'] end |
#copy_src_to_temp ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/jets/poly_fun/base_executor.rb', line 39 def copy_src_to_temp app_class = @task.class_name.constantize internal = app_class.respond_to?(:internal) && app_class.internal src = internal ? "#{File.("../internal", File.dirname(__FILE__))}/#{@task.poly_src_path}" : "#{Jets.root}/#{@task.poly_src_path}" dest = "#{@temp_dir}/#{@task.poly_src_path}" FileUtils.mkdir_p(File.dirname(dest)) FileUtils.cp(src, dest) end |
#create_tmpdir ⇒ Object
Mimic Dir.mktmpdir randomness, not using Dir.mktmpdir because that generates the folder at the /tmp level only.
32 33 34 35 36 37 |
# File 'lib/jets/poly_fun/base_executor.rb', line 32 def create_tmpdir random = "#{Time.now.strftime("%Y%d%H")}-#{Process.pid}-#{SecureRandom.hex[0..6]}" tmpdir = "#{Jets.build_root}/executor/#{random}" FileUtils.mkdir_p(tmpdir) tmpdir end |
#handler ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/jets/poly_fun/base_executor.rb', line 116 def handler # Must use the generated CloudFormation template to get the handler because # the handler is derived from mutiple sources. resource = Jets::Resource::Lambda::Function.new(@task) full_handler = resource.properties["Handler"] # full handler here File.extname(full_handler).sub(/^./,'') # the extension of the full handler is the handler end |
#lambda_executor_script ⇒ Object
51 52 53 |
# File 'lib/jets/poly_fun/base_executor.rb', line 51 def lambda_executor_script File.dirname("#{@temp_dir}/#{@task.poly_src_path}") + "/lambda_executor" + @task.lang_ext end |
#run(event, context) ⇒ Object
Handler is in properties:
-
copy lambda function into tmp folder
-
generate Lang wrapper script
-
call wrapper script from ruby. Handle stdout and stderr and result. Pass info back to ruby
16 17 18 19 20 21 22 23 |
# File 'lib/jets/poly_fun/base_executor.rb', line 16 def run(event, context) @temp_dir = create_tmpdir copy_src_to_temp write(code) result = run_lambda_executor(event, context) cleanup result end |
#run_lambda_executor(event, context) ⇒ Object
When polymorphic method errors, this method reproduces an error in the lambda format Here’s some examples to help example:
Example of what the raw python prints out to stderr:
Traceback (most recent call last):
File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/lambda_executor.py", line 6, in <module>
resp = handle(event, context)
File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/index.py", line 22, in handle
return response({'message': e.message}, 400)
File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/index.py", line 5, in response
badcode
NameError: global name 'badcode' is not defined
So last line has the error summary info. Other lines have stack trace after the Traceback indicator.
Example of the reproduced lambda error format:
{
"errorMessage": "'NameError' object has no attribute 'message'",
"errorType": "AttributeError",
"stackTrace": [
[
"/var/task/handlers/controllers/posts_controller/python/index.py",
22,
"handle",
"return response({'message': e.message}, 400)"
]
]
}
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 |
# File 'lib/jets/poly_fun/base_executor.rb', line 86 def run_lambda_executor(event, context) interpreter = @task.lang command = %Q|#{interpreter} #{lambda_executor_script} '#{JSON.dump(event)}' '#{JSON.dump(context)}'| stdout, stderr, status = Open3.capture3(command) # puts "=> #{command}".color(:green) # puts "stdout #{stdout}" # puts "stderr #{stderr}" # puts "status #{status}" if status.success? stdout else # We'll mimic the way lambda displays an error. # $stderr.puts(stderr) # uncomment to debug error_lines = stderr.split("\n") = error_lines.pop error_type = .split(':').first error_lines.shift # remove first line that has the Traceback stack_trace = error_lines.reverse # python shows stack trace in opposite order from ruby JSON.dump( "errorMessage" => , "errorType" => error_type, # hardcode "stackTrace" => stack_trace ) end end |
#write(code) ⇒ Object
25 26 27 28 |
# File 'lib/jets/poly_fun/base_executor.rb', line 25 def write(code) puts "lambda_executor_script #{lambda_executor_script}" if ENV['KEEP_LAMBDA_WRAPPER'] IO.write(lambda_executor_script, code) end |