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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
import time
import logging
from mwclient.errors import MaximumRetriesExceeded
log = logging.getLogger(__name__)
class Sleepers(object):
"""
A class that allows for the creation of multiple `Sleeper` objects with shared
arguments.
Examples:
Firstly a `Sleepers` object containing the shared attributes has to be created.
>>> max_retries, retry_timeout = 5, 5
>>> sleepers = Sleepers(max_retries, retry_timeout)
From this `Sleepers` object multiple individual `Sleeper` objects can be created
using the `make` method.
>>> sleeper = sleepers.make()
Args:
max_retries (int): The maximum number of retries to perform.
retry_timeout (int): The time to sleep for each past retry.
callback (Callable[[int, Any], None]): A callable to be called on each retry.
Attributes:
max_retries (int): The maximum number of retries to perform.
retry_timeout (int): The time to sleep for each past retry.
callback (callable): A callable to be called on each retry.
"""
def __init__(self, max_retries, retry_timeout, callback=lambda *x: None):
self.max_retries = max_retries
self.retry_timeout = retry_timeout
self.callback = callback
def make(self, args=None):
"""
Creates a new `Sleeper` object.
Args:
args (Any): Arguments to be passed to the `callback` callable.
Returns:
Sleeper: A `Sleeper` object.
"""
return Sleeper(args, self.max_retries, self.retry_timeout, self.callback)
class Sleeper(object):
"""
For any given operation, a `Sleeper` object keeps count of the number of retries.
For each retry, the sleep time increases until the max number of retries is reached
and a `MaximumRetriesExceeded` is raised. The sleeper object should be discarded
once the operation is successful.
Args:
args (Any): Arguments to be passed to the `callback` callable.
max_retries (int): The maximum number of retries to perform.
retry_timeout (int): The time to sleep for each past retry.
callback (callable, None]): A callable to be called on each retry.
Attributes:
args (Any): Arguments to be passed to the `callback` callable.
retries (int): The number of retries that have been performed.
max_retries (int): The maximum number of retries to perform.
retry_timeout (int): The time to sleep for each past retry.
callback (callable): A callable to be called on each retry.
"""
def __init__(self, args, max_retries, retry_timeout, callback):
self.args = args
self.retries = 0
self.max_retries = max_retries
self.retry_timeout = retry_timeout
self.callback = callback
def sleep(self, min_time=0):
"""
Sleeps for a minimum of `min_time` seconds. The actual sleeping time will increase
with the number of retries.
Args:
min_time (int): The minimum sleeping time.
Raises:
MaximumRetriesExceeded: If the number of retries exceeds the maximum.
"""
self.retries += 1
if self.retries > self.max_retries:
raise MaximumRetriesExceeded(self, self.args)
self.callback(self, self.retries, self.args)
timeout = self.retry_timeout * (self.retries - 1)
if timeout < min_time:
timeout = min_time
log.debug('Sleeping for %d seconds', timeout)
time.sleep(timeout)
|