Skip to content

Commit e719a9d

Browse files
committed
fix(testing): floor callback timer scaling
1 parent de86a53 commit e719a9d

3 files changed

Lines changed: 36 additions & 10 deletions

File tree

packages/aws-durable-execution-sdk-python-testing/src/aws_durable_execution_sdk_python_testing/executor.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272

7373
logger = logging.getLogger(__name__)
7474

75+
_CALLBACK_TIMEOUT_MINIMUM_DELAY_SECONDS = 5.0
76+
7577

7678
class Executor(ExecutionObserver):
7779
MAX_CONSECUTIVE_FAILED_ATTEMPTS: int = 5
@@ -1094,7 +1096,10 @@ def _schedule_callback_timeouts(
10941096

10951097
# Schedule main timeout if configured
10961098
if callback_options.timeout_seconds > 0:
1097-
timeout_delay = scale_delay(callback_options.timeout_seconds)
1099+
timeout_delay = scale_delay(
1100+
callback_options.timeout_seconds,
1101+
minimum=_CALLBACK_TIMEOUT_MINIMUM_DELAY_SECONDS,
1102+
)
10981103

10991104
def timeout_handler():
11001105
self._on_callback_timeout(execution_arn, callback_id)
@@ -1109,7 +1114,8 @@ def timeout_handler():
11091114
# Schedule heartbeat timeout if configured
11101115
if callback_options.heartbeat_timeout_seconds > 0:
11111116
heartbeat_delay = scale_delay(
1112-
callback_options.heartbeat_timeout_seconds
1117+
callback_options.heartbeat_timeout_seconds,
1118+
minimum=_CALLBACK_TIMEOUT_MINIMUM_DELAY_SECONDS,
11131119
)
11141120

11151121
def heartbeat_timeout_handler():
@@ -1154,7 +1160,8 @@ def _reset_callback_heartbeat_timeout(
11541160

11551161
if callback_options and callback_options.heartbeat_timeout_seconds > 0:
11561162
heartbeat_delay = scale_delay(
1157-
callback_options.heartbeat_timeout_seconds
1163+
callback_options.heartbeat_timeout_seconds,
1164+
minimum=_CALLBACK_TIMEOUT_MINIMUM_DELAY_SECONDS,
11581165
)
11591166

11601167
def heartbeat_timeout_handler():

packages/aws-durable-execution-sdk-python-testing/src/aws_durable_execution_sdk_python_testing/time_scale.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ def get_time_scale() -> float:
2727
return scale
2828

2929

30-
def scale_delay(delay: float | int) -> float:
30+
def scale_delay(delay: float | int, *, minimum: float = 0) -> float:
3131
"""Scale a durable timer delay for local testing."""
32-
return float(delay) * get_time_scale()
32+
scaled_delay = float(delay) * get_time_scale()
33+
if minimum <= 0:
34+
return scaled_delay
35+
36+
return max(scaled_delay, min(float(delay), minimum))

packages/aws-durable-execution-sdk-python-testing/tests/executor_test.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,16 +2579,31 @@ def test_callback_timeout_scheduling(executor, mock_store, mock_scheduler):
25792579
def test_callback_timeout_scheduling_scales_delays(
25802580
executor, mock_store, mock_scheduler, monkeypatch
25812581
):
2582-
"""Test that callback timeout timers honor local time scaling."""
2582+
"""Test that callback timeout timers honor local time scaling with a floor."""
25832583
monkeypatch.setenv("DURABLE_EXECUTION_TIME_SCALE", "0.05")
25842584
callback_options = CallbackOptions(timeout_seconds=60, heartbeat_timeout_seconds=30)
25852585
executor._completion_events["test-arn"] = Mock()
25862586

25872587
executor._schedule_callback_timeouts("test-arn", callback_options, "callback-id")
25882588

25892589
timeout_call, heartbeat_call = mock_scheduler.call_later.call_args_list
2590-
assert timeout_call.kwargs["delay"] == 3.0
2591-
assert heartbeat_call.kwargs["delay"] == 1.5
2590+
assert timeout_call.kwargs["delay"] == 5.0
2591+
assert heartbeat_call.kwargs["delay"] == 5.0
2592+
2593+
2594+
def test_callback_timeout_scheduling_keeps_short_delays(
2595+
executor, mock_store, mock_scheduler, monkeypatch
2596+
):
2597+
"""Test that short callback timeout timers are not inflated by the floor."""
2598+
monkeypatch.setenv("DURABLE_EXECUTION_TIME_SCALE", "0.05")
2599+
callback_options = CallbackOptions(timeout_seconds=1, heartbeat_timeout_seconds=2)
2600+
executor._completion_events["test-arn"] = Mock()
2601+
2602+
executor._schedule_callback_timeouts("test-arn", callback_options, "callback-id")
2603+
2604+
timeout_call, heartbeat_call = mock_scheduler.call_later.call_args_list
2605+
assert timeout_call.kwargs["delay"] == 1.0
2606+
assert heartbeat_call.kwargs["delay"] == 2.0
25922607

25932608

25942609
def test_callback_timeout_cleanup(executor, mock_store):
@@ -2646,7 +2661,7 @@ def test_callback_heartbeat_timeout_reset(executor, mock_store, mock_scheduler):
26462661
def test_callback_heartbeat_timeout_reset_scales_delay(
26472662
executor, mock_store, mock_scheduler, monkeypatch
26482663
):
2649-
"""Test that reset heartbeat timers honor local time scaling."""
2664+
"""Test that reset heartbeat timers honor local time scaling with a floor."""
26502665
monkeypatch.setenv("DURABLE_EXECUTION_TIME_SCALE", "0.05")
26512666
callback_token = CallbackToken(execution_arn="test-arn", operation_id="op-123")
26522667
callback_id = callback_token.to_str()
@@ -2665,7 +2680,7 @@ def test_callback_heartbeat_timeout_reset_scales_delay(
26652680
executor._reset_callback_heartbeat_timeout(callback_id, "test-arn")
26662681

26672682
mock_scheduler.call_later.assert_called_once()
2668-
assert mock_scheduler.call_later.call_args.kwargs["delay"] == 1.5
2683+
assert mock_scheduler.call_later.call_args.kwargs["delay"] == 5.0
26692684

26702685

26712686
def test_callback_timeout_handlers(executor, mock_store):

0 commit comments

Comments
 (0)