diff --git a/lambda-durable-eventbridge-cron-python-sam/EventBridge_DF_architecture.png b/lambda-durable-eventbridge-cron-python-sam/EventBridge_DF_architecture.png new file mode 100644 index 000000000..df6f7165a Binary files /dev/null and b/lambda-durable-eventbridge-cron-python-sam/EventBridge_DF_architecture.png differ diff --git a/lambda-durable-eventbridge-cron-python-sam/README.md b/lambda-durable-eventbridge-cron-python-sam/README.md new file mode 100644 index 000000000..a234e5742 --- /dev/null +++ b/lambda-durable-eventbridge-cron-python-sam/README.md @@ -0,0 +1,97 @@ +# EventBridge Cron to Durable Lambda Function + +This pattern demonstrates how to trigger a durable Lambda function using EventBridge on a cron schedule. The Lambda function uses the AWS Durable Execution SDK to implement a multi-step workflow with checkpointing and automatic replay capabilities. + +Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >> + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Architecture + +![Architecture](EventBridge_DF_architecture.png) + +This architecture demonstrates a serverless cron job implementation using EventBridge and durable Lambda functions. An EventBridge rule configured with a cron expression triggers the durable Lambda function every minute. The Lambda function uses the AWS Durable Execution SDK to implement a multi-step workflow that can span multiple invocations through checkpointing - when `context.wait()` is called, the function suspends execution and creates a checkpoint, then resumes from that point in a subsequent invocation without re-executing previous steps. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed +* [Python 3.14](https://www.python.org/downloads/) installed and available in your PATH + +## Deployment Instructions + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` + git clone https://github.com/aws-samples/serverless-patterns + ``` +1. Change directory to the pattern directory: + ``` + cd lambda-durable-eventbridge-cron-python-sam + ``` +1. From the command line, use AWS SAM to build and deploy the AWS resources for the pattern as specified in the template.yaml file: + ``` + sam build + sam deploy --guided + ``` +1. During the prompts: + * Enter a stack name + * Enter the desired AWS Region + * Allow SAM CLI to create IAM roles with the required permissions. + + Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. + +1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. + +## How it works + +This pattern creates: + +1. **Durable Lambda Function**: A Python 3.14 Lambda function that uses the AWS Durable Execution SDK to implement a multi-step workflow with automatic checkpointing and replay capabilities. + +2. **EventBridge Cron Rule**: An EventBridge rule configured with `cron(* * * * ? *)` that triggers the Lambda function every minute. + +3. **Function Versioning**: The Lambda function uses `AutoPublishAlias: live` to automatically publish a new version on each deployment and point the `live` alias to it. + +4. **Targeted Invocation**: The EventBridge rule specifically targets the published version via the alias as it is a best practice to use numbered versions or aliases for production durable functions rather than $LATEST. + +### Durable Execution Flow + +The Lambda function implements a durable workflow with three steps: + +1. **Data Fetching**: Simulates fetching data from an external API (checkpointed) +2. **Wait Period**: Suspends execution for 10 seconds using `context.wait()` - no compute costs during wait +3. **Data Processing**: Processes the fetched data and returns results + +**Execution Pattern**: +- **Invocation 1**: `fetch_data()` runs → checkpoint created → `context.wait()` suspends execution +- **Invocation 2**: `fetch_data()` replays from checkpoint (no re-execution) → wait completes → `process_data()` runs → workflow completes + +This demonstrates how durable functions can span multiple Lambda invocations while maintaining state and avoiding redundant work through checkpointing. + +## Testing + +1. After deployment, the EventBridge rule will automatically trigger the Lambda function every minute. + +2. Monitor the function execution in CloudWatch Logs: + ```bash + aws logs tail /aws/lambda/[FUNCTION_NAME] --follow + ``` + +3. You should observe the durable execution pattern: + - First invocation: "Fetching data from external API..." followed by suspension + - Second invocation: "Processing data..." (fetch_data skipped due to checkpoint) + +4. You can also see the durable execution section in the Lambda function console to get a detailed overview of each execution step in the execution. + +## Cleanup + +1. Delete the stack + ```bash + sam delete + ``` +---- +Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/lambda-durable-eventbridge-cron-python-sam/example-pattern.json b/lambda-durable-eventbridge-cron-python-sam/example-pattern.json new file mode 100644 index 000000000..2fdd0f29a --- /dev/null +++ b/lambda-durable-eventbridge-cron-python-sam/example-pattern.json @@ -0,0 +1,63 @@ +{ + "title": "EventBridge Cron to durable Lambda function", + "description": "Create a durable Lambda function triggered by EventBridge on a cron schedule using AWS SAM.", + "language": "Python", + "level": "200", + "framework": "AWS SAM", + "introBox": { + "headline": "How it works", + "text": [ + "This sample project demonstrates how to create a durable Lambda function that is triggered by EventBridge on a cron schedule. The Lambda function uses the AWS durable Execution SDK to implement a multi-step workflow with automatic checkpointing and replay capabilities.", + "The durable execution pattern allows Lambda functions to span multiple invocations while maintaining state. When the function calls context.wait(), it suspends execution and creates a checkpoint. A subsequent invocation resumes from the checkpoint without re-executing previous steps.", + "This pattern deploys a durable Lambda function with Python 3.14 runtime, an EventBridge rule with cron schedule, and uses function versioning to ensure the cron trigger targets a published version rather than $LATEST." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-durable-eventbridge-cron-python-sam", + "templateURL": "serverless-patterns/lambda-durable-eventbridge-cron-python-sam", + "projectFolder": "lambda-durable-eventbridge-cron-python-sam", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "AWS Lambda durable functions", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html" + }, + { + "text": "Invoking AWS Lambda durable functions", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/durable-invoking.html" + }, + { + "text": "AWS durable execution SDK for Python", + "link": "https://github.com/aws/aws-durable-execution-sdk-python" + } + ] + }, + "deploy": { + "text": [ + "sam build", + "sam deploy --guided" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: sam delete." + ] + }, + "authors": [ + { + "name": "Sidharth Kothari", + "image": "https://drive.google.com/file/d/1sUXFJLHYuCmadcu4Q7mhb0mBnWfTcrtT/view", + "bio": "Cloud Engineer II at AWS with deep expertise in serverless, event-driven and microservice-based solutions. Passionate about building scalable, secure and distributed applications that help organizations modernize their infrastructure and accelerate innovation.", + "linkedin": "sidharthkothari" + } + ] +} \ No newline at end of file diff --git a/lambda-durable-eventbridge-cron-python-sam/src/lambda_function.py b/lambda-durable-eventbridge-cron-python-sam/src/lambda_function.py new file mode 100644 index 000000000..906e60b59 --- /dev/null +++ b/lambda-durable-eventbridge-cron-python-sam/src/lambda_function.py @@ -0,0 +1,41 @@ +from aws_durable_execution_sdk_python.config import Duration +from aws_durable_execution_sdk_python.context import DurableContext, StepContext, durable_step +from aws_durable_execution_sdk_python.execution import durable_execution + +@durable_step +def fetch_data(step_context: StepContext) -> dict: + """Simulate fetching data from an external source.""" + # This runs only once — on replay, the checkpointed result is returned. + print("Fetching data from external API...") + return {"items": [1, 2, 3], "source": "external-api"} + + +@durable_step +def process_data(step_context: StepContext, data: dict) -> dict: + """Simulate processing the fetched data.""" + print("Processing data...") + total = sum(data["items"]) + return {"total": total, "source": data["source"], "status": "processed"} + + +@durable_execution +def lambda_handler(event: dict, context: DurableContext) -> dict: + """ + Durable function triggered by EventBridge cron. + + Execution flow: + Invocation 1: fetch_data runs → checkpoint → wait suspends execution + Invocation 2: fetch_data replays from cache → wait completes → process_data runs → done + """ + # Step 1: Fetch data (checkpointed, won't re-execute on replay) + data = context.step(fetch_data()) + + # Step 2: Wait 10 seconds (Lambda suspends, no idle compute cost) + context.wait(Duration.from_seconds(10)) + + # Step 3: Process the data + result = context.step(process_data(data)) + + return result + + diff --git a/lambda-durable-eventbridge-cron-python-sam/src/requirements.txt b/lambda-durable-eventbridge-cron-python-sam/src/requirements.txt new file mode 100644 index 000000000..ade9ff0ef --- /dev/null +++ b/lambda-durable-eventbridge-cron-python-sam/src/requirements.txt @@ -0,0 +1 @@ +aws-durable-execution-sdk-python==1.3.0 \ No newline at end of file diff --git a/lambda-durable-eventbridge-cron-python-sam/template.yaml b/lambda-durable-eventbridge-cron-python-sam/template.yaml new file mode 100644 index 000000000..24c1ccff3 --- /dev/null +++ b/lambda-durable-eventbridge-cron-python-sam/template.yaml @@ -0,0 +1,62 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Durable Lambda function triggered by an EventBridge cron schedule every 1 minute + +Globals: + Function: + Timeout: 900 + MemorySize: 256 + Runtime: python3.14 + +Resources: + # Durable Lambda function — publishes a new version on each deploy + DurableCronFunction: + Type: AWS::Serverless::Function + Properties: + Handler: lambda_function.lambda_handler + CodeUri: src/ + AutoPublishAlias: live + DurableConfig: + ExecutionTimeout: 900 + RetentionPeriodInDays: 7 + Description: Durable execution Lambda triggered every minute by EventBridge + Policies: + - Statement: + - Effect: Allow + Action: + - lambda:InvokeFunction + Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:* + + # EventBridge rule — every minute cron schedule + HourlyCronRule: + Type: AWS::Events::Rule + Properties: + Description: Triggers the durable Lambda function every minute + ScheduleExpression: cron(* * * * ? *) + State: ENABLED + Targets: + - Arn: !Ref DurableCronFunction.Alias + Id: DurableCronFunctionTarget + + # Permission for EventBridge to invoke the published alias + HourlyCronRulePermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref DurableCronFunction.Alias + Action: lambda:InvokeFunction + Principal: events.amazonaws.com + SourceArn: !GetAtt HourlyCronRule.Arn + +Outputs: + DurableCronFunctionAliasArn: + Description: ARN of the live alias (published version) + Value: !Ref DurableCronFunction.Alias + PublishedVersion: + Description: Latest published version number + Value: !Ref DurableCronFunction.Version + DurableCronFunctionName: + Description: Name of the durable cron Lambda function + Value: !Ref DurableCronFunction + HourlyCronRuleArn: + Description: ARN of the EventBridge every-minute cron rule + Value: !GetAtt HourlyCronRule.Arn