/[projects]/miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java
ViewVC logotype

Annotation of /miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3212 - (hide annotations) (download)
Thu Dec 28 09:34:47 2017 UTC (6 years, 5 months ago) by torben
File size: 5631 byte(s)
Use generics to encapsulate returned value
1 torben 467 package dk.thoerup.circuitbreaker;
2 torben 393
3    
4 torben 1148 import java.util.concurrent.ExecutorService;
5     import java.util.concurrent.Executors;
6    
7 torben 1306 import dk.thoerup.circuitbreaker.config.BreakerConfig;
8 torben 1289 import dk.thoerup.circuitbreaker.notification.NotiferHelper;
9 torben 467 import dk.thoerup.circuitbreaker.notification.Notifier;
10     import dk.thoerup.circuitbreaker.notification.NullNotifier;
11 torben 2569 import dk.thoerup.circuitbreaker.statistics.NullStatistics;
12     import dk.thoerup.circuitbreaker.statistics.Statistics;
13 torben 409
14 torben 394 /* Simple CircuitBreaker implementation - snipped from http://www.jroller.com/kenwdelong/entry/circuit_breaker_in_java
15     *
16     * example of how it can be used
17 torben 395
18 torben 3212 private CircuitBreaker<String> cb = new CircuitBreaker<>("test", 5, 10000);
19 torben 395 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
20 torben 3212 class TestInvocation implements CircuitInvocation<String> {
21 torben 393 String url;
22     public TestInvocation(String url) {
23     this.url = url;
24     }
25 torben 3212 public String proceed() throws Exception{
26 torben 393
27     URL u = new URL(url);
28     URLConnection c = u.openConnection();
29     c.connect();
30     InputStream in = c.getInputStream();
31     in.close();
32    
33    
34     return "hello";
35     }
36    
37     }
38     try {
39 torben 3212 String s = cb.invoke(new TestInvocation("http://rafiki/test"));
40 torben 393 response.getWriter().print(s);
41 torben 452 } catch (Exception e) {
42 torben 393 logger.warning( e.getMessage() );
43     response.sendError(500);
44     return;
45     }
46    
47     }
48     */
49    
50    
51 torben 3212 public class CircuitBreaker<T>{
52 torben 393
53 torben 443 private volatile CircuitBreakerState currentState;
54 torben 393
55 torben 424 private final OpenState open = new OpenState();
56     private final HalfOpenState halfOpen = new HalfOpenState();
57     private final ClosedState closed = new ClosedState();
58 torben 393
59     private String name;
60    
61 torben 1148 private ExecutorService executor = null;
62 torben 409 private Notifier notifier = new NullNotifier();
63 torben 2569 private Statistics stats = new NullStatistics();
64 torben 409
65 torben 1306
66     public CircuitBreaker(String name, BreakerConfig config) {
67     closed.setThreshold(config);
68     open.setTimeout(config);
69 torben 393
70     this.name = name;
71 torben 625
72 torben 627 //set correct intial state
73     internalReset();
74 torben 393 }
75    
76 torben 1148 public synchronized void shutdown() {
77     if (executor != null) {
78     executor.shutdown();
79     }
80     }
81 torben 393
82 torben 1148
83 torben 3212 public T invoke(CircuitInvocation<T> invocation) throws Exception
84 torben 393 {
85 torben 2569 stats.addStatistics(Event.Invocation);
86    
87 torben 3212 T result = null;
88 torben 393 try
89     {
90     getState().preInvoke(this);
91     result = invocation.proceed();
92     getState().postInvoke(this);
93     }
94 torben 450 catch(Exception e)
95 torben 2569 {
96     if (e instanceof CircuitBreakerException) {
97     stats.addStatistics(Event.InvocationBlocked);
98     } else {
99     stats.addStatistics(Event.InvocationFailure);
100     }
101    
102 torben 450 getState().onError(this, e);
103     throw e;
104 torben 393 }
105     return result;
106     }
107    
108     public void tripBreaker() {
109 torben 2569 commonTripBreaker(Event.BreakerTripped);
110 torben 393 }
111    
112 torben 864 //a re-trip should basically do the same as a normal trip, but it is here just to differentiate the two different events
113     public void retripBreaker() {
114 torben 2569 commonTripBreaker(Event.BreakerRetripped);
115 torben 871 }
116    
117 torben 2569 private void commonTripBreaker(Event event) {
118 torben 871 synchronized(this) {
119 torben 864 if (currentState != open) { // TODO:Is this conditional necessary ??
120     open.trip();
121     currentState = open;
122    
123 torben 1161 notifier.sendNotification(this, event);
124 torben 2569 stats.addStatistics(event);
125 torben 864 }
126 torben 871 }
127 torben 864 }
128    
129 torben 393 public void attemptReset() {
130     synchronized(this) {
131 torben 426 if (currentState != halfOpen) { // TODO:Is this conditional necessary ??
132     currentState = halfOpen;
133 torben 2569 notifier.sendNotification(this, Event.BreakerAttemptReset);
134     stats.addStatistics(Event.BreakerAttemptReset);
135 torben 426 }
136 torben 393 }
137 torben 409
138 torben 393 }
139    
140     public void reset() {
141     synchronized(this) {
142 torben 426 if (currentState != closed) { // TODO: Is this conditional necessary ??
143 torben 627 internalReset();
144 torben 2569 notifier.sendNotification(this, Event.BreakerReset);
145     stats.addStatistics(Event.BreakerReset);
146 torben 426 }
147 torben 393 }
148     }
149    
150 torben 627 //This one actually sets the correct closed/reset state
151     private void internalReset() {
152     closed.resetFailureCount();
153     currentState = closed;
154     }
155 torben 397
156 torben 627
157 torben 393 private CircuitBreakerState getState() {
158     synchronized(this) {
159     return currentState;
160     }
161     }
162 torben 397
163 torben 447 public boolean isClosed() {
164     return (getState() == closed);
165     }
166    
167     public boolean isOpen() {
168     return (getState() == open);
169     }
170    
171 torben 397 public String getName() {
172     return name;
173     }
174    
175     public String getStateName() {
176     return getState().getName();
177     }
178    
179     public int getThreshold() {
180     return closed.getThreshold();
181     }
182    
183 torben 413 public int getTimeout() {
184     return (int)open.getTimeout();
185     }
186    
187 torben 397 public int getFailureCount() {
188     if (getState() == closed) {
189     return closed.getFailureCount();
190     } else {
191     return -1;
192     }
193     }
194    
195     public long getElapsed() {
196     if (getState() == open) {
197     return open.getElapsed();
198     } else {
199     return -1;
200     }
201     }
202 torben 409
203     public void setNotifier(Notifier notifier) {
204 torben 2572 synchronized(this) {
205     this.notifier = notifier;
206     }
207 torben 409 }
208    
209 torben 1289 public String getNotifierName() {
210     return NotiferHelper.getName(notifier);
211 torben 409 }
212 torben 1148
213 torben 2569 public void setStatistics(Statistics newStats) {
214     this.stats = newStats;
215     }
216    
217     public Statistics getStatistics() {
218     return this.stats;
219     }
220    
221 torben 1148 public synchronized ExecutorService getExecutor() {
222    
223     if (executor == null) {
224     executor = Executors.newFixedThreadPool(1);
225     }
226    
227     return executor;
228    
229     }
230 torben 397
231 torben 393 }

Properties

Name Value
svn:mergeinfo

  ViewVC Help
Powered by ViewVC 1.1.20