Skip to content

fix(idempotency): POWERTOOLS_IDEMPOTENCY_DISABLED should respect truthy values #4391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
9 changes: 7 additions & 2 deletions aws_lambda_powertools/utilities/idempotency/idempotency.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
from aws_lambda_powertools.shared import constants
from aws_lambda_powertools.shared.functions import strtobool
from aws_lambda_powertools.shared.types import AnyCallableT
from aws_lambda_powertools.utilities.idempotency.base import IdempotencyHandler
from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig
Expand Down Expand Up @@ -66,7 +67,9 @@ def idempotent(
>>> return {"StatusCode": 200}
"""

if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV):
# Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True
# If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default
if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")):
return handler(event, context, **kwargs)

config = config or IdempotencyConfig()
Expand Down Expand Up @@ -150,7 +153,9 @@ def process_order(customer_id: str, order: dict, **kwargs):

@functools.wraps(function)
def decorate(*args, **kwargs):
if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV):
# Check if the IDEMPOTENCY_DISABLED_ENV environment variable is set to True
# If IDEMPOTENCY_DISABLED_ENV is not set or set to any false value, the function will be idempotent by default
if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "0")):
return function(*args, **kwargs)

if data_keyword_argument not in kwargs:
Expand Down
38 changes: 36 additions & 2 deletions tests/functional/idempotency/test_idempotency.py
Original file line number Diff line number Diff line change
Expand Up @@ -1667,13 +1667,19 @@ def dummy(payload):
dummy(payload=data_two)


def test_idempotency_disabled_envvar(monkeypatch, lambda_context, persistence_store: DynamoDBPersistenceLayer):
@pytest.mark.parametrize("idempotency_disabled_value", ["1", "y", "yes", "t", "true", "on"])
def test_idempotency_enabled_envvar(
monkeypatch,
lambda_context,
persistence_store: DynamoDBPersistenceLayer,
idempotency_disabled_value,
):
# Scenario to validate no requests sent to dynamodb table when 'POWERTOOLS_IDEMPOTENCY_DISABLED' is set
mock_event = {"data": "value"}

persistence_store.client = MagicMock()

monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", "1")
monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value))

@idempotent_function(data_keyword_argument="data", persistence_store=persistence_store)
def dummy(data):
Expand All @@ -1689,6 +1695,34 @@ def dummy_handler(event, context):
assert len(persistence_store.client.method_calls) == 0


@pytest.mark.parametrize("idempotency_disabled_value", ["0", "n", "no", "f", "false", "off"])
def test_idempotency_disabled_envvar(
monkeypatch,
lambda_context,
persistence_store: DynamoDBPersistenceLayer,
idempotency_disabled_value,
):
# Scenario to validate no requests sent to dynamodb table when 'POWERTOOLS_IDEMPOTENCY_DISABLED' is false
mock_event = {"data": "value"}

persistence_store.client = MagicMock()

monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", str(idempotency_disabled_value))

@idempotent_function(data_keyword_argument="data", persistence_store=persistence_store)
def dummy(data):
return {"message": "hello"}

@idempotent(persistence_store=persistence_store)
def dummy_handler(event, context):
return {"message": "hi"}

dummy(data=mock_event)
dummy_handler(mock_event, lambda_context)

assert len(persistence_store.client.method_calls) == 4


@pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True)
def test_idempotent_function_duplicates(
idempotency_config: IdempotencyConfig,
Expand Down