Skip to content

Commit a6f9db1

Browse files
author
Alex Wang
committed
test(examples): add wait and handler error test examples
- Add testing examples - wait for condition - handler error - Update web runner, return error response so that we can test on funciton exception
1 parent 74a4bf2 commit a6f9db1

File tree

7 files changed

+77
-31
lines changed

7 files changed

+77
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dist/
2929
.kiro/
3030
.idea
3131
.env
32+
.env*
3233

3334
.durable_executions
3435

examples/examples-catalog.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,17 @@
297297
"ExecutionTimeout": 300
298298
},
299299
"path": "./src/parallel/parallel_with_batch_serdes.py"
300+
},
301+
{
302+
"name": "Handler Error",
303+
"description": "Simple function with handler error",
304+
"handler": "handler_error.handler",
305+
"integration": true,
306+
"durableConfig": {
307+
"RetentionPeriodInDays": 7,
308+
"ExecutionTimeout": 300
309+
},
310+
"path": "./src/handler_error/handler_error.py"
300311
}
301312
]
302313
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Demonstrates how handler-level errors are captured and structured in results."""
2+
3+
from typing import Any
4+
5+
from aws_durable_execution_sdk_python.context import DurableContext
6+
from aws_durable_execution_sdk_python.execution import durable_execution
7+
8+
9+
def generate_large_string(size_in_kb: int) -> str:
10+
"""Generate a string of approximately the specified size in KB."""
11+
base_string = "B" * 1024 # 1KB string
12+
return base_string * size_in_kb
13+
14+
15+
@durable_execution
16+
def handler(_event: Any, _context: DurableContext) -> None:
17+
"""Handler demonstrating handler-level error capture."""
18+
# Simulate a handler-level error that might occur in real applications
19+
raise Exception("Intentional handler failure")

examples/src/wait_for_condition/wait_for_condition.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,25 @@
44

55
from aws_durable_execution_sdk_python.context import DurableContext
66
from aws_durable_execution_sdk_python.execution import durable_execution
7+
from aws_durable_execution_sdk_python.waits import WaitForConditionConfig, WaitForConditionDecision
78

89

910
@durable_execution
1011
def handler(_event: Any, context: DurableContext) -> int:
1112
"""Handler demonstrating wait-for-condition pattern."""
12-
state = 0
13-
attempt = 0
14-
max_attempts = 5
1513

16-
while attempt < max_attempts:
17-
attempt += 1
14+
def condition_function(state: int, _) -> int:
15+
"""Increment state by 1."""
16+
return state + 1
1817

19-
# Execute step to update state
20-
state = context.step(
21-
lambda _, s=state: s + 1,
22-
name=f"increment_state_{attempt}",
23-
)
24-
25-
# Check condition
18+
def wait_strategy(state: int, attempt: int) -> dict[str, Any]:
19+
"""Wait strategy that continues until state reaches 3."""
2620
if state >= 3:
27-
# Condition met, stop
28-
break
21+
return WaitForConditionDecision.stop_polling()
22+
return WaitForConditionDecision.continue_waiting(1)
23+
24+
config = WaitForConditionConfig(wait_strategy=wait_strategy, initial_state=0)
2925

30-
# Wait before next attempt
31-
context.wait(seconds=1)
26+
result = context.wait_for_condition(check=condition_function, config=config)
3227

33-
return state
28+
return result
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Tests for handler_error."""
2+
3+
import pytest
4+
from aws_durable_execution_sdk_python.execution import InvocationStatus
5+
6+
from src.handler_error import handler_error
7+
8+
9+
@pytest.mark.example
10+
@pytest.mark.durable_execution(
11+
handler=handler_error.handler,
12+
lambda_function_name="handler error",
13+
)
14+
def test_handle_handler_errors_gracefully_and_capture_error_details(durable_runner):
15+
"""Test that handler errors are handled gracefully and error details are captured."""
16+
test_payload = {"test": "error-case"}
17+
18+
with durable_runner:
19+
result = durable_runner.run(input=test_payload, timeout=10)
20+
21+
# Verify execution failed
22+
assert result.status is InvocationStatus.FAILED
23+
24+
# Check that error was captured in the result
25+
error = result.error
26+
assert error is not None
27+
28+
assert error.message == "Intentional handler failure"
29+
assert error.type == "Exception"
30+
31+
# Verify no operations were completed due to early error
32+
assert len(result.operations) == 0

examples/test/wait_for_condition/test_wait_for_condition.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import pytest
44
from aws_durable_execution_sdk_python.execution import InvocationStatus
5-
from aws_durable_execution_sdk_python.lambda_service import OperationType
65

76
from src.wait_for_condition import wait_for_condition
87
from test.conftest import deserialize_operation_payload
@@ -21,13 +20,3 @@ def test_wait_for_condition(durable_runner):
2120
assert result.status is InvocationStatus.SUCCEEDED
2221
# Should reach state 3 after 3 increments
2322
assert deserialize_operation_payload(result.result) == 3
24-
25-
# Verify step operations exist (should have 3 increment steps)
26-
step_ops = [
27-
op for op in result.operations if op.operation_type == OperationType.STEP
28-
]
29-
assert len(step_ops) == 3
30-
31-
# Verify wait operations exist (should have 2 waits before final state)
32-
wait_ops = [op for op in result.operations if op.operation_type.value == "WAIT"]
33-
assert len(wait_ops) == 2

src/aws_durable_execution_sdk_python_testing/runner.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -787,11 +787,10 @@ def run(
787787
msg = f"Lambda invocation failed with status {status_code}: {error_payload}"
788788
raise DurableFunctionsTestError(msg)
789789

790-
# Check for function errors
790+
# Check for function errors, we want to return function error for testing purpose
791791
if "FunctionError" in response:
792792
error_payload = response["Payload"].read().decode("utf-8")
793-
msg = f"Lambda function failed: {error_payload}"
794-
raise DurableFunctionsTestError(msg)
793+
logger.warning("Lambda function failed: %s", error_payload)
795794

796795
result_payload = response["Payload"].read().decode("utf-8")
797796
logger.info(

0 commit comments

Comments
 (0)