Skip to content

Commit 9dfbc06

Browse files
committed
docs(idempotency): cleanup redis usage and link with setup/infra
1 parent 6152b6d commit 9dfbc06

File tree

5 files changed

+109
-116
lines changed

5 files changed

+109
-116
lines changed

docs/utilities/idempotency.md

Lines changed: 83 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Unless you're looking to use an [existing table or customize each attribute](#dy
8787

8888
Note that `fn_qualified_name` means the [qualified name for classes and functions](https://peps.python.org/pep-3155/){target="_blank" rel="nofollow"} defined in PEP-3155.
8989

90-
##### IaC examples
90+
##### DynamoDB IaC examples
9191

9292
=== "AWS Serverless Application Model (SAM) example"
9393

@@ -116,11 +116,24 @@ Note that `fn_qualified_name` means the [qualified name for classes and function
116116

117117
#### Redis cluster
118118

119-
**TODO**: Experiment bringing upfront Redis even at the cost of readability, as setup and usage are disconnected today causing further harm.
119+
We recommend you start with a Redis compatible management services such as [Amazon ElastiCache for Redis](https://aws.amazon.com/elasticache/redis/){target="_blank"} or [Amazon MemoryDB for Redis](https://aws.amazon.com/memorydb/){target="_blank"}.
120120

121-
##### Constraints
121+
In both services and self-hosting Redis, you'll need to configure [VPC access](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html){target="_blank"} to your AWS Lambda.
122122

123-
If you'd like to use Redis, please [read here](#redis-as-persistent-storage-layer-provider) on how to setup and access secrets/SSL certs.
123+
!!! tip "First time setting it all up? Checkout the official tutorials for [Amazon ElastiCache for Redis](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/LambdaRedis.html) or [Amazon MemoryDB for Redis](https://aws.amazon.com/blogs/database/access-amazon-memorydb-for-redis-from-aws-lambda/)"
124+
125+
##### Redis IaC examples
126+
127+
=== "AWS CloudFormation example"
128+
129+
```yaml hl_lines="5 21"
130+
--8<-- "examples/idempotency/templates/cfn_redis_serverless.yaml"
131+
```
132+
133+
1. Replace the Security Group ID and Subnet ID to match your VPC settings.
134+
2. Replace the Security Group ID and Subnet ID to match your VPC settings.
135+
136+
Once setup, you can find quick start and advanced examples for Redis in [the persistent layers section](RedisCachePersistenceLayer).
124137

125138
<!-- markdownlint-enable MD013 -->
126139
### Idempotent decorator
@@ -364,6 +377,8 @@ This persistence layer is built-in, allowing you to use an existing DynamoDB tab
364377
--8<-- "examples/idempotency/src/customize_persistence_layer.py"
365378
```
366379

380+
##### DynamoDB defaults
381+
367382
When using DynamoDB as the persistence layer, you can customize the attribute names by passing the following parameters during the initialization of the persistence layer:
368383

369384
| Parameter | Required | Default | Description |
@@ -380,15 +395,68 @@ When using DynamoDB as the persistence layer, you can customize the attribute na
380395

381396
#### RedisPersistenceLayer
382397

383-
This persistence layer is built-in, allowing you to use an existing Redis service. For optimal performance and compatibility, it is strongly recommended to use a Redis service version 7 or higher.
398+
!!! info "We recommend Redis version 7 or higher for optimal performance."
384399

385-
=== "Customizing RedisPersistenceLayer to suit your data structure"
400+
For a quick start, initialize `RedisCachePersistenceLayer` and pass your cluster host endpoint along with the port to connect to.
386401

387-
```python hl_lines="9-16"
388-
--8<-- "examples/idempotency/src/customize_persistence_layer_redis.py"
402+
For security, we enforce SSL connections by default; to disable it, set `ssl=False`.
403+
404+
=== "Redis quick start"
405+
```python hl_lines="7-9 12 26"
406+
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_config.py"
407+
```
408+
409+
=== "Using an existing Redis client"
410+
```python hl_lines="4 9-11 14 22 36"
411+
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_client.py"
412+
```
413+
414+
=== "Sample event"
415+
416+
```json
417+
--8<-- "examples/idempotency/src/getting_started_with_idempotency_payload.json"
418+
```
419+
420+
##### Redis SSL connections
421+
422+
We recommend using AWS Secrets Manager to store and rotate certificates safely, and the [Parameters feature](./parameters.md){target="_blank"} to fetch and cache optimally.
423+
424+
For advanced configurations, we also recommend using an existing Redis client for optimal compatibility like SSL certificates and timeout.
425+
426+
=== "Advanced configuration using AWS Secrets"
427+
```python hl_lines="9-11 13 15 25"
428+
--8<-- "examples/idempotency/src/using_redis_client_with_aws_secrets.py"
389429
```
390430

391-
When using Redis as the persistence layer, you can customize the attribute names by providing the following parameters upon initialization of the persistence layer:
431+
1. JSON stored:
432+
```json
433+
{
434+
"REDIS_ENDPOINT": "127.0.0.1",
435+
"REDIS_PORT": "6379",
436+
"REDIS_PASSWORD": "redis-secret"
437+
}
438+
```
439+
440+
=== "Advanced configuration with local certificates"
441+
```python hl_lines="14 25-27"
442+
--8<-- "examples/idempotency/src/using_redis_client_with_local_certs.py"
443+
```
444+
445+
1. JSON stored:
446+
```json
447+
{
448+
"REDIS_ENDPOINT": "127.0.0.1",
449+
"REDIS_PORT": "6379",
450+
"REDIS_PASSWORD": "redis-secret"
451+
}
452+
```
453+
2. redis_user.crt file stored in the "certs" directory of your Lambda function
454+
3. redis_user_private.key file stored in the "certs" directory of your Lambda function
455+
4. redis_ca.pem file stored in the "certs" directory of your Lambda function
456+
457+
##### Redis defaults
458+
459+
You can customize attribute names when instantiating `RedisCachePersistenceLayer` with the following parameters:
392460

393461
| Parameter | Required | Default | Description |
394462
| --------------------------- | -------- | ------------------------ | --------------------------------------------------------------------------------------------- |
@@ -397,6 +465,12 @@ When using Redis as the persistence layer, you can customize the attribute names
397465
| **data_attr** | | `data` | Stores results of successfully executed Lambda handlers |
398466
| **validation_key_attr** | | `validation` | Hashed representation of the parts of the event used for validation |
399467

468+
=== "Customizing RedisPersistenceLayer to suit your data structure"
469+
470+
```python hl_lines="9-16"
471+
--8<-- "examples/idempotency/src/customize_persistence_layer_redis.py"
472+
```
473+
400474
### Idempotency request flow
401475

402476
The following sequence diagrams explain how the Idempotency feature behaves under different scenarios.
@@ -649,95 +723,6 @@ graph TD;
649723
<i>Race condition with Redis</i>
650724
</center>
651725

652-
## Redis as persistent storage layer provider
653-
654-
### Redis resources
655-
656-
Before setting up Redis as the persistent storage layer provider, you must have an existing Redis service. We recommend you to use Redis compatible services such as [Amazon ElastiCache for Redis](https://aws.amazon.com/elasticache/redis/){target="_blank"} or [Amazon MemoryDB for Redis](https://aws.amazon.com/memorydb/){target="_blank"} as your persistent storage layer provider.
657-
658-
???+ tip "No existing Redis service?"
659-
If you don't have an existing Redis service, we recommend using [DynamoDB](#dynamodbpersistencelayer) as the persistent storage layer provider.
660-
661-
=== "AWS CloudFormation example"
662-
663-
```yaml hl_lines="5"
664-
--8<-- "examples/idempotency/templates/cfn_redis_serverless.yaml"
665-
```
666-
667-
1. Replace the Security Group ID and Subnet ID to match your VPC settings.
668-
669-
### VPC Access
670-
671-
Your Lambda Function must have network access to the Redis endpoint before using it as the idempotency persistent storage layer. In most cases, you will need to [configure VPC access](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html){target="_blank"} for your Lambda Function.
672-
673-
???+ tip "Amazon ElastiCache/MemoryDB for Redis as persistent storage layer provider"
674-
If you plan to use Amazon ElastiCache for Redis as the idempotency persistent storage layer, you may find [this AWS tutorial](https://docs.aws.amazon.com/lambda/latest/dg/services-elasticache-tutorial.html){target="_blank"} helpful.
675-
For those using Amazon MemoryDB for Redis, refer to [this AWS tutorial](https://aws.amazon.com/blogs/database/access-amazon-memorydb-for-redis-from-aws-lambda/){target="_blank"} specifically for the VPC setup guidance.
676-
677-
After completing the VPC setup, you can use the templates provided below to set up Lambda functions with access to VPC internal subnets.
678-
679-
=== "AWS Serverless Application Model (SAM) example"
680-
681-
```yaml hl_lines="9"
682-
--8<-- "examples/idempotency/templates/sam_redis_vpc.yaml"
683-
```
684-
685-
1. Replace the Security Group ID and Subnet ID to match your VPC settings.
686-
687-
### Configuring Redis persistence layer
688-
689-
You can quickly get started by initializing the `RedisCachePersistenceLayer` class and applying the `idempotent` decorator to your Lambda handler. For a detailed example of using the `RedisCachePersistenceLayer`, refer to the [Persistence layers section](#redispersistencelayer).
690-
691-
???+ info
692-
We enforce security best practices by using SSL connections in the `RedisCachePersistenceLayer`; to disable it, set `ssl=False`
693-
694-
=== "Use Persistence Layer with Redis config variables"
695-
```python hl_lines="7-9 12 26"
696-
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_config.py"
697-
```
698-
699-
=== "Use established Redis Client"
700-
```python hl_lines="4 9-11 14 22 36"
701-
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_client.py"
702-
```
703-
704-
=== "Sample event"
705-
706-
```json
707-
--8<-- "examples/idempotency/src/getting_started_with_idempotency_payload.json"
708-
```
709-
710-
### Custom advanced settings
711-
712-
For advanced configurations, such as setting up SSL certificates or customizing parameters like a custom timeout, you can utilize the Redis client to tailor these specific settings to your needs.
713-
714-
=== "Advanced configuration using AWS Secrets"
715-
```python hl_lines="7-9 11 13 23"
716-
--8<-- "examples/idempotency/src/using_redis_client_with_aws_secrets.py"
717-
```
718-
719-
1. JSON stored:
720-
{
721-
"REDIS_ENDPOINT": "127.0.0.1",
722-
"REDIS_PORT": "6379",
723-
"REDIS_PASSWORD": "redis-secret"
724-
}
725-
726-
=== "Advanced configuration with local certificates"
727-
```python hl_lines="12 23-25"
728-
--8<-- "examples/idempotency/src/using_redis_client_with_local_certs.py"
729-
```
730-
731-
1. JSON stored:
732-
{
733-
"REDIS_ENDPOINT": "127.0.0.1",
734-
"REDIS_PORT": "6379",
735-
"REDIS_PASSWORD": "redis-secret"
736-
}
737-
2. redis_user.crt file stored in the "certs" directory of your Lambda function
738-
3. redis_user_private.key file stored in the "certs" directory of your Lambda function
739-
4. redis_ca.pem file stored in the "certs" directory of your Lambda function
740-
741726
## Advanced
742727

743728
### Customizing the default behavior

examples/idempotency/src/using_redis_client_with_aws_secrets.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from typing import Any
24

35
from redis import Redis
@@ -8,7 +10,7 @@
810
RedisCachePersistenceLayer,
911
)
1012

11-
redis_values: Any = parameters.get_secret("redis_info", transform="json") # (1)!
13+
redis_values: dict[str, Any] = parameters.get_secret("redis_info", transform="json") # (1)!
1214

1315
redis_client = Redis(
1416
host=redis_values.get("REDIS_HOST"),

examples/idempotency/src/using_redis_client_with_local_certs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from typing import Any
24

35
from redis import Redis
@@ -9,7 +11,7 @@
911
RedisCachePersistenceLayer,
1012
)
1113

12-
redis_values: Any = parameters.get_secret("redis_info", transform="json") # (1)!
14+
redis_values: dict[str, Any] = parameters.get_secret("redis_info", transform="json") # (1)!
1315

1416

1517
redis_client = Redis(
Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
AWSTemplateFormatVersion: '2010-09-09'
1+
AWSTemplateFormatVersion: "2010-09-09"
2+
Transform: AWS::Serverless-2016-10-31
23

34
Resources:
45
RedisServerlessIdempotency:
@@ -7,7 +8,24 @@ Resources:
78
Engine: redis
89
ServerlessCacheName: redis-cache
910
SecurityGroupIds: # (1)!
10-
- security-{your_sg_id}
11+
- security-{your_sg_id}
1112
SubnetIds:
13+
- subnet-{your_subnet_id_1}
14+
- subnet-{your_subnet_id_2}
15+
16+
HelloWorldFunction:
17+
Type: AWS::Serverless::Function
18+
Properties:
19+
Runtime: python3.12
20+
Handler: app.py
21+
VpcConfig: # (1)!
22+
SecurityGroupIds:
23+
- security-{your_sg_id}
24+
SubnetIds:
1225
- subnet-{your_subnet_id_1}
1326
- subnet-{your_subnet_id_2}
27+
Environment:
28+
Variables:
29+
POWERTOOLS_SERVICE_NAME: sample
30+
REDIS_HOST: !GetAtt RedisServerlessIdempotency.Endpoint.Address
31+
REDIS_PORT: !GetAtt RedisServerlessIdempotency.Endpoint.Port

examples/idempotency/templates/sam_redis_vpc.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)