Skip to content

Commit 68cb53b

Browse files
authored
Merge pull request #2876 from agawanea/lambda-durable-scheduled-tasks
New Serverless Pattern - Lambda Durable Functions scheduled tasks pattern with workflow orchestration
2 parents 53e5ca5 + a087988 commit 68cb53b

File tree

10 files changed

+1129
-0
lines changed

10 files changed

+1129
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SAM build artifacts
2+
.aws-sam/
3+
samconfig.toml
4+
5+
# Node.js
6+
node_modules/
7+
package-lock.json
8+
npm-debug.log*
9+
yarn-debug.log*
10+
yarn-error.log*
11+
12+
# Environment variables
13+
.env
14+
.env.local
15+
16+
# IDE
17+
.vscode/
18+
.idea/
19+
*.swp
20+
*.swo
21+
*~
22+
23+
# OS
24+
.DS_Store
25+
Thumbs.db
26+
27+
# Logs
28+
*.log
29+
logs/
30+
31+
# Test coverage
32+
coverage/
33+
.nyc_output/
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
# Multi-Day Scheduled Task Orchestration with AWS Lambda durable functions
2+
3+
This pattern demonstrates multi-day workflows with scheduled waits using AWS Lambda durable functions, showcasing automatic checkpointing and zero compute cost during wait periods.
4+
5+
**Important:** Check regional availability for AWS Lambda durable functions before deployment.
6+
7+
## Architecture
8+
9+
![Architecture Diagram](architecture.png)
10+
11+
The solution uses a streamlined architecture:
12+
- **Durable Function**: Handles async scheduled task orchestration with 7-day workflow and automatic checkpointing
13+
- **Task Management Function**: Unified function providing task listing, status queries, and deletion operations
14+
- **DynamoDB**: Stores task state and progress for real-time monitoring
15+
- **API Gateway**: RESTful API for task creation, status queries, and management
16+
17+
### Workflow Concept
18+
19+
The pattern demonstrates a multi-day workflow with scheduled waits between steps. Each step is automatically checkpointed, and the function incurs no compute charges during wait periods.
20+
21+
22+
23+
24+
25+
## Prerequisites
26+
27+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
28+
* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) installed
29+
* [Node.js 24+](https://nodejs.org/) installed
30+
31+
## Deployment
32+
33+
1. Navigate to the pattern directory:
34+
```bash
35+
cd lambda-durable-scheduled-tasks-sam
36+
```
37+
38+
2. Install dependencies:
39+
```bash
40+
cd src && npm install && cd ..
41+
```
42+
43+
3. Build the SAM application:
44+
```bash
45+
sam build
46+
```
47+
48+
4. Deploy the application:
49+
```bash
50+
sam deploy --guided
51+
```
52+
53+
54+
5. Note the `TaskApiEndpoint` from the outputs.
55+
56+
## Testing
57+
58+
### Step 1: Get Your API Endpoint
59+
60+
Retrieve your API endpoint from the CloudFormation stack:
61+
62+
```bash
63+
aws cloudformation describe-stacks \
64+
--stack-name lambda-durable-scheduled-tasks \
65+
--query 'Stacks[0].Outputs[?OutputKey==`TaskApiEndpoint`].OutputValue' \
66+
--output text
67+
```
68+
69+
### Step 2: Start a Scheduled Task
70+
71+
Create a new scheduled task with custom configuration:
72+
73+
```bash
74+
API_ENDPOINT=$(aws cloudformation describe-stacks \
75+
--stack-name lambda-durable-scheduled-tasks \
76+
--query 'Stacks[0].Outputs[?OutputKey==`TaskApiEndpoint`].OutputValue' \
77+
--output text)
78+
79+
curl -X POST ${API_ENDPOINT}/tasks \
80+
-H "Content-Type: application/json" \
81+
-d '{
82+
"config": {
83+
"reportType": "weekly",
84+
"dataSource": "analytics",
85+
"notifyEmail": "admin@example.com"
86+
}
87+
}'
88+
```
89+
90+
Response:
91+
```json
92+
{
93+
"taskId": "TASK-1733328000000",
94+
"status": "INITIALIZED",
95+
"message": "Task started successfully"
96+
}
97+
```
98+
99+
### Step 3: Check Task Status
100+
101+
Query the task status to see progress:
102+
103+
```bash
104+
TASK_ID="TASK-1733328000000" # Use your actual task ID
105+
106+
curl ${API_ENDPOINT}/tasks/${TASK_ID}
107+
```
108+
109+
Response:
110+
```json
111+
{
112+
"taskId": "TASK-1733328000000",
113+
"status": "DAY_3_COMPLETE",
114+
"currentDay": 3,
115+
"progress": {
116+
"percentage": 43,
117+
"completedDays": 3,
118+
"totalDays": 7,
119+
"steps": [
120+
{
121+
"day": 1,
122+
"action": "Data Collection",
123+
"result": {
124+
"records": 7543,
125+
"sources": ["database", "api", "files"]
126+
},
127+
"completedAt": "2024-12-04T10:00:00.000Z"
128+
},
129+
{
130+
"day": 2,
131+
"action": "Batch Processing",
132+
"result": {
133+
"recordsProcessed": 1823,
134+
"errors": 3
135+
},
136+
"completedAt": "2024-12-05T10:00:00.000Z"
137+
}
138+
]
139+
},
140+
"config": {
141+
"reportType": "weekly",
142+
"dataSource": "analytics",
143+
"notifyEmail": "admin@example.com"
144+
},
145+
"startTime": "2024-12-04T10:00:00.000Z"
146+
}
147+
```
148+
149+
### Step 4: List All Tasks
150+
151+
View all tasks in the system:
152+
153+
```bash
154+
curl ${API_ENDPOINT}/tasks
155+
```
156+
157+
Response:
158+
```json
159+
{
160+
"tasks": [
161+
{
162+
"taskId": "TASK-1733328000000",
163+
"status": "DAY_3_COMPLETE",
164+
"currentDay": 3,
165+
"progress": {...}
166+
}
167+
],
168+
"count": 1
169+
}
170+
```
171+
172+
### Step 5: Testing with Shorter Waits (Development)
173+
174+
For testing purposes, the default wait times are set to 1 minute. To test with real 24-hour intervals, modify the wait times in `src/index.js`:
175+
176+
```javascript
177+
// Change from 1 minute to 24 hours for real intervals
178+
await context.wait({ hours: 24 }); // Instead of { minutes: 1 }
179+
```
180+
181+
This allows you to test the complete 7-day workflow in just 7 minutes during development.
182+
183+
### Step 6: Monitor Execution
184+
185+
View CloudWatch logs for detailed execution information:
186+
187+
```bash
188+
aws logs tail /aws/lambda/lambda-durable-scheduled-tasks-ScheduledTask \
189+
--follow
190+
```
191+
192+
### Step 7: View Final Report
193+
194+
Once the task completes (status: `COMPLETED`), retrieve the final report:
195+
196+
```bash
197+
curl ${API_ENDPOINT}/tasks/${TASK_ID}
198+
```
199+
200+
The response will include a `finalReport` field with comprehensive statistics:
201+
202+
```json
203+
{
204+
"taskId": "TASK-1733328000000",
205+
"status": "COMPLETED",
206+
"finalReport": {
207+
"taskId": "TASK-1733328000000",
208+
"reportType": "weekly",
209+
"summary": {
210+
"totalDays": 7,
211+
"totalRecordsProcessed": 17543,
212+
"totalErrors": 23,
213+
"successRate": "99.87%"
214+
},
215+
"dailyBreakdown": [
216+
{ "day": 1, "type": "collection", "records": 7543 },
217+
{ "day": 2, "type": "processing", "records": 1823, "errors": 3 },
218+
{ "day": 3, "type": "processing", "records": 1654, "errors": 5 }
219+
],
220+
"generatedAt": "2024-12-11T10:00:00.000Z"
221+
}
222+
}
223+
```
224+
225+
## API Reference
226+
227+
### POST /tasks
228+
Start a new scheduled task
229+
230+
**Request Body:**
231+
```json
232+
{
233+
"config": {
234+
"reportType": "weekly",
235+
"dataSource": "analytics",
236+
"notifyEmail": "admin@example.com"
237+
}
238+
}
239+
```
240+
241+
**Response:**
242+
```json
243+
{
244+
"taskId": "TASK-1733328000000",
245+
"status": "INITIALIZED",
246+
"message": "Task started successfully"
247+
}
248+
```
249+
250+
### GET /tasks
251+
List all tasks
252+
253+
**Response:**
254+
```json
255+
{
256+
"tasks": [
257+
{
258+
"taskId": "TASK-1733328000000",
259+
"status": "DAY_3_COMPLETE",
260+
"currentDay": 3,
261+
"progress": {
262+
"percentage": 43,
263+
"completedDays": 3,
264+
"totalDays": 7,
265+
"steps": [...]
266+
},
267+
"config": {...},
268+
"startTime": "2024-12-04T10:00:00.000Z"
269+
}
270+
],
271+
"count": 1
272+
}
273+
```
274+
275+
### GET /tasks/{taskId}
276+
Get task status and progress
277+
278+
**Response:**
279+
```json
280+
{
281+
"taskId": "TASK-1733328000000",
282+
"status": "DAY_3_COMPLETE",
283+
"currentDay": 3,
284+
"progress": {
285+
"percentage": 43,
286+
"completedDays": 3,
287+
"totalDays": 7,
288+
"steps": [...]
289+
}
290+
}
291+
```
292+
293+
### DELETE /tasks
294+
Delete all tasks from DynamoDB
295+
296+
**Response:**
297+
```json
298+
{
299+
"message": "All tasks deleted successfully",
300+
"deletedCount": 5
301+
}
302+
```
303+
304+
## Task Status Values
305+
306+
Tasks progress through various states from `INITIALIZED` to `COMPLETED` or `FAILED`, with intermediate checkpoints automatically saved.
307+
308+
309+
310+
311+
312+
## Cleanup
313+
314+
Delete the CloudFormation stack:
315+
316+
```bash
317+
sam delete --stack-name lambda-durable-scheduled-tasks
318+
```
319+
320+
## Learn More
321+
322+
- [AWS Lambda durable functions Documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
323+
- [JavaScript/TypeScript SDK](https://github.com/aws/aws-durable-execution-sdk-js)
324+
- [AWS Blog Post](https://aws.amazon.com/blogs/aws/build-multi-step-applications-and-ai-workflows-with-aws-lambda-durable-functions/)
325+
326+
327+
## License
328+
329+
This library is licensed under the MIT-0 License. See the LICENSE file.
330+
331+
---
332+
333+
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
334+
335+
SPDX-License-Identifier: MIT-0
423 KB
Loading

0 commit comments

Comments
 (0)