Can you trigger an AWS Lambda on a dynamic timer?

Is there a way to trigger an AWS Lambda on a dynamic timer? Currently, I am utilizing scheduled-events to trigger the lambda, but this is a set timer. Is there a way to dynamically set a time for the Lambda to be triggered from within the Lambda?

The idea here is that this Lambda does specific checks and executes code to know when it should run next (because I only want this lambda to run when it needs to). I want to 1) determine the next time it needs to run and 2) set the time from within the Lambda code.

I see there are a lot of resources that are used for triggering Lambda functions (SNS, Kinesis, etc.), but I cant seem to find a good way to dynamically kick one off.

Answers 1

  • This can be accomplished by setting a CloudWatch event rule to trigger your Lambda function. On each invocation of your Lambda function, the function will need to determine its next run time and modify the event rule appropriately.

    var AWS = require("aws-sdk");
    
    exports.handler = function(event, context) {
        var cloudwatchevents = new AWS.CloudWatchEvents();
        var intervals = Array(3, 5, 7);
        var nextInterval = intervals[Math.floor(Math.random()*intervals.length)];
        var currentTime = new Date().getTime(); // UTC Time
        var nextTime = dateAdd(currentTime, "minute", nextInterval);
        var nextMinutes = nextTime.getMinutes();
        var nextHours = nextTime.getHours();
    
        //  =================================
        //  DO YOUR WORK HERE
        //  =================================
    
        var scheduleExpression = "cron(" + nextMinutes + " " + nextHours + " * * ? *)";
        var params = {
            Name: "YOUR CLOUDWATCH EVENT RULE NAME",
            ScheduleExpression: scheduleExpression
        };
        cloudwatchevents.putRule(params, function(err, data) {
            if (err) {
                console.log(err, err.stack);  
            }
            else {
                console.log(data);
            }
        })
    };
    
    var dateAdd = function(date, interval, units) {
        var ret = new Date(date); // don't change original date
        switch(interval.toLowerCase()) {
            case 'year'   :  ret.setFullYear(ret.getFullYear() + units);  break;
            case 'quarter':  ret.setMonth(ret.getMonth() + 3*units);  break;
            case 'month'  :  ret.setMonth(ret.getMonth() + units);  break;
            case 'week'   :  ret.setDate(ret.getDate() + 7*units);  break;
            case 'day'    :  ret.setDate(ret.getDate() + units);  break;
            case 'hour'   :  ret.setTime(ret.getTime() + units*3600000);  break;
            case 'minute' :  ret.setTime(ret.getTime() + units*60000);  break;
            case 'second' :  ret.setTime(ret.getTime() + units*1000);  break;
            default       :  ret = undefined;  break;
        }
        return ret;
    }
    

    You should be able to swap my random determination with your own scheduling logic and insert whatever work you need in place of my comment.

    You will need to substitute your event rule's name for "YOUR CLOUDWATCH EVENT RULE NAME" in my snippet.

    Great question for a blog: AWS Lambda Functions That Dynamically Schedule Their Next Runtime


Related Articles