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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2569 - (show 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 package dk.thoerup.circuitbreaker;
2
3
4 import java.util.concurrent.ExecutorService;
5 import java.util.concurrent.Executors;
6
7 import dk.thoerup.circuitbreaker.config.BreakerConfig;
8 import dk.thoerup.circuitbreaker.config.StaticConfig;
9 import dk.thoerup.circuitbreaker.notification.NotiferHelper;
10 import dk.thoerup.circuitbreaker.notification.Notifier;
11 import dk.thoerup.circuitbreaker.notification.NullNotifier;
12 import dk.thoerup.circuitbreaker.statistics.NullStatistics;
13 import dk.thoerup.circuitbreaker.statistics.Statistics;
14
15 /* 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
19 private CircuitBreaker cb = new CircuitBreaker("test", 5, 10000);
20 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
21 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 } catch (Exception e) {
43 logger.warning( e.getMessage() );
44 response.sendError(500);
45 return;
46 }
47
48 }
49 */
50
51
52 public class CircuitBreaker{
53
54 private volatile CircuitBreakerState currentState;
55
56 private final OpenState open = new OpenState();
57 private final HalfOpenState halfOpen = new HalfOpenState();
58 private final ClosedState closed = new ClosedState();
59
60 private String name;
61
62 private ExecutorService executor = null;
63 private Notifier notifier = new NullNotifier();
64 private Statistics stats = new NullStatistics();
65
66 @Deprecated
67 public CircuitBreaker(String name, int threshold, int timeoutMS) {
68 this(name, new StaticConfig(threshold, timeoutMS) );
69 }
70
71 public CircuitBreaker(String name, BreakerConfig config) {
72 closed.setThreshold(config);
73 open.setTimeout(config);
74
75 this.name = name;
76
77 //set correct intial state
78 internalReset();
79 }
80
81 public synchronized void shutdown() {
82 if (executor != null) {
83 executor.shutdown();
84 }
85 }
86
87
88 public Object invoke(CircuitInvocation invocation) throws Exception
89 {
90 stats.addStatistics(Event.Invocation);
91
92 Object result = null;
93 try
94 {
95 getState().preInvoke(this);
96 result = invocation.proceed();
97 getState().postInvoke(this);
98 }
99 catch(Exception e)
100 {
101 if (e instanceof CircuitBreakerException) {
102 stats.addStatistics(Event.InvocationBlocked);
103 } else {
104 stats.addStatistics(Event.InvocationFailure);
105 }
106
107 getState().onError(this, e);
108 throw e;
109 }
110 return result;
111 }
112
113 public void tripBreaker() {
114 commonTripBreaker(Event.BreakerTripped);
115 }
116
117 //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 commonTripBreaker(Event.BreakerRetripped);
120 }
121
122 private void commonTripBreaker(Event event) {
123 synchronized(this) {
124 if (currentState != open) { // TODO:Is this conditional necessary ??
125 open.trip();
126 currentState = open;
127
128 notifier.sendNotification(this, event);
129 stats.addStatistics(event);
130 }
131 }
132 }
133
134 public void attemptReset() {
135 synchronized(this) {
136 if (currentState != halfOpen) { // TODO:Is this conditional necessary ??
137 currentState = halfOpen;
138 notifier.sendNotification(this, Event.BreakerAttemptReset);
139 stats.addStatistics(Event.BreakerAttemptReset);
140 }
141 }
142
143 }
144
145 public void reset() {
146 synchronized(this) {
147 if (currentState != closed) { // TODO: Is this conditional necessary ??
148 internalReset();
149 notifier.sendNotification(this, Event.BreakerReset);
150 stats.addStatistics(Event.BreakerReset);
151 }
152 }
153 }
154
155 //This one actually sets the correct closed/reset state
156 private void internalReset() {
157 closed.resetFailureCount();
158 currentState = closed;
159 }
160
161
162 private CircuitBreakerState getState() {
163 synchronized(this) {
164 return currentState;
165 }
166 }
167
168 public boolean isClosed() {
169 return (getState() == closed);
170 }
171
172 public boolean isOpen() {
173 return (getState() == open);
174 }
175
176 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 public int getTimeout() {
189 return (int)open.getTimeout();
190 }
191
192 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
208 public void setNotifier(Notifier notifier) {
209 this.notifier = notifier;
210 }
211
212 public String getNotifierName() {
213 return NotiferHelper.getName(notifier);
214 }
215
216 public void setStatistics(Statistics newStats) {
217 this.stats = newStats;
218 }
219
220 public Statistics getStatistics() {
221 return this.stats;
222 }
223
224 public synchronized ExecutorService getExecutor() {
225
226 if (executor == null) {
227 executor = Executors.newFixedThreadPool(1);
228 }
229
230 return executor;
231
232 }
233
234 }

Properties

Name Value
svn:mergeinfo

  ViewVC Help
Powered by ViewVC 1.1.20