Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invoke lambda function with hours delay

Tags:

aws-lambda

I am trying to figure out what is the best approach to invoke an aws lambda function 5 hours later. I have another lambda function that would issue multiple retrieval jobs to grab items out of aws glacier, and I need a solution to run another lambda function on each of the items once they are retrieved, which is about 5 hours. I was thinking about using sns but was wondering if there are other approaches to this. any input is appreciated.

like image 589
Calvin Avatar asked Oct 23 '17 20:10

Calvin


People also ask

How do you trigger Lambda function every hour?

You can also create a Lambda function and direct AWS Lambda to invoke it on a regular schedule. You can specify a fixed rate (for example, invoke a Lambda function every hour or 15 minutes), or you can specify a Cron expression. Open the Functions page of the Lambda console. Under Function overview, choose Add trigger.

Can Lambda run on schedule?

You can set up a rule to run an AWS Lambda function on a schedule. This tutorial shows how to use the AWS Management Console or the AWS CLI to create the rule.

How do you trigger a Lambda function every 24 hours?

To trigger a Lambda function once every 20 or 24 hours, we can schedule a trigger in CloudWatch Events. CloudWatch Events allows targets to be triggered using a Schedule Expression. A Schedule Expression can define a rate; for example, every 24 hours. Or can accept a standard cron job expression.


2 Answers

Besides using CloudWatch, another interesting approach in your case would be to use AWS Step Functions:

  1. Either use a wait state by setting a fixed period (or even a dynamic one if you provide input data to the state machine):

    {
      "Comment": "An example of the Amazon States Language using wait states",
      "StartAt": "WaitState",
      "States": {
        "WaitState": {
          "Type": "Wait",
          "Seconds": 10,
          "Next": "MyLambda"
        },
        "MyLambda": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
          "End": true
        }
      }
    }
    
  2. Or you can use a separate Lambda function in a task state combined with a choice state which checks in a loop if the other function should run:

    {
      "Comment": "A state machine that submits a Job to AWS Batch and monitors the Job until it completes.",
      "StartAt": "Wait X Seconds",
      "States": {
        "Wait X Seconds": {
          "Type": "Wait",
          "SecondsPath": "$.wait_time",
          "Next": "Get Job Status"
        },
        "Get Job Status": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:CheckJob",
          "Next": "Job Complete?"
        },
        "Job Complete?": {
          "Type": "Choice",
          "Choices": [
            {
              "Variable": "$.status",
              "StringEquals": "RUNNING",
              "Next": "Wait X Seconds"
            },
            {
              "Variable": "$.status",
              "StringEquals": "SUCCEEDED",
              "Next": "Do Job"
            }
          ],
          "Default": "Wait X Seconds"
        },
        "Do Job": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:DoJob",
          "End": true
        }
      } 
    }
    
like image 116
s.hesse Avatar answered Jan 12 '23 01:01

s.hesse


I feel that the cloudwatch and step-functions based solutions do not scale well and they are pretty heavy code-wise.

I recommend creating two SQS queues. One will be the waiting queue, and the other one will be the execution queue.

Waiting Queue: Set the execution queue as the deadletter queue of the waiting queue. Set the Default Visibility Timeout equal to the time you want to wait to run the lambda (up to 12 hours). Set maximum receives of 1. Create a Lambda that consumes an SQS message and returns an error. Add the waiting queue as a trigger to this lambda.

exports.handler =  async function(event, context) {
  throw new Error('Go back to the waiting queue and wait');
}

Execution Queue: Add the execution queue as a trigger to your Lambda (that you want to schedule).

Then, to schedule your lambda you need to simply post a message to the waiting queue.

The message will go to the waiting queue where it will be consumed by the error-out lambda. It will tgen sit on the waiting queue until its visibility times out and it will be pushed to the deadletter execution queue for pickup by your scheduled lambda.

like image 25
Ioannis Tsiokos Avatar answered Jan 12 '23 01:01

Ioannis Tsiokos