Skip to content
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

Botocore endpoint timeout not the same as the lambda timeout #2657

Open
lucasdf opened this issue Jun 11, 2017 · 12 comments · Fixed by #2689
Open

Botocore endpoint timeout not the same as the lambda timeout #2657

lucasdf opened this issue Jun 11, 2017 · 12 comments · Fixed by #2689
Labels
feature-request A feature should be added or improved. lambda needs-discussion p3 This is a minor priority issue

Comments

@lucasdf
Copy link

lucasdf commented Jun 11, 2017

Issue:

I have an AWS Lambda function that is expected to run for a few minutes and it has a timeout of 4 minutes. I noticed that when I invoke this function using the CLI the function is always invoked multiple times, basically once every one minute.

By using the "--debug" flag I noticed that botocore is setting the timeout of the endpoint as 60 seconds. So this is the cause of the multiple invocations: since the CLI reaches the timeout after one minute it sends a new request every minute, despite the fact that the lambda function's own timeout is higher than this value and the first invocation is still being processed.

Questions:

  1. What is the expected behaviour of botocore/aws-cli: is it to use 60 seconds as timeout no matter what the lambda function timeout is, or is the expected behaviour to get the timeout value from the function definition? It seems to me that using the same timeout as the function should be the expected behaviour. If indeed it is then there seems to be something wrong when setting this value.
  2. Is there a way to set the timeout value while invoking aws lambda invoke? aws lambda invoke help does not display any information regarding this.

Commands:
I am invoking the function using the following command:
aws lambda invoke --function-name FUNCTION_NAME --payload 'JSON_PAYLOAD' output.json
The debug flag shows the following message:
MainThread - botocore.endpoint - DEBUG - Setting lambda timeout as (60, 60)

Versions:
aws-cli/1.11.93 Python/2.7.12 Linux/4.4.0-79-generic botocore/1.5.56
My lambda function is using Python 3.6

Reproducing the issue:
It should be possible to reproduce it by creating a lambda function that just sleeps for more than 60 seconds and invoking it by using the CLI.

tl;dr:
My function is being invoked multiple times because botocore is using 60 seconds as the timeout instead of using the four minutes that is defined in my lambda function. The expected behaviour should be to use the same timeout used by the lambda function. At least there should be a way for me to define the timeout value as a parameter when using aws lambda invoke.

@jamesls
Copy link
Member

jamesls commented Jun 12, 2017

The expected behavior is to use the default of 60 seconds for all operations. Changing the defaults is tricky, especially for people that may be relying on the existing behavior. To control the timeout per-invocation, you can specify the --cli-read-timeout option to the number of seconds to wait before timing out.

aws lambda invoke --cli-read-timeout 240 --function-name FUNCTION_NAME --payload 'JSON_PAYLOAD' output.json

Let me know if you have any more questions.

@jamesls jamesls added closing-soon This issue will automatically close in 4 days unless further comments are made. question labels Jun 12, 2017
@lucasdf
Copy link
Author

lucasdf commented Jun 12, 2017

@jamesls oh I see. It took me a while to understand why the function was being invoked multiple times.

Do you think it would make sense to have an option such as "--use-resource-timeout" that would get the resource configuration, parse the timeout and use it instead of using the default of 60 seconds?

@jamesls
Copy link
Member

jamesls commented Jun 14, 2017

It's an interesting idea, that would require an extra API call to get that value before invoking the function. You could write an CLI alias (https://github.com/awslabs/awscli-aliases) that did that. It would look something like:

invoke-function = 
  !f() {
   aws lambda invoke ... \
     --cli-read-timeout $(aws lambda get-function-configuration --function-name $1 --query Timeout --output text)
  }; f

@lucasdf
Copy link
Author

lucasdf commented Jun 15, 2017

I wrote an alias to do that, but it seems that bash does not like arguments with quotes or double quotes, so this only works if the payload is loaded from a file and it won't work when the JSON is written inline.

aws lambda-invoke --function-name LAMBDA_NAME --payload file://FILE_NAME output.temp

