In this demo, we will:
AWSLambdaBasicExecutionRole
AWSXRayDaemonWriteAccess
AmazonDynamoDBFullAccess
LambdaXRayRole
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:*:*:function:GetProductFunction"
}
]
}
LambdalnvokePolicy
ProductCatalog
ProductId
{
"ProductId": {
"S": "PROD-001"
},
"ProductName": {
"S": "Wireless Mouse"
},
"Price": {
"N": "29.99"
},
"Category": {
"S": "Electronics"
},
"Stock": {
"N": "150"
}
}
{
"ProductId": {
"S": "PROD-002"
},
"ProductName": {
"S": "Mechanical Keyboard"
},
"Price": {
"N": "89.99"
},
"Category": {
"S": "Electronics"
},
"Stock": {
"N": "75"
}
}
GetProductFunction
import json
import boto3
import random
import time
# Initialize DynamoDB client
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('ProductCatalog')
def lambda_handler(event, context):
# Simulate variable processing time
process_time = random.uniform(0.1, 0.5)
try:
# Extract product ID from event
if 'pathParameters' not in event or 'productId' not in event['pathParameters']:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Product ID is required'}),
'headers': {
'Content-Type': 'application/json'
}
}
product_id = event['pathParameters']['productId']
print(f"Fetching product: {product_id}")
# Simulate validation processing
time.sleep(process_time)
# Query DynamoDB
response = table.get_item(Key={'ProductId': product_id})
if 'Item' not in response:
print(f"Product not found: {product_id}")
return {
'statusCode': 404,
'body': json.dumps({'error': 'Product not found'}),
'headers': {
'Content-Type': 'application/json'
}
}
print(f"Product found: {product_id}")
# Simulate post-processing
time.sleep(0.1)
return {
'statusCode': 200,
'body': json.dumps(response['Item'], default=str),
'headers': {
'Content-Type': 'application/json'
}
}
except Exception as e:
print(f"Error: {str(e)}")
import traceback
traceback.print_exc()
return {
'statusCode': 500,
'body': json.dumps({'error': 'Internal server error', 'details': str(e)}),
'headers': {
'Content-Type': 'application/json'
}
}
ProcessOrderFunction
import json
import boto3
import random
import time
from datetime import datetime
# Initialize clients
dynamodb = boto3.resource('dynamodb')
lambda_client = boto3.client('lambda')
table = dynamodb.Table('ProductCatalog')
def lambda_handler(event, context):
# Parse request body
try:
if 'body' in event:
body = json.loads(event['body'])
else:
body = event
product_id = body.get('productId')
quantity = body.get('quantity', 1)
print(f"Processing order - Product: {product_id}, Quantity: {quantity}")
except Exception as e:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Invalid request body'}),
'headers': {
'Content-Type': 'application/json'
}
}
try:
# Call GetProductFunction to validate product exists
invoke_response = lambda_client.invoke(
FunctionName='GetProductFunction',
InvocationType='RequestResponse',
Payload=json.dumps({
'pathParameters': {'productId': product_id}
})
)
response_payload = json.loads(invoke_response['Payload'].read())
if response_payload['statusCode'] != 200:
return {
'statusCode': 404,
'body': json.dumps({'error': 'Product not found'}),
'headers': {
'Content-Type': 'application/json'
}
}
product = json.loads(response_payload['body'])
# Simulate inventory check with random delay
time.sleep(random.uniform(0.2, 0.6))
if product.get('Stock', 0) < quantity:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Insufficient stock'}),
'headers': {
'Content-Type': 'application/json'
}
}
# Simulate order processing
time.sleep(random.uniform(0.3, 0.7))
# Occasionally simulate a slow operation
if random.random() > 0.8:
print("Slow operation triggered")
time.sleep(2.0)
order_id = f"ORD-{int(time.time())}"
return {
'statusCode': 200,
'body': json.dumps({
'orderId': order_id,
'productId': product_id,
'quantity': quantity,
'totalPrice': float(product.get('Price', 0)) * quantity,
'status': 'Processing'
}),
'headers': {
'Content-Type': 'application/json'
}
}
except Exception as e:
print(f"Error processing order: {str(e)}")
import traceback
traceback.print_exc()
return {
'statusCode': 500,
'body': json.dumps({'error': 'Order processing failed'}),
'headers': {
'Content-Type': 'application/json'
}
}
ProductServiceAPI
API for product catalog and order processing
products
{productId}
orders
prod
# Test retrieving a product
curl -X GET "${API_ENDPOINT}/products/PROD-001"
# Set your API endpoint
API_ENDPOINT=
# Test non-existent product
curl -X GET "${API_ENDPOINT}/products/PROD-999"
# Process an order
curl -X POST "${API_ENDPOINT}/orders" \
-H "Content-Type: application/json" \
-d '{
"productId": "PROD-001",
"quantity": 2
}'
# Test with invalid product
curl -X POST "${API_ENDPOINT}/orders" \
-H "Content-Type: application/json" \
-d '{
"productId": "INVALID-PRODUCT",
"quantity": 1
}'
# Generate 20 requests with varying patterns
for i in {1..20}; do
# Alternate between products
if [ $((i % 2)) -eq 0 ]; then
PRODUCT="PROD-001"
else
PRODUCT="PROD-002"
fi
# GET request
curl -s -X GET "${API_ENDPOINT}/products/${PRODUCT}" > /dev/null &
# POST request
curl -s -X POST "${API_ENDPOINT}/orders" \
-H "Content-Type: application/json" \
-d "{\"productId\": \"${PRODUCT}\", \"quantity\": $((RANDOM % 5 + 1))}" > /dev/null &
# Small delay between requests
sleep 0.5
done
echo "Traffic generation complete. Wait for all requests to finish..."
wait
echo "All requests completed."
Regular Text
Learn the fundamentals and find valuable information to get the most out of AWS.
Formatted Text
Code Text
cat > test_memorydb.py << EOF
import redis
import json
import sys
from datetime import datetime
# Check for command line argument
if len(sys.argv) != 2:
print("Usage: python3 test_memorydb.py <your-cluster-endpoint>")
print("Example: python3 test_memorydb.py memorydb-demo-cluster.abc123.memorydb.us-east-1.amazonaws.com")
sys.exit(1)
cluster_endpoint = sys.argv[1]
# Configure connection
try:
r = redis.Redis(
host=cluster_endpoint,
port=6379,
ssl=True,
decode_responses=True
)
# Test connection
r.ping()
print(f"✓ Successfully connected to MemoryDB cluster: {cluster_endpoint}")
except redis.ConnectionError as e:
print(f"✗ Failed to connect to {cluster_endpoint}")
print(f"Error: {e}")
print("\nPlease check:")
print(" - Cluster endpoint is correct")
print(" - Security group allows port 6379 from this instance")
print(" - Instance and cluster are in the same VPC")
sys.exit(1)
# Session management example
def create_session(user_id, username):
session_data = {
'user_id': user_id,
'username': username,
'login_time': datetime.now().isoformat()
}
# Store session with 30-minute expiration
r.setex(f'session:{user_id}', 1800, json.dumps(session_data))
print(f"✓ Session created for {username}")
def get_session(user_id):
session = r.get(f'session:{user_id}')
if session:
return json.loads(session)
return None
# Test the functions
print("\n--- Testing Session Management ---")
create_session('user001', 'alice')
session = get_session('user001')
print(f"✓ Retrieved session: {session}")
# Cache example with automatic expiration
print("\n--- Testing Cache with TTL ---")
r.setex('cache:api_response', 300, json.dumps({'data': 'cached response'}))
print(f"✓ Cache created with TTL: {r.ttl('cache:api_response')} seconds")
# Additional tests for data persistence
print("\n--- Testing Data Persistence ---")
r.set('persistent:data', 'This will survive a failover')
print(f"✓ Persistent data stored")
# Test various data structures
print("\n--- Testing Redis Data Structures ---")
# Hash
r.hset('user:1001', mapping={
'name': 'Alice',
'email': 'alice@example.com',
'lastLogin': datetime.now().isoformat()
})
print(f"✓ Hash created: {r.hgetall('user:1001')}")
# List
r.lpush('recent:logins', 'user001', 'user002', 'user003')
print(f"✓ List created: {r.lrange('recent:logins', 0, -1)}")
# Set
r.sadd('active:users', 'alice', 'bob', 'charlie')
print(f"✓ Set created with {r.scard('active:users')} members")
print("\n✓ All tests completed successfully!")
EOF