Skip to content

Commit 2c26f84

Browse files
authored
fix(idempotency): idempotent_function should support standalone falsy values (#1669)
1 parent baf50f9 commit 2c26f84

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

Diff for: aws_lambda_powertools/utilities/idempotency/idempotency.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,14 @@ def decorate(*args, **kwargs):
134134
if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV):
135135
return function(*args, **kwargs)
136136

137-
payload = kwargs.get(data_keyword_argument)
138-
139-
if not payload:
137+
if data_keyword_argument not in kwargs:
140138
raise RuntimeError(
141139
f"Unable to extract '{data_keyword_argument}' from keyword arguments."
142140
f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument"
143141
)
144142

143+
payload = kwargs.get(data_keyword_argument)
144+
145145
idempotency_handler = IdempotencyHandler(
146146
function=function,
147147
function_payload=payload,

Diff for: tests/functional/idempotency/test_idempotency.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_idempotent_lambda_already_completed(
7272
lambda_context,
7373
):
7474
"""
75-
Test idempotent decorator where event with matching event key has already been succesfully processed
75+
Test idempotent decorator where event with matching event key has already been successfully processed
7676
"""
7777

7878
stubber = stub.Stubber(persistence_store.table.meta.client)
@@ -1247,6 +1247,46 @@ def lambda_handler(event, _):
12471247
assert handler_result == expected_result
12481248

12491249

1250+
@pytest.mark.parametrize("data", [None, 0, False])
1251+
def test_idempotent_function_falsy_values(data):
1252+
# Scenario to validate we can use idempotent_function with any function
1253+
# receiving a falsy value (`None`, `False`, `0`, etc.)
1254+
# shouldn't cause a RuntimeError
1255+
mock_event = data
1256+
idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_falsy_values.<locals>.record_handler#{hash_idempotency_key(mock_event)}" # noqa: E501
1257+
1258+
persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key)
1259+
expected_result = {"message": "Foo"}
1260+
1261+
@idempotent_function(persistence_store=persistence_layer, data_keyword_argument="record")
1262+
def record_handler(record):
1263+
return expected_result
1264+
1265+
# WHEN calling the function
1266+
result = record_handler(record=mock_event)
1267+
# THEN we expect the function to execute successfully
1268+
assert result == expected_result
1269+
1270+
1271+
@pytest.mark.parametrize("data", [None, 0, False])
1272+
def test_idempotent_function_falsy_values_with_raise_on_no_idempotency_key(
1273+
data, persistence_store: DynamoDBPersistenceLayer
1274+
):
1275+
# GIVEN raise_on_no_idempotency_key is True
1276+
idempotency_config = IdempotencyConfig(event_key_jmespath="idemKey", raise_on_no_idempotency_key=True)
1277+
1278+
@idempotent_function(data_keyword_argument="record", persistence_store=persistence_store, config=idempotency_config)
1279+
def record_handler(record):
1280+
return ValueError("Should not be raised")
1281+
1282+
# WHEN calling the function
1283+
with pytest.raises(IdempotencyKeyError) as e:
1284+
record_handler(record=data)
1285+
1286+
# THEN we expect an idempotency key error message
1287+
assert "No data found to create a hashed idempotency_key" == e.value.args[0]
1288+
1289+
12501290
def test_idempotent_data_sorting():
12511291
# Scenario to validate same data in different order hashes to the same idempotency key
12521292
data_one = {"data": "test message 1", "more_data": "more data 1"}

0 commit comments

Comments
 (0)