1313from apify_client ._consts import (
1414 DEFAULT_MAX_RETRIES ,
1515 DEFAULT_MIN_DELAY_BETWEEN_RETRIES ,
16- DEFAULT_REQUEST_TIMEOUT ,
17- DEFAULT_REQUEST_TIMEOUT_MAX ,
18- Timeout ,
16+ DEFAULT_TIMEOUT_LONG ,
17+ DEFAULT_TIMEOUT_MAX ,
18+ DEFAULT_TIMEOUT_MEDIUM ,
19+ DEFAULT_TIMEOUT_SHORT ,
1920)
2021from apify_client ._docs import docs_group
2122from apify_client ._statistics import ClientStatistics
23+ from apify_client ._utils import to_seconds
2224
2325if TYPE_CHECKING :
2426 from collections .abc import AsyncIterator , Iterator , Mapping
2527
26- from apify_client ._consts import JsonSerializable , Timeout
28+ from apify_client ._types import JsonSerializable , Timeout
2729
2830
2931@docs_group ('HTTP clients' )
@@ -90,8 +92,10 @@ def __init__(
9092 self ,
9193 * ,
9294 token : str | None = None ,
93- timeout : timedelta = DEFAULT_REQUEST_TIMEOUT ,
94- timeout_max : timedelta = DEFAULT_REQUEST_TIMEOUT_MAX ,
95+ timeout_short : timedelta = DEFAULT_TIMEOUT_SHORT ,
96+ timeout_medium : timedelta = DEFAULT_TIMEOUT_MEDIUM ,
97+ timeout_long : timedelta = DEFAULT_TIMEOUT_LONG ,
98+ timeout_max : timedelta = DEFAULT_TIMEOUT_MAX ,
9599 max_retries : int = DEFAULT_MAX_RETRIES ,
96100 min_delay_between_retries : timedelta = DEFAULT_MIN_DELAY_BETWEEN_RETRIES ,
97101 statistics : ClientStatistics | None = None ,
@@ -101,14 +105,18 @@ def __init__(
101105
102106 Args:
103107 token: Apify API token for authentication.
104- timeout: Initial request timeout.
108+ timeout_short: Timeout for fast CRUD operations (e.g., get, update, delete).
109+ timeout_medium: Timeout for batch, list, and data transfer operations.
110+ timeout_long: Timeout for long-polling, streaming, and other heavy operations.
105111 timeout_max: Maximum timeout cap for exponential timeout growth across retries.
106112 max_retries: Maximum number of retries for failed requests.
107113 min_delay_between_retries: Minimum delay between retries.
108114 statistics: Statistics tracker for API calls. Created automatically if not provided.
109115 headers: Additional HTTP headers to include in all requests.
110116 """
111- self ._timeout = timeout
117+ self ._timeout_short = timeout_short
118+ self ._timeout_medium = timeout_medium
119+ self ._timeout_long = timeout_long
112120 self ._timeout_max = timeout_max
113121 self ._max_retries = max_retries
114122 self ._min_delay_between_retries = min_delay_between_retries
@@ -157,6 +165,34 @@ def _parse_params(params: dict[str, Any] | None) -> dict[str, Any] | None:
157165
158166 return parsed_params
159167
168+ def _compute_timeout (self , timeout : Timeout , attempt : int ) -> int | float | None :
169+ """Resolve a timeout tier and compute the timeout for a request attempt with exponential increase.
170+
171+ For `'no_timeout'`, returns `None`. For tier literals and explicit `timedelta` values, doubles the timeout
172+ with each attempt but caps at `timeout_max`.
173+
174+ Args:
175+ timeout: The timeout specification to resolve (tier literal or explicit `timedelta`).
176+ attempt: Current attempt number (1-indexed).
177+
178+ Returns:
179+ Timeout in seconds, or `None` for `'no_timeout'`.
180+ """
181+ if timeout == 'no_timeout' :
182+ return None
183+
184+ if timeout == 'short' :
185+ resolved = self ._timeout_short
186+ elif timeout == 'medium' :
187+ resolved = self ._timeout_medium
188+ elif timeout == 'long' :
189+ resolved = self ._timeout_long
190+ else :
191+ resolved = timeout
192+
193+ new_timeout = min (resolved * (2 ** (attempt - 1 )), self ._timeout_max )
194+ return to_seconds (new_timeout )
195+
160196 def _prepare_request_call (
161197 self ,
162198 headers : dict [str , str ] | None = None ,
@@ -221,7 +257,7 @@ def call(
221257 data : str | bytes | bytearray | None = None ,
222258 json : Any = None ,
223259 stream : bool | None = None ,
224- timeout : Timeout = None ,
260+ timeout : Timeout = 'medium' ,
225261 ) -> HttpResponse :
226262 """Make an HTTP request.
227263
@@ -233,8 +269,9 @@ def call(
233269 data: Raw request body data. Cannot be used together with json.
234270 json: JSON-serializable data for the request body. Cannot be used together with data.
235271 stream: Whether to stream the response body.
236- timeout: Timeout for the API HTTP request. `None` uses the timeout configured on the client,
237- a `timedelta` overrides it for this call, and `'no_timeout'` disables the timeout entirely.
272+ timeout: Timeout for the API HTTP request. Use `short`, `medium`, or `long` tier literals for
273+ preconfigured timeouts. A `timedelta` overrides it for this call, and `no_timeout` disables
274+ the timeout entirely.
238275
239276 Returns:
240277 The HTTP response object.
@@ -264,7 +301,7 @@ async def call(
264301 data : str | bytes | bytearray | None = None ,
265302 json : Any = None ,
266303 stream : bool | None = None ,
267- timeout : Timeout = None ,
304+ timeout : Timeout = 'medium' ,
268305 ) -> HttpResponse :
269306 """Make an HTTP request.
270307
@@ -276,8 +313,9 @@ async def call(
276313 data: Raw request body data. Cannot be used together with json.
277314 json: JSON-serializable data for the request body. Cannot be used together with data.
278315 stream: Whether to stream the response body.
279- timeout: Timeout for the API HTTP request. `None` uses the timeout configured on the client,
280- a `timedelta` overrides it for this call, and `'no_timeout'` disables the timeout entirely.
316+ timeout: Timeout for the API HTTP request. Use `short`, `medium`, or `long` tier literals for
317+ preconfigured timeouts. A `timedelta` overrides it for this call, and `no_timeout` disables
318+ the timeout entirely.
281319
282320 Returns:
283321 The HTTP response object.
0 commit comments