Skip to content

Commit b482152

Browse files
author
Michael Brewer
committed
fix: Reanable test
1 parent dfb5b0f commit b482152

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

aws_lambda_powertools/utilities/idempotency/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
from aws_lambda_powertools.utilities.idempotency.persistence.base import BasePersistenceLayer
66
from aws_lambda_powertools.utilities.idempotency.persistence.dynamodb import DynamoDBPersistenceLayer
77

8-
from .idempotency import idempotent
8+
from .idempotency import IdempotencyConfig, idempotent
99

10-
__all__ = ("DynamoDBPersistenceLayer", "BasePersistenceLayer", "idempotent")
10+
__all__ = ("DynamoDBPersistenceLayer", "BasePersistenceLayer", "idempotent", "IdempotencyConfig")

aws_lambda_powertools/utilities/idempotency/persistence/base.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
import warnings
1010
from abc import ABC, abstractmethod
1111
from types import MappingProxyType
12-
from typing import Any, Dict
12+
from typing import Any, Dict, Optional
1313

1414
import jmespath
1515

1616
from aws_lambda_powertools.shared.cache_dict import LRUDict
1717
from aws_lambda_powertools.shared.json_encoder import Encoder
18+
from aws_lambda_powertools.utilities.idempotency.config import IdempotencyConfig
1819
from aws_lambda_powertools.utilities.idempotency.exceptions import (
1920
IdempotencyInvalidStatusError,
2021
IdempotencyItemAlreadyExistsError,
2122
IdempotencyKeyError,
2223
IdempotencyValidationError,
2324
)
24-
from aws_lambda_powertools.utilities.idempotency.idempotency import IdempotencyConfig
2525

2626
logger = logging.getLogger(__name__)
2727

@@ -108,14 +108,16 @@ class BasePersistenceLayer(ABC):
108108
"""
109109

110110
def __init__(self):
111-
self.event_key_jmespath = None
111+
self.configured = False
112+
113+
self.event_key_jmespath: Optional[str] = None
112114
self.event_key_compiled_jmespath = None
113-
self.payload_validation_enabled = None
115+
self.payload_validation_enabled = False
114116
self.validation_key_jmespath = None
115-
self.raise_on_no_idempotency_key = None
117+
self.raise_on_no_idempotency_key = False
116118
self.expires_after_seconds = None
117-
self.use_local_cache = None
118-
self._cache = None
119+
self.use_local_cache = False
120+
self._cache: Optional[LRUDict] = None
119121
self.hash_function = None
120122

121123
def configure(self, config: IdempotencyConfig,) -> None:
@@ -127,10 +129,13 @@ def configure(self, config: IdempotencyConfig,) -> None:
127129
config: IdempotencyConfig
128130
Configuration settings
129131
"""
132+
if self.configured:
133+
# Temp hack to prevent being reconfigured.
134+
return
135+
self.configured = True
130136
self.event_key_jmespath = config.event_key_jmespath
131-
if self.event_key_jmespath:
137+
if config.event_key_jmespath:
132138
self.event_key_compiled_jmespath = jmespath.compile(config.event_key_jmespath)
133-
self.payload_validation_enabled = False
134139
if config.payload_validation_jmespath:
135140
self.validation_key_jmespath = jmespath.compile(config.payload_validation_jmespath)
136141
self.payload_validation_enabled = True

tests/functional/idempotency/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def hashed_validation_key(lambda_apigw_event):
152152

153153
@pytest.fixture
154154
def persistence_store(config):
155-
return DynamoDBPersistenceLayer(table_name=TABLE_NAME, boto_config=config,)
155+
return DynamoDBPersistenceLayer(table_name=TABLE_NAME, boto_config=config)
156156

157157

158158
@pytest.fixture

tests/functional/idempotency/test_idempotency.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,53 @@ def lambda_handler(event, context):
207207
stubber.deactivate()
208208

209209

210+
@pytest.mark.skipif(sys.version_info < (3, 8), reason="issue with pytest mock lib for < 3.8")
211+
@pytest.mark.parametrize("idempotency_config", [{"use_local_cache": True}], indirect=True)
212+
def test_idempotent_lambda_first_execution_cached(
213+
idempotency_config,
214+
persistence_store,
215+
lambda_apigw_event,
216+
expected_params_update_item,
217+
expected_params_put_item,
218+
lambda_response,
219+
hashed_idempotency_key,
220+
mocker,
221+
):
222+
"""
223+
Test idempotent decorator when lambda is executed with an event with a previously unknown event key. Ensure
224+
result is cached locally on the persistence store instance.
225+
"""
226+
persistence_store.configure(idempotency_config)
227+
save_to_cache_spy = mocker.spy(persistence_store, "_save_to_cache")
228+
retrieve_from_cache_spy = mocker.spy(persistence_store, "_retrieve_from_cache")
229+
stubber = stub.Stubber(persistence_store.table.meta.client)
230+
ddb_response = {}
231+
232+
stubber.add_response("put_item", ddb_response, expected_params_put_item)
233+
stubber.add_response("update_item", ddb_response, expected_params_update_item)
234+
stubber.activate()
235+
236+
@idempotent(persistence_store=persistence_store, config=idempotency_config)
237+
def lambda_handler(event, context):
238+
return lambda_response
239+
240+
lambda_handler(lambda_apigw_event, {})
241+
242+
retrieve_from_cache_spy.assert_called_once()
243+
save_to_cache_spy.assert_called_once()
244+
assert save_to_cache_spy.call_args[0][0].status == "COMPLETED"
245+
assert persistence_store._cache.get(hashed_idempotency_key).status == "COMPLETED"
246+
247+
# This lambda call should not call AWS API
248+
lambda_handler(lambda_apigw_event, {})
249+
assert retrieve_from_cache_spy.call_count == 3
250+
retrieve_from_cache_spy.assert_called_with(idempotency_key=hashed_idempotency_key)
251+
252+
# This assertion fails if an AWS API operation was called more than once
253+
stubber.assert_no_pending_responses()
254+
stubber.deactivate()
255+
256+
210257
@pytest.mark.parametrize("idempotency_config", [{"use_local_cache": False}, {"use_local_cache": True}], indirect=True)
211258
def test_idempotent_lambda_expired(
212259
idempotency_config,

0 commit comments

Comments
 (0)