From 6ff7729af4f0c472645c6bc37754f9097372138c Mon Sep 17 00:00:00 2001 From: Will Mizzi Date: Fri, 17 Apr 2026 14:46:14 +1000 Subject: [PATCH] fix: extend Lambda read_timeout, disable retries - Introduce a shared Lambda client config with a 960s read_timeout and retries disabled - Route all Lambda client construction through a single helper --- .../invoker.py | 36 ++++++++++++++----- .../runner.py | 5 ++- tests/invoker_test.py | 3 ++ tests/runner_web_test.py | 4 +++ 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/aws_durable_execution_sdk_python_testing/invoker.py b/src/aws_durable_execution_sdk_python_testing/invoker.py index 42c283d..26143c9 100644 --- a/src/aws_durable_execution_sdk_python_testing/invoker.py +++ b/src/aws_durable_execution_sdk_python_testing/invoker.py @@ -7,6 +7,8 @@ from uuid import uuid4 import boto3 # type: ignore +from botocore.config import Config # type: ignore + from aws_durable_execution_sdk_python.execution import ( DurableExecutionInvocationInput, DurableExecutionInvocationInputWithClient, @@ -29,6 +31,26 @@ from aws_durable_execution_sdk_python_testing.execution import Execution +# Max Lambda function timeout is 15 minutes (900s); we give headroom for +# network round-trip and RIE startup. +_LAMBDA_READ_TIMEOUT_SECONDS = 960 +_LAMBDA_CLIENT_CONFIG = Config( + read_timeout=_LAMBDA_READ_TIMEOUT_SECONDS, + retries={"max_attempts": 0}, +) + + +def create_lambda_client(endpoint_url: str | None, region_name: str) -> Any: + """Create a boto3 Lambda client configured for durable function invocations.""" + + return boto3.client( + "lambda", + endpoint_url=endpoint_url, + region_name=region_name, + config=_LAMBDA_CLIENT_CONFIG, + ) + + @dataclass(frozen=True) class InvokeResponse: """Response from invoking a durable function.""" @@ -136,9 +158,7 @@ def __init__(self, lambda_client: Any) -> None: @staticmethod def create(endpoint_url: str, region_name: str) -> LambdaInvoker: """Create with the boto lambda client.""" - invoker = LambdaInvoker( - boto3.client("lambda", endpoint_url=endpoint_url, region_name=region_name) - ) + invoker = LambdaInvoker(create_lambda_client(endpoint_url, region_name)) invoker._current_endpoint = endpoint_url invoker._endpoint_clients[endpoint_url] = invoker.lambda_client return invoker @@ -148,8 +168,8 @@ def update_endpoint(self, endpoint_url: str, region_name: str) -> None: # Cache client by endpoint to reuse across executions with self._lock: if endpoint_url not in self._endpoint_clients: - self._endpoint_clients[endpoint_url] = boto3.client( - "lambda", endpoint_url=endpoint_url, region_name=region_name + self._endpoint_clients[endpoint_url] = create_lambda_client( + endpoint_url, region_name ) self.lambda_client = self._endpoint_clients[endpoint_url] self._current_endpoint = endpoint_url @@ -164,10 +184,8 @@ def _get_client_for_execution( # Use provided endpoint or fall back to cached endpoint for this execution if lambda_endpoint: if lambda_endpoint not in self._endpoint_clients: - self._endpoint_clients[lambda_endpoint] = boto3.client( - "lambda", - endpoint_url=lambda_endpoint, - region_name=region_name or "us-east-1", + self._endpoint_clients[lambda_endpoint] = create_lambda_client( + lambda_endpoint, region_name or "us-east-1" ) return self._endpoint_clients[lambda_endpoint] diff --git a/src/aws_durable_execution_sdk_python_testing/runner.py b/src/aws_durable_execution_sdk_python_testing/runner.py index 34e80f4..d60e774 100644 --- a/src/aws_durable_execution_sdk_python_testing/runner.py +++ b/src/aws_durable_execution_sdk_python_testing/runner.py @@ -46,6 +46,7 @@ from aws_durable_execution_sdk_python_testing.invoker import ( InProcessInvoker, LambdaInvoker, + create_lambda_client, ) from aws_durable_execution_sdk_python_testing.model import ( GetDurableExecutionHistoryResponse, @@ -858,9 +859,7 @@ def _create_boto3_client(self) -> Any: Exception: If client creation fails - exceptions propagate naturally for CLI to handle as general Exception """ - # Create client with Lambda endpoint configuration - return boto3.client( - "lambda", + return create_lambda_client( endpoint_url=self._config.lambda_endpoint, region_name=self._config.local_runner_region, ) diff --git a/tests/invoker_test.py b/tests/invoker_test.py index 10b1f7d..7e60c9a 100644 --- a/tests/invoker_test.py +++ b/tests/invoker_test.py @@ -25,6 +25,8 @@ from aws_durable_execution_sdk_python_testing.invoker import ( InProcessInvoker, LambdaInvoker, + _LAMBDA_CLIENT_CONFIG, + create_lambda_client, create_test_lambda_context, ) from aws_durable_execution_sdk_python_testing.model import ( @@ -133,6 +135,7 @@ def test_lambda_invoker_create(): "lambda", endpoint_url="http://localhost:3001", region_name="us-west-2", + config=_LAMBDA_CLIENT_CONFIG, ) diff --git a/tests/runner_web_test.py b/tests/runner_web_test.py index 01c5f1d..f810bf3 100644 --- a/tests/runner_web_test.py +++ b/tests/runner_web_test.py @@ -12,6 +12,7 @@ from aws_durable_execution_sdk_python_testing.exceptions import ( DurableFunctionsLocalRunnerError, ) +from aws_durable_execution_sdk_python_testing.invoker import _LAMBDA_CLIENT_CONFIG from aws_durable_execution_sdk_python_testing.runner import ( WebRunner, WebRunnerConfig, @@ -420,6 +421,7 @@ def test_should_handle_boto3_client_creation_with_custom_config(): "lambda", endpoint_url="http://custom-endpoint:8080", region_name="eu-west-1", + config=_LAMBDA_CLIENT_CONFIG, ) # Verify public behavior works @@ -445,6 +447,7 @@ def test_should_handle_boto3_client_creation_with_defaults(): "lambda", endpoint_url="http://127.0.0.1:3001", # Default lambda_endpoint value region_name="us-west-2", # Default value + config=_LAMBDA_CLIENT_CONFIG, ) # Verify public behavior works @@ -768,6 +771,7 @@ def test_should_pass_correct_boto3_client_to_lambda_invoker(): "lambda", endpoint_url="http://test-endpoint:7777", region_name="ap-southeast-2", + config=_LAMBDA_CLIENT_CONFIG, ) # Verify LambdaInvoker was created with the client