Skip to content

Commit d4f6d42

Browse files
committed
rest: apply sane default timeout on requests
datadog API has a default timeout of 60s We observe regular error from lambda client using this lib where the connection is open without any timeout leading to write errors and connection interrupted by our servers. this patch aims to set a sane default for requests. Signed-off-by: William Dauchy <[email protected]>
1 parent 8fb4ffd commit d4f6d42

File tree

2 files changed

+31
-13
lines changed
  • .generator/src/generator/templates
  • src/datadog_api_client

2 files changed

+31
-13
lines changed

.generator/src/generator/templates/rest.j2

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ logger = logging.getLogger(__name__)
2323

2424
RETRY_AFTER_STATUS_CODES = frozenset([429, 500, 501, 502, 503, 504, 505, 506, 507, 509, 510, 511, 512])
2525
RETRY_ALLOWED_METHODS = frozenset(["GET", "PUT", "DELETE", "POST", "PATCH"])
26+
# apply sane default for calls to datadog API which has 60s timeout
27+
DEFAULT_TIMEOUT = 55
28+
DEFAULT_IDLE_CONN_MS = 55000
2629

2730

2831
class ClientRetry(urllib3.util.Retry):
@@ -138,7 +141,7 @@ class RESTClientObject:
138141
post_params = post_params or {}
139142
headers = headers or {}
140143

141-
timeout = None
144+
timeout = urllib3.Timeout(total=DEFAULT_TIMEOUT)
142145
if request_timeout:
143146
if isinstance(request_timeout, (int, float)):
144147
timeout = urllib3.Timeout(total=request_timeout)
@@ -238,7 +241,13 @@ class AsyncRESTClientObject:
238241
proxy = None
239242
if configuration.proxy:
240243
proxy = aiosonic.Proxy(configuration.proxy, configuration.proxy_headers)
241-
self._client = aiosonic.HTTPClient(proxy=proxy, verify_ssl=configuration.verify_ssl)
244+
pool_configs = {
245+
":default": aiosonic.PoolConfig(
246+
max_conn_idle_ms=DEFAULT_IDLE_CONN_MS
247+
)
248+
}
249+
connector = aiosonic.TCPConnector(pool_configs=pool_configs)
250+
self._client = aiosonic.HTTPClient(connector=connector, proxy=proxy, verify_ssl=configuration.verify_ssl)
242251
self._configuration = configuration
243252

244253
def close(self):
@@ -286,13 +295,13 @@ class AsyncRESTClientObject:
286295
(connection, read) timeouts.
287296
"""
288297
assert not post_params, "not supported for now"
298+
from aiosonic.timeout import Timeouts # type: ignore
299+
timeout = Timeouts(request_timeout=DEFAULT_TIMEOUT)
289300
if request_timeout is not None:
290-
from aiosonic.timeout import Timeouts # type: ignore
291-
292301
if isinstance(request_timeout, (int, float)):
293-
request_timeout = Timeouts(request_timeout=request_timeout)
302+
timeout = Timeouts(request_timeout=request_timeout)
294303
else:
295-
request_timeout = Timeouts(sock_connect=request_timeout[0], sock_read=request_timeout[1])
304+
timeout = Timeouts(sock_connect=request_timeout[0], sock_read=request_timeout[1])
296305
request_body = None
297306
if (
298307
"Content-Type" not in headers

src/datadog_api_client/rest.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626
RETRY_AFTER_STATUS_CODES = frozenset([429, 500, 501, 502, 503, 504, 505, 506, 507, 509, 510, 511, 512])
2727
RETRY_ALLOWED_METHODS = frozenset(["GET", "PUT", "DELETE", "POST", "PATCH"])
28+
# apply sane default for calls to datadog API which has 60s timeout
29+
DEFAULT_TIMEOUT = 55
30+
DEFAULT_IDLE_CONN_MS = 55000
2831

2932

3033
class ClientRetry(urllib3.util.Retry):
@@ -140,7 +143,7 @@ def request(
140143
post_params = post_params or {}
141144
headers = headers or {}
142145

143-
timeout = None
146+
timeout = urllib3.Timeout(total=DEFAULT_TIMEOUT)
144147
if request_timeout:
145148
if isinstance(request_timeout, (int, float)):
146149
timeout = urllib3.Timeout(total=request_timeout)
@@ -240,7 +243,13 @@ def __init__(self, configuration):
240243
proxy = None
241244
if configuration.proxy:
242245
proxy = aiosonic.Proxy(configuration.proxy, configuration.proxy_headers)
243-
self._client = aiosonic.HTTPClient(proxy=proxy, verify_ssl=configuration.verify_ssl)
246+
pool_configs = {
247+
":default": aiosonic.PoolConfig(
248+
max_conn_idle_ms=DEFAULT_IDLE_CONN_MS
249+
)
250+
}
251+
connector = aiosonic.TCPConnector(pool_configs=pool_configs)
252+
self._client = aiosonic.HTTPClient(connector=connector, proxy=proxy, verify_ssl=configuration.verify_ssl)
244253
self._configuration = configuration
245254

246255
def close(self):
@@ -290,13 +299,13 @@ async def request(
290299
(connection, read) timeouts.
291300
"""
292301
assert not post_params, "not supported for now"
302+
from aiosonic.timeout import Timeouts # type: ignore
303+
timeout = Timeouts(request_timeout=DEFAULT_TIMEOUT)
293304
if request_timeout is not None:
294-
from aiosonic.timeout import Timeouts # type: ignore
295-
296305
if isinstance(request_timeout, (int, float)):
297-
request_timeout = Timeouts(request_timeout=request_timeout)
306+
timeout = Timeouts(request_timeout=request_timeout)
298307
else:
299-
request_timeout = Timeouts(sock_connect=request_timeout[0], sock_read=request_timeout[1])
308+
timeout = Timeouts(sock_connect=request_timeout[0], sock_read=request_timeout[1])
300309
request_body = None
301310
if (
302311
"Content-Type" not in headers
@@ -317,7 +326,7 @@ async def request(
317326
counter = 0
318327
while True:
319328
response = await self._client.request(
320-
url, method, headers, query_params, request_body, timeouts=request_timeout
329+
url, method, headers, query_params, request_body, timeouts=timeout
321330
)
322331
retry = self._retry(method, response, counter)
323332
if not retry:

0 commit comments

Comments
 (0)