Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get an AWS Lambda Remaining time using Python and Zappa?

I'm using Flask and Zappa to deploy to AWS Lambda, but one of my tasks takes more than 300 seconds to execute so the lambda shuts down.

I'd like to call another lambda before it happens to finish the work, is it possible to get the remaining time using Zappa?

like image 415
Fernando Freitas Alves Avatar asked Jul 14 '17 15:07

Fernando Freitas Alves


1 Answers

Below is the simple app I built

from flask import Flask, jsonify, request
import time
import traceback

app = Flask(__name__)

@app.route("/")
def index():
    return jsonify(traceback.format_stack())

if __name__ == "__main__":
   app.run()

And that gave me traceback

[
" File "/var/runtime/awslambda/bootstrap.py", line 534, in <module> main() ",
" File "/var/runtime/awslambda/bootstrap.py", line 529, in main handle_event_request(request_handler, invokeid, event_body, context_objs, invoked_function_arn) ",
" File "/var/runtime/awslambda/bootstrap.py", line 249, in handle_event_request result = request_handler(json_input, context) ",
" File "/var/task/handler.py", line 511, in lambda_handler return LambdaHandler.lambda_handler(event, context) ",
" File "/var/task/handler.py", line 242, in lambda_handler return handler.handler(event, context) ",
" File "/var/task/handler.py", line 454, in handler response = Response.from_app(self.wsgi_app, environ) ",
" File "/var/task/werkzeug/wrappers.py", line 903, in from_app return cls(*_run_wsgi_app(app, environ, buffered)) ",
" File "/var/task/werkzeug/test.py", line 884, in run_wsgi_app app_rv = app(environ, start_response) ",
" File "/var/task/zappa/middleware.py", line 70, in __call__ response = self.application(environ, encode_response) ",
" File "/var/task/flask/app.py", line 1997, in __call__ return self.wsgi_app(environ, start_response) ",
" File "/var/task/flask/app.py", line 1982, in wsgi_app response = self.full_dispatch_request() ",
" File "/var/task/flask/app.py", line 1612, in full_dispatch_request rv = self.dispatch_request() ",
" File "/var/task/flask/app.py", line 1598, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) ",
" File "/var/task/myapp.py", line 8, in index return jsonify(traceback.format_stack()) "
]

The traceback pointed me to

https://github.com/Miserlou/Zappa/blob/f7a785351450fa9115864c7dfe223660f5a99ae6/zappa/handler.py#L454

Just before that it has

# We are always on https on Lambda, so tell our wsgi app that.
environ['HTTPS'] = 'on'
environ['wsgi.url_scheme'] = 'https'
environ['lambda.context'] = context

These are filled in WSGI app environ for the request. This is accessible as flask.request.environ.get. So then I changed the code to

from flask import Flask, jsonify, request
import time
import traceback

app = Flask(__name__)

@app.route("/")
def index():
    context = request.environ.get('lambda.context', None)
    if context is not None:
       before = context.get_remaining_time_in_millis()
       time.sleep(1)
       after = context.get_remaining_time_in_millis()
       return "Time Before={}\nTime After={}".format(before, after)
    return jsonify(traceback.format_stack())

if __name__ == "__main__":
   app.run()

And the response was as expected

Time Before After

PS: Detailed the solution, so you understand how to find solution to such problems

like image 134
Tarun Lalwani Avatar answered Oct 12 '22 05:10

Tarun Lalwani