-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path39.DesignACircuitBreakerSystem.java
More file actions
146 lines (122 loc) · 5.38 KB
/
39.DesignACircuitBreakerSystem.java
File metadata and controls
146 lines (122 loc) · 5.38 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* --------------------- CIRCUIT BREAKER (JAVA DEMO) --------------------------
Fully self-contained, no DB, runnable in VS Code.
Includes line-by-line explanation for YouTube teaching.
---------------------------------------------------------------------------- */
import java.util.function.Supplier;
// ----------------------------------------
// 1. Enum representing the 3 states
// ----------------------------------------
enum State {
CLOSED, // Normal state
OPEN, // Reject calls
HALF_OPEN // Allow one test call
}
// ----------------------------------------
// 2. Circuit Breaker Implementation
// ----------------------------------------
class CircuitBreaker {
private final int failureThreshold; // Number of failures allowed
private final long recoveryTimeoutMillis; // Time before trying HALF-OPEN
private int failureCount = 0; // Track failures
private State currentState = State.CLOSED; // Start in CLOSED
private long lastFailureTime = 0; // Track when OPEN occurred
// Constructor
public CircuitBreaker(int failureThreshold, long recoveryTimeoutMillis) {
this.failureThreshold = failureThreshold; // Set allowed failures
this.recoveryTimeoutMillis = recoveryTimeoutMillis; // Cooldown time
}
// ----------------------------------------
// 3. Move to OPEN state
// ----------------------------------------
private synchronized void moveToOpen() {
currentState = State.OPEN; // Change state to OPEN
lastFailureTime = System.currentTimeMillis(); // Record time of failure
System.out.println("➡️ STATE CHANGE → OPEN");
}
// ----------------------------------------
// 4. Move to HALF-OPEN state
// ----------------------------------------
private synchronized void moveToHalfOpen() {
currentState = State.HALF_OPEN; // Move to HALF-OPEN
System.out.println("➡️ STATE CHANGE → HALF-OPEN");
}
// ----------------------------------------
// 5. Move to CLOSED state
// ----------------------------------------
private synchronized void moveToClosed() {
currentState = State.CLOSED; // Reset to CLOSED
failureCount = 0; // Reset failures
System.out.println("➡️ STATE CHANGE → CLOSED");
}
// ----------------------------------------
// 6. Should we allow the call?
// ----------------------------------------
private synchronized boolean canPass() {
if (currentState == State.CLOSED) {
return true; // Normal operation
}
if (currentState == State.OPEN) {
long now = System.currentTimeMillis(); // Check time
if (now - lastFailureTime >= recoveryTimeoutMillis) {
moveToHalfOpen(); // Try HALF-OPEN
return true;
}
return false; // Still OPEN
}
return true; // HALF-OPEN → allow exactly one call
}
// ----------------------------------------
// 7. The main call wrapper
// ----------------------------------------
public synchronized String call(Supplier<String> externalService) {
if (!canPass()) { // If OPEN → block
System.out.println("❌ Request BLOCKED (OPEN)");
return "BLOCKED";
}
try {
String result = externalService.get(); // Execute service
if (currentState == State.HALF_OPEN) { // If test succeeded
moveToClosed();
}
failureCount = 0; // Reset failure count
return result; // Return success
} catch (Exception e) {
failureCount++; // Track failure
System.out.println("⚠️ Failure #" + failureCount);
if (failureCount >= failureThreshold) { // Exceeded limit?
moveToOpen();
}
return "ERROR: " + e.getMessage(); // Return error
}
}
}
// ----------------------------------------
// 8. Simulated external service
// ----------------------------------------
class FlakyService {
private int counter = 0; // fails first 3 times
public String execute() {
counter++;
if (counter <= 3) {
throw new RuntimeException("Service Down"); // Fail first 3 calls
}
return "SUCCESS"; // After that → success
}
}
// ----------------------------------------
// 9. DEMO main function
// ----------------------------------------
public class Main {
public static void main(String[] args) throws Exception {
CircuitBreaker cb = new CircuitBreaker(3, 3000); // 3 failures, 3 secs
FlakyService service = new FlakyService(); // Create test service
System.out.println("\n----- DEMO START -----\n");
for (int i = 1; i <= 8; i++) {
System.out.print("Call " + i + " → ");
String result = cb.call(() -> service.execute());
System.out.println(result);
Thread.sleep(1000); // 1 second interval
}
System.out.println("\n----- DEMO END -----");
}
}