lambda-invoke =
  !f() {
    set -e
    args="$*"

    for i in "$@"; do
      if [ "$i" = "--function-name" ]; then
        shift
        lambda_name="$1"
        break
      fi
      shift
    done
    timeout=$(aws lambda get-function-configuration --function-name $lambda_name --query Timeout --output text)
    aws lambda invoke --cli-read-timeout $timeout $args
  }; f

Another option, which is the one that I am using, is to use an alias to get the timeout only.

aws lambda invoke --function-name LAMBDA_NAME --payload PAYLOAD --cli-read-timeout $(aws lambda-timeout LAMBDA_NAME) output.temp

lambda-timeout =
  !f() {
    aws lambda get-function-configuration --function-name "$1" --query Timeout --output text
  }; f

@AlJohri
Copy link

AlJohri commented Nov 23, 2018

@jamesls just got burned by this- couldn't tell for the life of me while the lambda kept "restarting" even though it was in RequestResponse mode. I realized that since the request id's weren't the same it wasn't "restarting" but instead multiple invocations exactly 1 minute spaced apart. Like @lucasdf mentioned, --debug helped me figure it out for sure.

I believe this should be mentioned in the aws lambda invoke help page along with the boto3 documentation as suggested here (boto/boto3#883 (comment)).

@diehlaws diehlaws added guidance Question that needs advice or information. and removed question labels Jan 4, 2019
@AlJohri
Copy link

AlJohri commented Apr 5, 2019

Wow, I just got burned by this again. Tried to invoke a long running lambda from the CLI and it fired twice. Ended up sending emails to all my users twice. This is definitely not obvious from reading the command. Please change the default!

@jmehnle
Copy link

jmehnle commented Jan 27, 2021

This issue was closed by a commit that "quote[s] arguments in aliases" (#2689). This merely facilitates one particular work-around for this issue but in no way actually fixes the issue. At the very least the aws lambda invoke help documentation should be updated to very prominently call out that if your synchronous lambda takes more than 60 seconds to return a response, it will be implicitly reinvoked every 60 seconds.

I inherited a lambda function that rotates the master user password shared by multiple RDS clusters, and this generally takes on the order of 75-120 seconds, causing an implicit reinvocation by the aws CLI. And it just so happened that this reinvocation interfered with the initial run, which was still in the process of updating the first cluster's password, which then makes both invocations fail and retry internally, which makes the aws CLI retry even more times. Granted, this may not be the best designed lambda (again, I inherited this), but it took me hours to figure out that it's the aws CLI that's quietly making multiple retries.

Honestly, though, this issue should be fixed regardless of documentation.

@kdaily kdaily reopened this Jan 28, 2021
@kdaily kdaily added lambda needs-discussion and removed closing-soon This issue will automatically close in 4 days unless further comments are made. guidance Question that needs advice or information. labels Jan 28, 2021
@kdaily
Copy link
Member

kdaily commented Jan 28, 2021

@jmehnle, thanks for your comments. I'm reopening to review the behavior.

I would agree that documentation improvements would be welcome - I'll open a separate issue for that.

@hack2learn
Copy link

it would be great if the cli command could use the lambda's configured timeout.

@kdaily kdaily added the feature-request A feature should be added or improved. label Jun 3, 2021
@irvintim
Copy link

Wouldn't the easiest thing to do be to just make the default --cli-read-timeout be 900 (or maybe 910) when calling "lambda invoke"? 900 is the max lambda timeout, so it will end when the Lambda completes, or when it timeouts.

@frenchtoastbeer
Copy link

I don't want to increase the timeout, I want to disable the retry.

@jdsampayo
Copy link

@frenchtoastbeer in order to disable the retry you can use:

AWS_MAX_ATTEMPTS=1 aws lambda invoke ...

cmoralesmx added a commit to cmoralesmx/aws-lambda-developer-guide that referenced this issue Sep 28, 2022
There is an information gap regarding long-running lambda functions
invoked synchronously via the AWS CLI under default conditions.
Two possible solutions to address this are included, these are mentioned
[here](aws/aws-cli#2657).
@tim-finnigan tim-finnigan added the p3 This is a minor priority issue label Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved. lambda needs-discussion p3 This is a minor priority issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.