0
# Retry Logic
1
2
Configurable retry mechanisms with exponential backoff, custom predicates, and support for both synchronous and asynchronous operations including streaming. The retry system provides robust error recovery for transient failures in API communication.
3
4
## Capabilities
5
6
### Unary Retry Classes
7
8
Retry decorators for single request-response operations with exponential backoff and configurable retry conditions.
9
10
```python { .api }
11
class Retry:
12
"""
13
Retry decorator for synchronous unary operations.
14
15
Args:
16
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
17
initial (float): Initial delay between retries in seconds (default: 1.0)
18
maximum (float): Maximum delay between retries in seconds (default: 60.0)
19
multiplier (float): Multiplier for exponential backoff (default: 2.0)
20
deadline (float): Total time limit for all retry attempts in seconds (default: 120.0)
21
on_error (Callable[[Exception], None]): Optional callback for each retry attempt
22
"""
23
def __init__(self, predicate=None, initial=1.0, maximum=60.0, multiplier=2.0, deadline=120.0, on_error=None): ...
24
25
def __call__(self, func): ...
26
def with_deadline(self, deadline): ...
27
def with_delay(self, initial=None, maximum=None, multiplier=None): ...
28
def with_predicate(self, predicate): ...
29
30
class AsyncRetry:
31
"""
32
Retry decorator for asynchronous unary operations.
33
34
Args:
35
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
36
initial (float): Initial delay between retries in seconds (default: 1.0)
37
maximum (float): Maximum delay between retries in seconds (default: 60.0)
38
multiplier (float): Multiplier for exponential backoff (default: 2.0)
39
deadline (float): Total time limit for all retry attempts in seconds (default: 120.0)
40
on_error (Callable[[Exception], None]): Optional callback for each retry attempt
41
"""
42
def __init__(self, predicate=None, initial=1.0, maximum=60.0, multiplier=2.0, deadline=120.0, on_error=None): ...
43
44
def __call__(self, func): ...
45
def with_deadline(self, deadline): ...
46
def with_delay(self, initial=None, maximum=None, multiplier=None): ...
47
def with_predicate(self, predicate): ...
48
```
49
50
### Streaming Retry Classes
51
52
Retry decorators for streaming operations that can handle connection interruptions and resume streaming.
53
54
```python { .api }
55
class StreamingRetry:
56
"""
57
Retry decorator for synchronous streaming operations.
58
59
Args:
60
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
61
initial (float): Initial delay between retries in seconds (default: 1.0)
62
maximum (float): Maximum delay between retries in seconds (default: 60.0)
63
multiplier (float): Multiplier for exponential backoff (default: 2.0)
64
deadline (float): Total time limit for all retry attempts in seconds (default: 120.0)
65
on_error (Callable[[Exception], None]): Optional callback for each retry attempt
66
"""
67
def __init__(self, predicate=None, initial=1.0, maximum=60.0, multiplier=2.0, deadline=120.0, on_error=None): ...
68
69
def __call__(self, func): ...
70
def with_deadline(self, deadline): ...
71
def with_delay(self, initial=None, maximum=None, multiplier=None): ...
72
def with_predicate(self, predicate): ...
73
74
class AsyncStreamingRetry:
75
"""
76
Retry decorator for asynchronous streaming operations.
77
78
Args:
79
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
80
initial (float): Initial delay between retries in seconds (default: 1.0)
81
maximum (float): Maximum delay between retries in seconds (default: 60.0)
82
multiplier (float): Multiplier for exponential backoff (default: 2.0)
83
deadline (float): Total time limit for all retry attempts in seconds (default: 120.0)
84
on_error (Callable[[Exception], None]): Optional callback for each retry attempt
85
"""
86
def __init__(self, predicate=None, initial=1.0, maximum=60.0, multiplier=2.0, deadline=120.0, on_error=None): ...
87
88
def __call__(self, func): ...
89
def with_deadline(self, deadline): ...
90
def with_delay(self, initial=None, maximum=None, multiplier=None): ...
91
def with_predicate(self, predicate): ...
92
```
93
94
### Retry Utility Functions
95
96
Core retry mechanism and helper functions for implementing retry logic.
97
98
```python { .api }
99
def retry_target(target, predicate, sleep_generator, deadline=None, on_error=None):
100
"""
101
Call a function and retry on transient errors.
102
103
Args:
104
target (Callable): Function to call
105
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
106
sleep_generator: Iterator yielding sleep durations between retries
107
deadline (float, optional): Deadline for all retry attempts in seconds
108
on_error (Callable[[Exception], None], optional): Callback for each retry attempt
109
110
Returns:
111
Any: Result of successful target function call
112
113
Raises:
114
RetryError: When all retry attempts are exhausted
115
"""
116
117
async def retry_target_async(target, predicate, sleep_generator, deadline=None, on_error=None):
118
"""
119
Async version of retry_target.
120
121
Args:
122
target (Callable): Async function to call
123
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
124
sleep_generator: Iterator yielding sleep durations between retries
125
deadline (float, optional): Deadline for all retry attempts in seconds
126
on_error (Callable[[Exception], None], optional): Callback for each retry attempt
127
128
Returns:
129
Any: Result of successful target function call
130
131
Raises:
132
RetryError: When all retry attempts are exhausted
133
"""
134
135
def retry_target_stream(target, predicate, sleep_generator, deadline=None, on_error=None):
136
"""
137
Call a streaming function and retry on transient errors.
138
139
Args:
140
target (Callable): Streaming function to call
141
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
142
sleep_generator: Iterator yielding sleep durations between retries
143
deadline (float, optional): Deadline for all retry attempts in seconds
144
on_error (Callable[[Exception], None], optional): Callback for each retry attempt
145
146
Returns:
147
Iterator: Stream results from successful target function call
148
149
Raises:
150
RetryError: When all retry attempts are exhausted
151
"""
152
153
async def retry_target_stream_async(target, predicate, sleep_generator, deadline=None, on_error=None):
154
"""
155
Async version of retry_target_stream.
156
157
Args:
158
target (Callable): Async streaming function to call
159
predicate (Callable[[Exception], bool]): Function to determine if exception should trigger retry
160
sleep_generator: Iterator yielding sleep durations between retries
161
deadline (float, optional): Deadline for all retry attempts in seconds
162
on_error (Callable[[Exception], None], optional): Callback for each retry attempt
163
164
Returns:
165
AsyncIterator: Async stream results from successful target function call
166
167
Raises:
168
RetryError: When all retry attempts are exhausted
169
"""
170
```
171
172
### Sleep Generation and Predicates
173
174
Utilities for generating retry delays and determining retry conditions.
175
176
```python { .api }
177
def exponential_sleep_generator(initial_delay, maximum_delay, multiplier):
178
"""
179
Generate exponentially increasing sleep delays.
180
181
Args:
182
initial_delay (float): Initial delay in seconds
183
maximum_delay (float): Maximum delay in seconds
184
multiplier (float): Multiplier for exponential backoff
185
186
Yields:
187
float: Sleep duration in seconds for each retry attempt
188
"""
189
190
def if_exception_type(*exception_types):
191
"""
192
Create a predicate that returns True if exception is one of the specified types.
193
194
Args:
195
*exception_types: Exception classes to match
196
197
Returns:
198
Callable[[Exception], bool]: Predicate function
199
"""
200
201
def if_transient_error(exception):
202
"""
203
Predicate that returns True for transient errors that should be retried.
204
205
Args:
206
exception (Exception): Exception to check
207
208
Returns:
209
bool: True if exception represents a transient error
210
"""
211
212
def build_retry_error(exc_list, reason):
213
"""
214
Build a RetryError from a list of exceptions and failure reason.
215
216
Args:
217
exc_list (List[Exception]): List of exceptions encountered during retries
218
reason (RetryFailureReason): Reason for retry failure
219
220
Returns:
221
RetryError: Constructed retry error with exception history
222
"""
223
```
224
225
### Retry Failure Reasons
226
227
Enumeration of reasons why retry attempts failed.
228
229
```python { .api }
230
from enum import Enum
231
232
class RetryFailureReason(Enum):
233
"""Reasons why retry attempts failed."""
234
TIMEOUT = "timeout"
235
NON_RETRYABLE_ERROR = "non_retryable_error"
236
EMPTY_GENERATOR = "empty_generator"
237
```
238
239
## Usage Examples
240
241
### Basic Retry Configuration
242
243
```python
244
from google.api_core import retry
245
from google.api_core import exceptions
246
import requests
247
248
# Configure retry with exponential backoff
249
retry_config = retry.Retry(
250
predicate=retry.if_exception_type(
251
exceptions.InternalServerError,
252
exceptions.ServiceUnavailable,
253
exceptions.DeadlineExceeded
254
),
255
initial=1.0,
256
maximum=60.0,
257
multiplier=2.0,
258
deadline=300.0
259
)
260
261
@retry_config
262
def make_api_call():
263
response = requests.get("https://api.example.com/data")
264
if response.status_code >= 500:
265
raise exceptions.InternalServerError("Server error")
266
return response.json()
267
268
# Call with automatic retry
269
try:
270
data = make_api_call()
271
print("Success:", data)
272
except retry.RetryError as e:
273
print("All retry attempts failed:", e)
274
```
275
276
### Custom Retry Predicate
277
278
```python
279
from google.api_core import retry
280
from google.api_core import exceptions
281
282
def custom_predicate(exception):
283
"""Custom logic for determining if error should be retried."""
284
if isinstance(exception, exceptions.TooManyRequests):
285
return True
286
if isinstance(exception, exceptions.ServiceUnavailable):
287
return True
288
if isinstance(exception, ConnectionError):
289
return True
290
return False
291
292
retry_config = retry.Retry(
293
predicate=custom_predicate,
294
initial=2.0,
295
maximum=120.0,
296
deadline=600.0
297
)
298
299
@retry_config
300
def complex_operation():
301
# Operation that may fail with various errors
302
pass
303
```
304
305
### Async Retry Usage
306
307
```python
308
import asyncio
309
from google.api_core import retry
310
from google.api_core import exceptions
311
import aiohttp
312
313
async_retry_config = retry.AsyncRetry(
314
predicate=retry.if_exception_type(
315
exceptions.ServiceUnavailable,
316
aiohttp.ClientError
317
),
318
initial=1.0,
319
maximum=60.0,
320
multiplier=1.5
321
)
322
323
@async_retry_config
324
async def async_api_call():
325
async with aiohttp.ClientSession() as session:
326
async with session.get("https://api.example.com/data") as response:
327
if response.status >= 500:
328
raise exceptions.ServiceUnavailable("Server unavailable")
329
return await response.json()
330
331
# Use async retry
332
async def main():
333
try:
334
data = await async_api_call()
335
print("Success:", data)
336
except retry.RetryError as e:
337
print("Async retry failed:", e)
338
339
asyncio.run(main())
340
```
341
342
### Streaming Retry Usage
343
344
```python
345
from google.api_core import retry
346
from google.api_core import exceptions
347
348
streaming_retry = retry.StreamingRetry(
349
predicate=retry.if_exception_type(
350
exceptions.ServiceUnavailable,
351
ConnectionError
352
),
353
initial=0.5,
354
maximum=30.0,
355
deadline=180.0
356
)
357
358
@streaming_retry
359
def stream_data():
360
"""Generator function that yields data from a stream."""
361
# Simulate streaming API call that may fail
362
for i in range(100):
363
if i == 50: # Simulate transient error
364
raise exceptions.ServiceUnavailable("Temporary unavailable")
365
yield f"data_item_{i}"
366
367
# Use streaming retry
368
try:
369
for item in stream_data():
370
print(f"Received: {item}")
371
except retry.RetryError as e:
372
print("Streaming retry exhausted:", e)
373
```
374
375
### Using Retry Target Directly
376
377
```python
378
from google.api_core import retry
379
import time
380
381
def unreliable_function():
382
"""Function that fails randomly."""
383
import random
384
if random.random() < 0.7: # 70% failure rate
385
raise ConnectionError("Random failure")
386
return "Success!"
387
388
# Use retry_target directly without decorator
389
sleep_gen = retry.exponential_sleep_generator(1.0, 60.0, 2.0)
390
predicate = retry.if_exception_type(ConnectionError)
391
392
try:
393
result = retry.retry_target(
394
target=unreliable_function,
395
predicate=predicate,
396
sleep_generator=sleep_gen,
397
deadline=120.0,
398
on_error=lambda exc: print(f"Retry attempt failed: {exc}")
399
)
400
print("Final result:", result)
401
except retry.RetryError as e:
402
print("All retries exhausted:", e)
403
```