or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asynchronous-strategies.mdbulkhead-strategies.mdcircuit-breaker-strategies.mdconfiguration.mdfallback-strategies.mdindex.mdprogrammatic-api.mdrate-limiting-strategies.mdretry-strategies.mdtimeout-strategies.md

circuit-breaker-strategies.mddocs/

0

# Circuit Breaker Strategies

1

2

Circuit breaker patterns that prevent cascading failures by monitoring failure rates and temporarily blocking calls to failing services. Provides automatic failure detection, recovery mechanisms, and named circuit breaker instances for shared state.

3

4

## Capabilities

5

6

### Basic Circuit Breaker

7

8

Standard circuit breaker functionality with configurable failure thresholds, delays, and recovery logic.

9

10

```java { .api }

11

@CircuitBreaker(

12

requestVolumeThreshold = 20,

13

failureRatio = 0.5,

14

delay = 5000,

15

delayUnit = ChronoUnit.MILLISECONDS,

16

successThreshold = 1,

17

failOn = {IOException.class, TimeoutException.class},

18

skipOn = {IllegalArgumentException.class}

19

)

20

public ReturnType protectedMethod() throws Exception;

21

```

22

23

#### Parameters

24

25

- `requestVolumeThreshold` - Minimum requests before failure evaluation (default: 20)

26

- `failureRatio` - Failure ratio to open circuit (0.0-1.0, default: 0.5)

27

- `delay` - Time before transitioning from open to half-open (default: 5 seconds)

28

- `delayUnit` - Time unit for delay (default: MILLIS)

29

- `successThreshold` - Successful calls needed to close from half-open (default: 1)

30

- `failOn` - Exception types considered failures (default: Throwable.class)

31

- `skipOn` - Exception types not considered failures (takes precedence)

32

33

#### Circuit Breaker States

34

35

- **Closed**: Normal operation, calls pass through

36

- **Open**: Calls immediately fail without execution

37

- **Half-Open**: Test calls allowed to check service recovery

38

39

#### Usage Example

40

41

```java

42

@ApplicationScoped

43

public class PaymentService {

44

45

// Payment processing with circuit breaker

46

@CircuitBreaker(

47

requestVolumeThreshold = 10,

48

failureRatio = 0.3,

49

delay = 30000,

50

successThreshold = 3

51

)

52

@Fallback(fallbackMethod = "processPaymentOffline")

53

public PaymentResult processPayment(PaymentRequest request) throws PaymentException {

54

return paymentGateway.process(request);

55

}

56

57

public PaymentResult processPaymentOffline(PaymentRequest request) {

58

// Queue payment for later processing

59

return paymentQueue.enqueue(request);

60

}

61

62

// External service with aggressive circuit breaker

63

@CircuitBreaker(

64

requestVolumeThreshold = 5,

65

failureRatio = 0.2,

66

delay = 60000,

67

failOn = {ConnectException.class, SocketTimeoutException.class},

68

skipOn = {ValidationException.class}

69

)

70

public ExternalApiResponse callExternalService(ApiRequest request) {

71

return externalApiClient.call(request);

72

}

73

}

74

```

75

76

### Named Circuit Breakers

77

78

Named circuit breaker instances that share state across multiple methods or classes.

79

80

```java { .api }

81

@CircuitBreakerName("shared-circuit-breaker")

82

@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.4)

83

public ReturnType namedCircuitBreakerMethod();

84

85

// Multiple methods sharing the same circuit breaker state

86

@CircuitBreakerName("database-circuit")

87

public ReturnType firstDatabaseMethod();

88

89

@CircuitBreakerName("database-circuit")

90

public ReturnType secondDatabaseMethod();

91

```

92

93

#### Usage Example

94

95

```java

96

@ApplicationScoped

97

public class DatabaseService {

98

99

// All database operations share the same circuit breaker

100

@CircuitBreakerName("database-operations")

101

@CircuitBreaker(requestVolumeThreshold = 15, failureRatio = 0.3)

102

public List<User> findUsers(UserQuery query) throws SQLException {

103

return userRepository.find(query);

104

}

105

106

@CircuitBreakerName("database-operations")

107

@CircuitBreaker(requestVolumeThreshold = 15, failureRatio = 0.3)

108

public void saveUser(User user) throws SQLException {

109

userRepository.save(user);

110

}

111

112

@CircuitBreakerName("database-operations")

113

@CircuitBreaker(requestVolumeThreshold = 15, failureRatio = 0.3)

114

public void deleteUser(Long userId) throws SQLException {

115

userRepository.delete(userId);

116

}

117

}

118

119

@ApplicationScoped

120

public class OrderService {

121

122

// Order service also uses the same database circuit breaker

123

@CircuitBreakerName("database-operations")

124

@CircuitBreaker(requestVolumeThreshold = 15, failureRatio = 0.3)

125

public List<Order> findOrders(OrderQuery query) throws SQLException {

126

return orderRepository.find(query);

127

}

128

}

129

```

130

131

### Circuit Breaker with Fallback

132

133

Combined circuit breaker and fallback patterns for complete resilience.

134

135

```java { .api }

136

@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5)

137

@Fallback(fallbackMethod = "fallbackMethod")

138

public ReturnType protectedMethodWithFallback();

139

140

@CircuitBreaker(requestVolumeThreshold = 5)

141

@Fallback(value = CustomFallbackHandler.class)

142

public ReturnType protectedMethodWithHandler();

143

```

144

145

#### Usage Example

146

147

```java

148

@ApplicationScoped

149

public class WeatherService {

150

151

@Inject

152

CacheService cache;

153

154

// Weather API with circuit breaker and cached fallback

155

@CircuitBreaker(

156

requestVolumeThreshold = 8,

157

failureRatio = 0.4,

158

delay = 20000

159

)

160

@Fallback(fallbackMethod = "getCachedWeather")

161

@Timeout(5000)

162

public WeatherData getCurrentWeather(String city) throws WeatherServiceException {

163

return weatherApiClient.getWeather(city);

164

}

165

166

public WeatherData getCachedWeather(String city) {

167

WeatherData cached = cache.get("weather:" + city);

168

if (cached != null) {

169

return cached.withStaleIndicator();

170

}

171

return WeatherData.unavailable(city);

172

}

173

174

// Stock quote service with handler-based fallback

175

@CircuitBreaker(requestVolumeThreshold = 5, failureRatio = 0.6)

176

@Fallback(value = StockQuoteFallbackHandler.class)

177

public StockQuote getStockQuote(String symbol) throws QuoteServiceException {

178

return stockApiClient.getQuote(symbol);

179

}

180

}

181

182

public class StockQuoteFallbackHandler implements FallbackHandler<StockQuote> {

183

184

@Inject

185

HistoricalDataService historicalData;

186

187

@Override

188

public StockQuote handle(ExecutionContext context) {

189

String symbol = (String) context.getParameters()[0];

190

// Return last known quote or estimated quote

191

return historicalData.getLastKnownQuote(symbol)

192

.orElse(StockQuote.estimated(symbol));

193

}

194

}

195

```

196

197

### Circuit Breaker Monitoring

198

199

Integration with metrics and health checks for circuit breaker monitoring.

200

201

```java { .api }

202

// Circuit breaker with custom name for monitoring

203

@CircuitBreakerName("payment-gateway")

204

@CircuitBreaker(requestVolumeThreshold = 20, failureRatio = 0.25)

205

public PaymentResult processPayment(PaymentRequest request);

206

207

// Accessing circuit breaker state programmatically

208

CircuitBreakerRegistry registry;

209

CircuitBreaker circuitBreaker = registry.circuitBreaker("payment-gateway");

210

CircuitBreaker.State state = circuitBreaker.getState();

211

```

212

213

#### Usage Example

214

215

