Have you come across a time where you wanted to run a lambda function at a particular time or a sequence of lambda functions at particular intervals? I came across this problem in one of our projects where we needed to control the execution according to the start time and end time of an online classroom. So how can you execute your lambda at a particular time or how can you keep a time interval between the execution of sequence of lambdas? Aws provide a solution to these using AWS Step Functions. While Step Functions provide a wide variety of uses, scheduling your lambda function to given time or time interval is a key use.
What is a Step Function?
Step Functions are a way of controling workflow in aws. It lets you control and stitch together multiple aws resources with a series of steps.
Example Scenario
What we will be discussing in this article is an online classroom. When an user creates a classroom, two separate lambda functions should send data to the classroom server at the start time and end time respectively. We will use a step function to build this process.
Define the step function
Before executing the step function we need to define a state machine using Step Functions console or serverless.yml if you are using serverless framework.
If you use the console you can follow this link to create the state machine. Use the state machine definition below in the State machine definition pane.
If you are using serverless framework you can use the following definition in your serverless.yml.
stepFunctions:
stateMachines:
stepFunction:
events:
- http:
path: classroom/create
method: POST
name: classroom-state-machine
definition:
StartAt: RecordingWait
States:
RecordingWait:
Type: Wait
TimestampPath: "$.start"
Next: StartRecording
StartRecording:
Type: Task
Resource: arn:aws:lambda:ap-southeast-1:13######:function:consult-api-dev-StartRecorder
Next: SendLivePingWait
SendLivePingWait:
Type: Wait
Seconds: 60
Next: StoppingWait
SendLivePing:
Type: Task
Resource: arn:aws:lambda:ap-southeast-1:13######:function:consult-api-dev-SendLivePing
Next: StoppingWait
StoppingWait:
Type: Wait
TimestampPath: "$.end"
Next: StopRecording
StopRecording:
Type: Task
Resource: arn:aws:lambda:ap-southeast-1:13######:function:consult-api-dev-StopRecorder
End: true
Let's go through this definition. First you have to define this under stepFunctions in the serverless.yml file. You can define a http event handler if you want but this is optional.
events:
- http:
path: classroom/create
method: POST
Give a name to the state machine (name: classroom-state-machine
). In the state machine you can define several states. Each state would mean either a task or time interval (Type: Task/Wait
). A typical task would be a lambda function. A time interval or a wait step is to define time periods between the execution of tasks. This is what comes in handy when you want to schedule a lambda. In a task you need to provide the ARN of the resource (i.e. ARN of lambda function) and what would be the next state (Next: StartRecording
)that would be executed.
In the definition, first you have to define at what state the execution of the state machine should begin (StartAt: RecordingWait
) and in one of the states you should define where it ends by giving End:true
. Flow of the state machine would be defined by Next
and End
statements in the state.
Execute the Step Function
We have now defined the state machine in serverless framework. Now you can execute it in a lambda or any other function. Given below is the function used to start the execution of this step function.
const AWS = require("aws-sdk");
const stepFunction = new AWS.StepFunctions();
function executeRecordingStateMachine(start, end, className) {
const Param = {
stateMachineArn: RECORDER_STATE_MACHINE_ARN,
input: JSON.stringify({ start, end }),
name: className,
};
return new Promise((resolve, reject) => {
stepFunction.startExecution(Param, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
Here in Param
which we passed to the startExecution
method of the step function, we need to give the arn of the state machine, data object that we would be sending to the start state of the state machine and the name of the state machine to identify a particular execution. Giving an unique name to the execution would be helpful since we can see the current state in the visual flow diagram of the state machine in step functions console. Here we have used the classroom id as the execution name.
Explaining the example
The above definition is of a online classroom where recording of the classroom should begin at the start time of the class, send a live status to the classroom and recording should stop at the class end time. The execution begins at RecordingWait
state which is a wait step and it waits until start
which is the timestamp of the class start time. Here $.start
means start time we passed at the start of the execution. Normally, a classroom is scheduled at least a day prior to the class start time. At the time of class creation we would start the execution of the state machine. The state machine would wait until the classroom start time to start the recording. This is the functionality that the state machine brings in.
At the class start time, the state machine would move to the next state which is StartRecording
which is a lambda function to start the recorder. After starting the recorder it will move on to the next state which is SendLivePingWait
which is a wait step. This is a bit different to the first wait step since here the time period would be defined in seconds and not timestamp. So the state machine would wait 60 seconds as per this example before moving on to the next state which is to execute the task SendLivePing
. After executing the SendLivePing
state it would again wait till the end of class to stop the recorder. At the end time it will execute the StopRecorder
task to stop the recorder and it will end the state machine there since we have defined to end the state machine there.
P.S. : To pass data after the execution of a lambda to the next state, the data should be returned in the callback of the lambda function.
Leave a Comment