-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy path_utils.py
More file actions
49 lines (33 loc) · 1.69 KB
/
_utils.py
File metadata and controls
49 lines (33 loc) · 1.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from __future__ import annotations
import asyncio
from typing import TYPE_CHECKING, TypeVar
from crawlee._utils.crypto import crypto_random_object_id
from apify import Actor
if TYPE_CHECKING:
from collections.abc import Awaitable, Callable
T = TypeVar('T')
async def call_with_exp_backoff(fn: Callable[[], Awaitable[T]], *, max_retries: int = 3) -> T | None:
"""Call an async callable with exponential backoff retries until it returns a truthy value.
In shared request queue mode, there is a propagation delay before newly added, reclaimed, or handled requests
become visible in the API (see https://github.com/apify/apify-sdk-python/issues/808). This helper retries with
exponential backoff to handle that delay in integration tests.
"""
result = None
for attempt in range(max_retries):
result = await fn()
if result:
return result
delay = 2**attempt
Actor.log.info(f'{fn} returned {result!r}, retrying in {delay}s (attempt {attempt + 1}/{max_retries})')
await asyncio.sleep(delay)
return result
def generate_unique_resource_name(label: str) -> str:
"""Generates a unique resource name, which will contain the given label."""
name_template = 'python-sdk-tests-{}-generated-{}'
template_length = len(name_template.format('', ''))
api_name_limit = 63
generated_random_id_length = 8
label_length_limit = api_name_limit - template_length - generated_random_id_length
label = label.replace('_', '-')
assert len(label) <= label_length_limit, f'Max label length is {label_length_limit}, but got {len(label)}'
return name_template.format(label, crypto_random_object_id(generated_random_id_length))