-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async Lambda Extension (ActiveJob, Suckerpunch, Async NewRelic, Etc) #98
Comments
New early return too. https://lumigo.io/blog/lambda-extensions-just-got-even-better/ |
For ActiveJob adapter to use Non-local (prod, stage) Local In relation to Rollbar, log collection, I do agree now that extensions is much more viable though because it replaces sucker_punch as a background threading system. Anytime where I have heavy data && passing to SQS/Lambdakiq isn't viable, background threading rules. |
Cool, that's the use case I'm thinking is the strongest too. |
I got pretty far on this today. Lots of reading on Lambda Extensions.
An "internal" extension is just not going to work. It was easy to create one but in order to keep the same process you will have to use #!/var/lang/bin/ruby
$FOOBAR = 'HELLO THERE'
load "/var/runtime/lib/runtime.rb" I think "external" is the way to go. I got something basic in place using this. #!/var/lang/bin/ruby
def log(msg) ; puts("['LambdaPunch'] #{msg}") ; end
log "Required"
LAMBDA_PUNCH_BASE_URI = "http://#{ENV['AWS_LAMBDA_RUNTIME_API']}/2020-01-01/extension"
require 'uri'
require 'json'
require 'net/http'
def post(path, options = {})
uri = URI.parse "#{LAMBDA_PUNCH_BASE_URI}/#{path}"
http = Net::HTTP.new uri.host, uri.port
request = Net::HTTP::Post.new uri.request_uri
request['Content-Type'] = 'application/vnd.aws.lambda.extension+json'
options[:headers].each do |header, value|
request[header] = value
end if options[:headers]
request.body = options[:body] if options[:body]
http.request(request)
end
def event_next
uri = URI.parse "#{LAMBDA_PUNCH_BASE_URI}/event/next"
http = Net::HTTP.new uri.host, uri.port
request = Net::HTTP::Get.new uri.request_uri
request['Content-Type'] = 'application/vnd.aws.lambda.extension+json'
request['Lambda-Extension-Identifier'] = LAMBDA_PUNCH_EXTENSION_ID
http.request(request)
end
log "Extension Init.."
response = post 'register',
body: %q|{"events":["SHUTDOWN"]}|,
headers: { 'Lambda-Extension-Name' => File.basename(__FILE__) }
LAMBDA_PUNCH_EXTENSION_ID = response.each_header.to_h['lambda-extension-identifier']
log "LAMBDA_PUNCH_EXTENSION_ID: #{LAMBDA_PUNCH_EXTENSION_ID}"
event_next This worked too but in order to call random blocks from the other Rails process in this extension process we need a line of communication. I think the way to go would be to use DRb (https://wiki.c2.com/?DistributedRuby) and (https://ruby-doc.org/stdlib-2.7.1/libdoc/drb/rdoc/DRb.html). So my next step is to test this out and see if it works. |
Fun fact, DRb is used in ActiveSupport's testing parallel stuff. https://github.com/rails/rails/blob/main/activesupport/lib/active_support/testing/parallelization.rb |
As this diagram shows, there is no post-invoke hook. And if we are to use this as an I was reading there is a Log API (https://docs.aws.amazon.com/lambda/latest/dg/runtimes-logs-api.html) as some event system, but that seems very heavy handed and I'm not sure the guarantees are there. Bi-directional IPC with DRb is not really a thing. Sure I could expose state in the app and have the extensions loop till it sees it, but I'm not sure I like that either. This post on a Rust extension (https://dev.to/aws-builders/building-an-aws-lambda-extension-with-rust-3p81) got me thinking. It talked about
{
"eventType": "INVOKE",
"deadlineMs": 1624399969622,
"requestId": "59358f44-900e-41f9-ba63-806e585dc418",
"invokedFunctionArn": "arn:aws:lambda:us-east-1:831702759394:function:lambdapunch-main-Lambda-5iePWQ1aaoaz:live",
"tracing": {
"type": "X-Amzn-Trace-Id",
"value": "Root=1-60d26025-01eef3a30f72afd16dfb2982;Parent=7905e3756d42aff7;Sampled=0"
}
} |
All done! v1.0.0 released to RubyGems. I've run this thru half a million invokes and everything is working great. Please let me know if you try it and have any feedback. |
If you use :async it will not work on Lambda. Maybe we can use Lambda Extensions to buffer and run things?
https://twitter.com/julian_wood/status/1396882542737903624
The text was updated successfully, but these errors were encountered: