Skip to content

Commit f4ea4f8

Browse files
docs(idempotency): improve navigation, wording, and new section on guarantees (#4613)
* docs(idempotency): cleanup redis usage and link with setup/infra * docs(idempotency): cleanup idempotent decorator; inline admonitions Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): cleanup idempotent_decorator section Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): cleanup serialization, fields subset, move batch to new common use cases section Signed-off-by: heitorlessa <[email protected]> * docs: cleanup handling exceptions Signed-off-by: heitorlessa <[email protected]> * docs: move caching to getting started * docs: use env var for DDB table, no hardcode * docs: moved expiration window to getting started; updated example to set to 24h * docs: include IdempotencyValidationError in example * Fixing errors on Redis examples * docs(config): add social links * docs(idempotency): cleanup intro and key features * docs(idempotency): cleanup getting started ddb vs redis * docs(idempotency): break iam permissions into table; IAM permission to clipboard * docs(idempotency): cleanup dynamodb required resource; break subsections and update nav * docs(idempotency): make terminologies crispier Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): line editing before decorators Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): cleanup timeout section Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): use cards for required resources Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): note to skip timeout section when using handler decorator Signed-off-by: heitorlessa <[email protected]> * docs: remove tabbed content for single timeout snippet Signed-off-by: heitorlessa <[email protected]> * docs: cleanup persistence layers attrs, snippet titles etc Signed-off-by: heitorlessa <[email protected]> * docs: typo in batch integration Signed-off-by: heitorlessa <[email protected]> * docs: rename batch integration to actual use case name Signed-off-by: heitorlessa <[email protected]> * docs(idempotency): cleanup default behavior section Signed-off-by: heitorlessa <[email protected]> * docs: move bold to draw attention to whole event as idempotency key Signed-off-by: heitorlessa <[email protected]> * docs: lead with parameter name over config name * docs: moved composite key under DDB section * docs: cut unnecessary anchor name * docs: fix broken links after sections renaming * Making mypy happy * docs: fix conflicts out of order * docs(leandro's feedback): add caching in key features * Apply suggestions from code review Co-authored-by: Leandro Damascena <[email protected]> Signed-off-by: Heitor Lessa <[email protected]> * docs(leandro's feedback): time window placement * docs(leandro's feedback): key features success vs failure ambiguity * docs(leandro's feedback): Redis anchor name * docs(leandro's feedback): remove ambiguity on Redis VPC connectivity * Update docs/utilities/idempotency.md Co-authored-by: Leandro Damascena <[email protected]> Signed-off-by: Heitor Lessa <[email protected]> * Update docs/utilities/idempotency.md Co-authored-by: Leandro Damascena <[email protected]> Signed-off-by: Heitor Lessa <[email protected]> * docs: move primary key for both persistence storages plus additional ctx --------- Signed-off-by: heitorlessa <[email protected]> Signed-off-by: Heitor Lessa <[email protected]> Co-authored-by: Leandro Damascena <[email protected]>
1 parent 39c0314 commit f4ea4f8

33 files changed

+524
-444
lines changed

docs/utilities/idempotency.md

Lines changed: 330 additions & 339 deletions
Large diffs are not rendered by default.

examples/idempotency/src/customize_persistence_layer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import os
2+
13
from aws_lambda_powertools.utilities.idempotency import (
24
DynamoDBPersistenceLayer,
35
idempotent,
46
)
57
from aws_lambda_powertools.utilities.typing import LambdaContext
68

9+
table = os.getenv("IDEMPOTENCY_TABLE", "")
710
persistence_layer = DynamoDBPersistenceLayer(
8-
table_name="IdempotencyTable",
11+
table_name=table,
912
key_attr="idempotency_key",
1013
expiry_attr="expires_at",
1114
in_progress_expiry_attr="in_progress_expires_at",

examples/idempotency/src/customize_persistence_layer_redis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from aws_lambda_powertools.utilities.idempotency import (
24
idempotent,
35
)
@@ -6,8 +8,9 @@
68
)
79
from aws_lambda_powertools.utilities.typing import LambdaContext
810

11+
redis_endpoint = os.getenv("REDIS_CLUSTER_ENDPOINT", "localhost")
912
persistence_layer = RedisCachePersistenceLayer(
10-
host="localhost",
13+
host=redis_endpoint,
1114
port=6379,
1215
in_progress_expiry_attr="in_progress_expiration",
1316
status_attr="status",

examples/idempotency/src/getting_started_with_idempotency.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from dataclasses import dataclass, field
23
from uuid import uuid4
34

@@ -7,7 +8,8 @@
78
)
89
from aws_lambda_powertools.utilities.typing import LambdaContext
910

10-
persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
11+
table = os.getenv("IDEMPOTENCY_TABLE", "")
12+
persistence_layer = DynamoDBPersistenceLayer(table_name=table)
1113

1214

1315
@dataclass
@@ -17,8 +19,7 @@ class Payment:
1719
payment_id: str = field(default_factory=lambda: f"{uuid4()}")
1820

1921

20-
class PaymentError(Exception):
21-
...
22+
class PaymentError(Exception): ...
2223

2324

2425
@idempotent(persistence_store=persistence_layer)

examples/idempotency/src/getting_started_with_idempotency_redis_client.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from dataclasses import dataclass, field
23
from uuid import uuid4
34

@@ -11,8 +12,9 @@
1112
)
1213
from aws_lambda_powertools.utilities.typing import LambdaContext
1314