```java

216

@ApplicationScoped

217

public class SystemHealthService {

218

219

@Inject

220

CircuitBreakerRegistry circuitBreakerRegistry;

221

222

@Inject

223

MeterRegistry meterRegistry;

224

225

public HealthCheckResponse checkCircuitBreakerHealth() {

226

List<String> openCircuits = new ArrayList<>();

227

228

// Check all named circuit breakers

229

for (String name : circuitBreakerRegistry.getAllCircuitBreakerNames()) {

230

CircuitBreaker cb = circuitBreakerRegistry.circuitBreaker(name);

231

if (cb.getState() == CircuitBreaker.State.OPEN) {

232

openCircuits.add(name);

233

}

234

}

235

236

if (openCircuits.isEmpty()) {

237

return HealthCheckResponse.up("circuit-breakers")

238

.withData("status", "All circuit breakers closed")

239

.build();

240

} else {

241

return HealthCheckResponse.down("circuit-breakers")

242

.withData("open-circuits", openCircuits)

243

.build();

244

}

245

}

246

247

@EventObserver

248

public void onCircuitBreakerStateChange(CircuitBreakerStateChangeEvent event) {

249

// Record metrics when circuit breaker state changes

250

Counter counter = Counter.builder("circuit.breaker.state.changes")

251

.tag("name", event.getCircuitBreakerName())

252

.tag("from", event.getFromState().toString())

253

.tag("to", event.getToState().toString())

254

.register(meterRegistry);

255

256

counter.increment();

257

}

258

}

259

```

260

261

### Advanced Circuit Breaker Patterns

262

263

Complex patterns combining circuit breakers with other fault tolerance strategies.

264

265

#### Retry with Circuit Breaker

266

267

```java { .api }

268

@Retry(maxRetries = 3, delay = 1000)

269

@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5)

270

@Timeout(5000)

271

public ReturnType resilientMethod();

272

```

273

274

#### Bulkhead with Circuit Breaker

275

276

```java { .api }

277

@Bulkhead(value = 5, waitingTaskQueue = 10)

278

@CircuitBreaker(requestVolumeThreshold = 15, failureRatio = 0.4)

279

public ReturnType isolatedMethod();

280

```

281

282

#### Usage Example

283

284

```java

285

@ApplicationScoped

286

public class CriticalService {

287

288

// Maximum resilience combination

289

@Retry(maxRetries = 2, delay = 500)

290

@CircuitBreaker(

291

requestVolumeThreshold = 12,

292

failureRatio = 0.3,

293

delay = 45000

294

)

295

@Timeout(8000)

296

@Fallback(fallbackMethod = "criticalFallback")

297

@Bulkhead(value = 3)

298

public CriticalData performCriticalOperation(String operationId) throws Exception {

299

return criticalSystemClient.execute(operationId);

300

}

301

302

public CriticalData criticalFallback(String operationId) {

303

// Emergency fallback - might return cached data or trigger manual process

304

return emergencyDataSource.getCriticalData(operationId);

305

}

306

}

307

```

308

309

## Types

310

311

### Circuit Breaker Core Types

312

313

```java { .api }

314

// Circuit breaker states

315

enum CircuitBreakerState {

316

CLOSED, // Normal operation

317

OPEN, // Calls blocked

318

HALF_OPEN // Testing recovery

319

}

320

321

// Circuit breaker registry for programmatic access

322

interface CircuitBreakerRegistry {

323

CircuitBreaker circuitBreaker(String name);

324

Set<String> getAllCircuitBreakerNames();

325

}

326

327

// Circuit breaker instance

328

interface CircuitBreaker {

329

State getState();

330

Metrics getMetrics();

331

String getName();

332

333

enum State {

334

CLOSED, OPEN, HALF_OPEN, DISABLED, FORCED_OPEN

335

}

336

}

337

```

338

339

### Circuit Breaker Metrics

340

341

```java { .api }

342

// Circuit breaker metrics

343

interface CircuitBreakerMetrics {

344

int getNumberOfSuccessfulCalls();

345

int getNumberOfFailedCalls();

346

int getNumberOfBufferedCalls();

347

int getNumberOfSlowCalls();

348

float getFailureRate();

349

float getSlowCallRate();

350

Duration getSlowCallRateThreshold();

351

}

352

```

353

354

### Event Types

355

356

```java { .api }

357

// Circuit breaker events for monitoring

358

interface CircuitBreakerEvent {

359

String getCircuitBreakerName();

360

ZonedDateTime getCreationTime();

361

362

enum Type {

363

SUCCESS, ERROR, IGNORED_ERROR, STATE_TRANSITION,

364

RESET, DISABLED, FORCED_OPEN_STATE

365

}

366

}

367

368

// State change event

369

interface CircuitBreakerStateChangeEvent extends CircuitBreakerEvent {

370

CircuitBreaker.State getFromState();

371

CircuitBreaker.State getToState();

372

}

373

```