diff --git a/packages/aws-durable-execution-sdk-python-insight/README.md b/packages/aws-durable-execution-sdk-python-insight/README.md index 2260a0176..920e36a62 100644 --- a/packages/aws-durable-execution-sdk-python-insight/README.md +++ b/packages/aws-durable-execution-sdk-python-insight/README.md @@ -183,7 +183,12 @@ OTelExporter(endpoint="https://otlp.vendor.com/v1/logs", headers={"x-api-key": " `POST` (or `method="PUT"`) the record as JSON to `url` with `Content-Type: application/json` plus `headers`; a non-2xx status raises. -`timeout_ms` defaults to 10000. No IAM. +`timeout_ms` defaults to 10000 and currently applies to each socket operation +(the connect, each write of the request, and each read of the status line, +headers, and a non-2xx error body; a 2xx body is never read) rather than to the +whole request, so an endpoint that consumes or responds slowly can hold the +export open longer than `timeout_ms`; a future release may enforce it as a +whole-request deadline. No IAM. ```python HttpExporter(url="https://hooks.example.com/insight", headers={"Authorization": "Bearer ..."}) diff --git a/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/_common.py b/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/_common.py index 28ef36262..36d347e97 100644 --- a/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/_common.py +++ b/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/_common.py @@ -89,7 +89,11 @@ def http_send( message. Redirects are not followed: a 3xx is returned like any other failure. ``error_text`` is the first ``_MAX_ERROR_BODY_BYTES`` of a non-2xx response body and empty on success; a success body is never read. Network - errors and timeouts propagate. + errors and timeouts propagate. ``timeout`` is ``urllib``'s per-socket- + operation timeout: it bounds the connect, each write of the request, and + each read of the status line, headers, and any error body separately, not + the request as a whole. A peer that keeps consuming or sending bytes + slowly can outlive it. """ request = urllib.request.Request(url, data=body, method=method) for key, value in headers.items(): diff --git a/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/http_exporter.py b/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/http_exporter.py index fec782811..540715b4c 100644 --- a/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/http_exporter.py +++ b/packages/aws-durable-execution-sdk-python-insight/src/aws_durable_execution_sdk_python_insight/exporters/http_exporter.py @@ -34,8 +34,17 @@ class HttpExporter: """Sends each record as a JSON body to any HTTP endpoint. The endpoint must answer 2xx; any other status raises. ``timeout_ms`` - bounds the whole request (default 10 seconds). ``max_record_size_bytes`` - has no default because a generic endpoint has no known limit. + (default 10 seconds) is currently applied to each blocking socket + operation, not to the request as a whole: the connect, each write while + sending the request (headers and the record body), and each read of the + status line and headers, plus of the error body on a non-2xx response. A + successful response body is never read. An endpoint that stops reading or + goes silent fails at ``timeout_ms``, but one that keeps consuming or + sending bytes slowly can hold the request open for longer. A future + release may enforce ``timeout_ms`` as a deadline for the whole request, so + do not rely on a request being allowed to exceed it. Size the function + timeout with this in mind. ``max_record_size_bytes`` has no default because + a generic endpoint has no known limit. """ def __init__( diff --git a/packages/aws-durable-execution-sdk-python-insight/tests/test_http_exporter.py b/packages/aws-durable-execution-sdk-python-insight/tests/test_http_exporter.py index 6fd64d6b0..d2f66176b 100644 --- a/packages/aws-durable-execution-sdk-python-insight/tests/test_http_exporter.py +++ b/packages/aws-durable-execution-sdk-python-insight/tests/test_http_exporter.py @@ -181,7 +181,7 @@ def test_non_2xx_response_raises(http_capture: HttpCapture) -> None: exporter.export(_record()) -def test_timeout_is_enforced(http_capture: HttpCapture) -> None: +def test_timeout_applies_to_a_silent_peer(http_capture: HttpCapture) -> None: http_capture.delay_seconds = 1.0 exporter = HttpExporter(url=http_capture.url, timeout_ms=100) with pytest.raises(TimeoutError):