• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SwissDataScienceCenter / renku-data-services / 18840025735

27 Oct 2025 11:53AM UTC coverage: 86.84% (+0.03%) from 86.806%
18840025735

Pull #1083

github

web-flow
Merge 7a8145fff into 9cffdf9a6
Pull Request #1083: fix: do not pass awaitable in __get_gitlab_image_pull_secret

1 of 3 new or added lines in 1 file covered. (33.33%)

4 existing lines in 3 files now uncovered.

22727 of 26171 relevant lines covered (86.84%)

1.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.38
/components/renku_data_services/notebooks/util/retries.py
1
"""Methods for retrying requests."""
2

3
import asyncio
2✔
4
import functools
2✔
5
from collections.abc import Awaitable, Callable
2✔
6
from time import sleep
2✔
7
from typing import Concatenate, ParamSpec, TypeVar
2✔
8

9
from renku_data_services.notebooks.errors.intermittent import RetryTimeoutError
2✔
10

11
_RetType = TypeVar("_RetType")
2✔
12
_Params = ParamSpec("_Params")
2✔
13

14

15
def retry_with_exponential_backoff(
2✔
16
    should_retry: Callable[[_RetType], bool],
17
    num_retries: int = 10,
18
    initial_wait_ms: int = 20,
19
    multiplier: float = 2.0,
20
) -> Callable[[Callable[Concatenate[_Params], _RetType]], Callable[Concatenate[_Params], _RetType]]:
21
    """Retries the wrapped function with an exponential backoff.
22

23
    The should_retry "callback" is passed the results from calling the wrapped function.
24
    If the response is true, the function is called again, otherwise the loop ends and
25
    the result of the wrapped function is returned.
26

27
    With the default values the wait times start with 20ms and then double every iteration.
28
    """
29

30
    def decorator_retry(func: Callable[Concatenate[_Params], _RetType]) -> Callable[Concatenate[_Params], _RetType]:
×
31
        @functools.wraps(func)
×
32
        def wrapper_retry(*args: _Params.args, **kwargs: _Params.kwargs) -> _RetType:
×
33
            for i in range(num_retries):
×
34
                res = func(*args, **kwargs)
×
35
                if not should_retry(res):
×
36
                    return res
×
37
                sleep(initial_wait_ms * (multiplier**i) / 1000)
×
38
            raise RetryTimeoutError(f"Retrying the function {func.__name__} timed out after {num_retries} retries.")
×
39

40
        return wrapper_retry
×
41

42
    return decorator_retry
×
43

44

45
def retry_with_exponential_backoff_async(
2✔
46
    should_retry: Callable[[_RetType], bool],
47
    num_retries: int = 10,
48
    initial_wait_ms: int = 20,
49
    multiplier: float = 2.0,
50
) -> Callable[
51
    [Callable[Concatenate[_Params], Awaitable[_RetType]]], Callable[Concatenate[_Params], Awaitable[_RetType]]
52
]:
53
    """Retries the wrapped function with an exponential backoff.
54

55
    The should_retry "callback" is passed the results from calling the wrapped function.
56
    If the response is true, the function is called again, otherwise the loop ends and
57
    the result of the wrapped function is returned.
58

59
    With the default values the wait times start with 20ms and then double every iteration.
60
    """
61

62
    def decorator_retry(
1✔
63
        func: Callable[Concatenate[_Params], Awaitable[_RetType]],
64
    ) -> Callable[Concatenate[_Params], Awaitable[_RetType]]:
65
        @functools.wraps(func)
1✔
66
        async def wrapper_retry(*args: _Params.args, **kwargs: _Params.kwargs) -> _RetType:
1✔
67
            for i in range(num_retries):
1✔
68
                res = await func(*args, **kwargs)
1✔
69
                if not should_retry(res):
1✔
70
                    return res
1✔
71

UNCOV
72
                await asyncio.sleep(initial_wait_ms * (multiplier**i) / 1000)
×
73
            raise RetryTimeoutError(f"Retrying the function {func.__name__} timed out after {num_retries} retries.")
×
74

75
        return wrapper_retry
1✔
76

77
    return decorator_retry
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc