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

Properties

Name Value
svn:mergeinfo

  ViewVC Help
Powered by ViewVC 1.1.20