or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bidirectional-streaming.mdclient-config.mddatetime.mdexceptions.mdgapic-framework.mdiam-policies.mdindex.mdoperations.mdpage-iteration.mdpath-templates.mdprotobuf-helpers.mdretry.mdtimeout.mdtransport.mduniverse-domain.md

retry.mddocs/

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

```