Skip to content

Commit 7c5900c

Browse files
MEPalmajoe4dev
authored andcommitted
concurrency sample
1 parent 6545cf8 commit 7c5900c

File tree

9 files changed

+186
-3
lines changed

9 files changed

+186
-3
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Python: Remote Attach",
6+
"type": "debugpy",
7+
"request": "attach",
8+
"connect": {
9+
"host": "localhost",
10+
"port": 19891
11+
},
12+
"pathMappings": [
13+
{
14+
"localRoot": "${workspaceFolder}",
15+
"remoteRoot": "."
16+
}
17+
]
18+
}
19+
]
20+
}
21+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export AWS_ACCESS_KEY_ID ?= test
2+
export AWS_SECRET_ACCESS_KEY ?= test
3+
export AWS_DEFAULT_REGION = us-east-1
4+
VENV_DIR ?= .venv
5+
6+
usage: ## Show this help
7+
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
8+
9+
install: ## Install dependencies
10+
@which awslocal || pip install awscli-local
11+
test -e $(VENV_DIR) || virtualenv $(VENV_DIR)
12+
. $(VENV_DIR)/bin/activate; pip install debugpy
13+
14+
run: ## Deploy and invoke the Lambda container locally
15+
echo "Deploying Lambda locally"; \
16+
./run.sh; \
17+
echo "Done - test successfully finished."
18+
19+
.PHONY: usage install run
20+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# LocalStack Demo: Lambda Debug Mode Automatically Handle Concurrent Function Invocations
2+
3+
A simple demo application showcasing how to Lambda Debug Mode automatically controls concurrent lambda call invocations.
4+
The demo deploys a Lambda function with a one-second timeout, and continues to invoke this function
5+
three times. Upon connecting the remote debugger, the user should see how only the first call is received and can be
6+
debugged, with concurrency error messages being logged about the following two invocations.
7+
8+
## Prerequisites
9+
10+
* LocalStack
11+
* Docker
12+
* `make`
13+
* [`awslocal`](https://github.com/localstack/awscli-local)
14+
15+
## Installing
16+
17+
To install the dependencies:
18+
```
19+
make install
20+
```
21+
22+
## Starting Up
23+
24+
Make sure that LocalStack is started with the following configuration:
25+
```
26+
LAMBDA_DEBUG_MODE=1 \
27+
LAMBDA_DEBUG_MODE_CONFIG_PATH=path/to/lambda_debug_mode_config.yaml \
28+
localstack start
29+
```
30+
31+
Lambda Debug Mode is enabled through the config option `LAMBDA_DEBUG_MODE=1`.
32+
33+
The config option `LAMBDA_DEBUG_MODE_CONFIG_PATH` should point to the provided `yaml` config file for Lambda Debug Mode `lambda_debug_mode_config.yaml`.
34+
The config file contains instructions for Lambda Debug Mode to debug the Lambda function `arn:aws:lambda:us-east-1:000000000000:function:function-one` on port `19891`.
35+
36+
37+
## Running the Sample
38+
39+
The project ships with a Visual Studio Code debug launch config (see `.vscode/launch.json`). This configuration can be used to attach to the code in the Lambda function while it is executing.
40+
41+
The following command used to deploy and invoke the Lambda locally:
42+
43+
```
44+
make run
45+
```
46+
47+
### Attaching the VSCode Debugger
48+
49+
After the Lambda function is invoked you can switch to Visual Studio Code, set a breakpoint in the Lambda handler, and run the preconfigured remote debugger.
50+
LocalStack will automatically waive the set one second timeout for the Lambda function, giving you ample time to connect the debugger and debug the logic in the function.
51+
You should also notice how the debugger connects to the first invocation (the message object would end with `Attempt 1`), whilst the following invocations
52+
are refused automatically by Lambda Debug Mode as explained in the corresponding log messages.
53+
54+
## License
55+
56+
The code in this sample is available under the Apache 2.0 license.
57+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
def handler(event, context):
2+
"""Lambda handler that will get invoked by the LocalStack runtime"""
3+
4+
# Wait for the debugger to get attached.
5+
wait_for_debug_client()
6+
7+
# Print the incoming invocation event.
8+
print(event)
9+
10+
# Return the incoming invocation event.
11+
return event
12+
13+
14+
def wait_for_debug_client(timeout=15):
15+
"""Utility function to enable debugging with Visual Studio Code"""
16+
import time, threading
17+
import sys, glob
18+
sys.path.append(glob.glob(".venv/lib/python*/site-packages")[0])
19+
import debugpy
20+
21+
debugpy.listen(("0.0.0.0", 19891))
22+
class T(threading.Thread):
23+
daemon = True
24+
def run(self):
25+
time.sleep(timeout)
26+
print("Canceling debug wait task ...")
27+
debugpy.wait_for_client.cancel()
28+
T().start()
29+
print("Waiting for client to attach debugger ...")
30+
debugpy.wait_for_client()
31+
32+
33+
if __name__ == "__main__":
34+
handler({}, {})
35+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
functions:
2+
arn:aws:lambda:us-east-1:000000000000:function:function-one:
3+
debug-port: 19891
4+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
#
3+
# Set the name of the Lambda function.
4+
FUNCTION_NAME="function-one"
5+
6+
# Create the Lambda function 'function-one' through hot-reload with one second timeout.
7+
echo "Creating Lambda function $FUNCTION_NAME through hot-reload with one second timeout."
8+
awslocal lambda create-function \
9+
--function-name "$FUNCTION_NAME"\
10+
--timeout 1 \
11+
--code "S3Bucket=hot-reload,S3Key=$(pwd)/" \
12+
--handler handler.handler \
13+
--role arn:aws:iam::000000000000:role/test-role \
14+
--runtime python3.9
15+
16+
# Function to check the status of the Lambda function.
17+
check_lambda_status() {
18+
status=$(awslocal lambda get-function --function-name "$FUNCTION_NAME" 2>&1)
19+
# Check if "Active" is in the response
20+
if echo "$status" | grep -q "Active"; then
21+
return 0
22+
fi
23+
return 1
24+
}
25+
26+
# Wait until the Lambda function is active
27+
echo "Waiting for Lambda function to become active..."
28+
while true; do
29+
if check_lambda_status; then
30+
echo "Lambda function is active."
31+
break
32+
else
33+
echo "Lambda function is still pending. Waiting..."
34+
sleep 1
35+
fi
36+
done
37+
38+
# Invoke the Lambda function 3 times every 5 seconds.
39+
for i in {1..3}; do
40+
echo "Invoking the Lambda function, attempt $i."
41+
awslocal lambda invoke \
42+
--function-name function-one \
43+
test.lambda.$i.log \
44+
--payload "{\"message\": \"Testing Lambda Debug Mode lifting the 1-second timeout for function-one. Attempt $i.\"}" &
45+
sleep 5
46+
done

lambda-debug-mode/python/base-enable-lambda-debug-mode/handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def handler(event, context):
77
# Print the incoming invocation event.
88
print(event)
99

10-
# Return the incomeing invocation evant.
10+
# Return the incoming invocation event.
1111
return event
1212

1313

lambda-debug-mode/python/base-multiple-lambda-debug-mode/handler_function_one.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def handler(event, context):
1010
# Print the incoming invocation event.
1111
print(event)
1212

13-
# Return the incomeing invocation evant.
13+
# Return the incoming invocation event.
1414
return event
1515

1616

lambda-debug-mode/python/base-multiple-lambda-debug-mode/handler_function_two.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def handler(event, context):
1010
# Print the incoming invocation event.
1111
print(event)
1212

13-
# Return the incomeing invocation evant.
13+
# Return the incoming invocation event.
1414
return event
1515

1616

0 commit comments

Comments
 (0)