Skip to content

Commit e06460e

Browse files
refactor: check if the input is a durable input
1 parent 58423ec commit e06460e

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

src/aws_durable_execution_sdk_python/execution.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,18 @@ def wrapper(event: Any, context: LambdaContext) -> MutableMapping[str, Any]:
217217
invocation_input = event
218218
service_client = invocation_input.service_client
219219
else:
220-
logger.debug("durableExecutionArn: %s", event.get("DurableExecutionArn"))
221-
invocation_input = DurableExecutionInvocationInput.from_dict(event)
220+
try:
221+
logger.debug(
222+
"durableExecutionArn: %s", event.get("DurableExecutionArn")
223+
)
224+
invocation_input = DurableExecutionInvocationInput.from_dict(event)
225+
except (KeyError, TypeError, AttributeError) as e:
226+
msg = (
227+
"The function is not being invoked as a durable function. "
228+
"Please check the function configuration to ensure durability is turned on, "
229+
"or use the testing SDK for local testing."
230+
)
231+
raise ValueError(msg) from e
222232

223233
# Local runner always uses its own client, otherwise use custom or default
224234
if invocation_input.is_local_runner:

tests/execution_test.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,3 +2012,59 @@ def test_handler(event: Any, context: DurableContext) -> dict:
20122012
# THEN the execution succeeds using the custom client
20132013
assert result["Status"] == InvocationStatus.SUCCEEDED.value
20142014
assert result["Result"] == '{"result": "success"}'
2015+
2016+
2017+
def test_durable_execution_with_non_durable_payload_raises_error():
2018+
"""Test that invoking a durable function with a regular event raises a helpful error."""
2019+
2020+
# GIVEN a durable function
2021+
@durable_execution
2022+
def test_handler(event: Any, context: DurableContext) -> dict:
2023+
return {"result": "success"}
2024+
2025+
# GIVEN a regular Lambda event (not a durable execution payload)
2026+
regular_event = {"key": "value", "data": "test"}
2027+
2028+
lambda_context = Mock()
2029+
lambda_context.aws_request_id = "test-request"
2030+
lambda_context.client_context = None
2031+
lambda_context.identity = None
2032+
lambda_context._epoch_deadline_time_in_ms = 1000000 # noqa: SLF001
2033+
lambda_context.invoked_function_arn = None
2034+
lambda_context.tenant_id = None
2035+
2036+
# WHEN the handler is invoked with a non-durable payload
2037+
# THEN it raises a ValueError with a helpful message
2038+
with pytest.raises(
2039+
ValueError,
2040+
match="The function is not being invoked as a durable function",
2041+
):
2042+
test_handler(regular_event, lambda_context)
2043+
2044+
2045+
def test_durable_execution_with_non_dict_event_raises_error():
2046+
"""Test that invoking a durable function with a non-dict event raises a helpful error."""
2047+
2048+
# GIVEN a durable function
2049+
@durable_execution
2050+
def test_handler(event: Any, context: DurableContext) -> dict:
2051+
return {"result": "success"}
2052+
2053+
# GIVEN a non-dict event
2054+
non_dict_event = "not a dict"
2055+
2056+
lambda_context = Mock()
2057+
lambda_context.aws_request_id = "test-request"
2058+
lambda_context.client_context = None
2059+
lambda_context.identity = None
2060+
lambda_context._epoch_deadline_time_in_ms = 1000000 # noqa: SLF001
2061+
lambda_context.invoked_function_arn = None
2062+
lambda_context.tenant_id = None
2063+
2064+
# WHEN the handler is invoked with a non-dict event
2065+
# THEN it raises a ValueError with a helpful message
2066+
with pytest.raises(
2067+
ValueError,
2068+
match="The function is not being invoked as a durable function",
2069+
):
2070+
test_handler(non_dict_event, lambda_context)

0 commit comments

Comments
 (0)