15+
redis_endpoint = os.getenv("REDIS_CLUSTER_ENDPOINT", "localhost")
1416
client = Redis(
15-
host="localhost",
17+
host=redis_endpoint,
1618
port=6379,
1719
socket_connect_timeout=5,
1820
socket_timeout=5,
@@ -29,8 +31,7 @@ class Payment:
2931
payment_id: str = field(default_factory=lambda: f"{uuid4()}")
3032

3133

32-
class PaymentError(Exception):
33-
...
34+
class PaymentError(Exception): ...
3435

3536

3637
@idempotent(persistence_store=persistence_layer)

examples/idempotency/src/getting_started_with_idempotency_redis_config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from dataclasses import dataclass, field
23
from uuid import uuid4
34

@@ -9,7 +10,8 @@
910
)
1011
from aws_lambda_powertools.utilities.typing import LambdaContext
1112

12-
persistence_layer = RedisCachePersistenceLayer(host="localhost", port=6379)
13+
redis_endpoint = os.getenv("REDIS_CLUSTER_ENDPOINT", "localhost")
14+
persistence_layer = RedisCachePersistenceLayer(host=redis_endpoint, port=6379)
1315

1416

1517
@dataclass
@@ -19,8 +21,7 @@ class Payment:
1921
payment_id: str = field(default_factory=lambda: f"{uuid4()}")
2022

2123

22-
class PaymentError(Exception):
23-
...
24+
class PaymentError(Exception): ...
2425

2526

2627
@idempotent(persistence_store=persistence_layer)
Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
from aws_lambda_powertools import Logger
2-
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType
1+
import os
2+
from typing import Any, Dict
3+
4+
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
35
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
46
from aws_lambda_powertools.utilities.idempotency import (
57
DynamoDBPersistenceLayer,
@@ -8,30 +10,24 @@
810
)
911
from aws_lambda_powertools.utilities.typing import LambdaContext
1012

11-
logger = Logger()
1213
processor = BatchProcessor(event_type=EventType.SQS)
1314

14-
dynamodb = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
15-
config = IdempotencyConfig(
16-
event_key_jmespath="messageId", # see Choosing a payload subset section
17-
)
15+
table = os.getenv("IDEMPOTENCY_TABLE", "")
16+
dynamodb = DynamoDBPersistenceLayer(table_name=table)
17+
config = IdempotencyConfig(event_key_jmespath="messageId")
1818

1919

2020
@idempotent_function(data_keyword_argument="record", config=config, persistence_store=dynamodb)
2121
def record_handler(record: SQSRecord):
2222
return {"message": record.body}
2323

2424

25-
def lambda_handler(event: SQSRecord, context: LambdaContext):
25+
def lambda_handler(event: Dict[str, Any], context: LambdaContext):
2626
config.register_lambda_context(context) # see Lambda timeouts section
2727

28-
# with Lambda context registered for Idempotency
29-
# we can now kick in the Bach processing logic
30-
batch = event["Records"]
31-
with processor(records=batch, handler=record_handler):
32-
# in case you want to access each record processed by your record_handler
33-
# otherwise ignore the result variable assignment
34-
processed_messages = processor.process()
35-
logger.info(processed_messages)
36-
37-
return processor.response()
28+
return process_partial_response(
29+
event=event,
30+
context=context,
31+
processor=processor,
32+
record_handler=record_handler,
33+
)

examples/idempotency/src/integrate_idempotency_with_validator.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from aws_lambda_powertools.utilities.idempotency import (
24
DynamoDBPersistenceLayer,
35
IdempotencyConfig,
@@ -6,8 +8,9 @@
68
from aws_lambda_powertools.utilities.typing import LambdaContext
79
from aws_lambda_powertools.utilities.validation import envelopes, validator
810

11+
table = os.getenv("IDEMPOTENCY_TABLE", "")
912
config = IdempotencyConfig(event_key_jmespath='["message", "username"]')
10-
persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
13+
persistence_layer = DynamoDBPersistenceLayer(table_name=table)
1114

1215

1316
@validator(envelope=envelopes.API_GATEWAY_HTTP)

examples/idempotency/src/using_redis_client_with_aws_secrets.py

Lines changed: 5 additions & 3 deletions
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,11 +10,11 @@
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(
14-
host=redis_values.get("REDIS_HOST"),
15-
port=redis_values.get("REDIS_PORT"),
16+
host=redis_values.get("REDIS_HOST", "localhost"),
17+
port=redis_values.get("REDIS_PORT", 6379),
1618
password=redis_values.get("REDIS_PASSWORD"),
1719
decode_responses=True,
1820
socket_timeout=10.0,

examples/idempotency/src/using_redis_client_with_local_certs.py

Lines changed: 5 additions & 3 deletions
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,12 +11,12 @@
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(
16-
host=redis_values.get("REDIS_HOST"),
17-
port=redis_values.get("REDIS_PORT"),
18+
host=redis_values.get("REDIS_HOST", "localhost"),
19+
port=redis_values.get("REDIS_PORT", 6379),
1820
password=redis_values.get("REDIS_PASSWORD"),
1921
decode_responses=True,
2022
socket_timeout=10.0,

0 commit comments

Comments
 (0)